Routers

    A router is in charge of connecting incoming requests to the services that can handle them. In the process, routers may use pieces of middleware to update the request, or act before forwarding the request to the service.

    Requests /foo are Handled by service-foo — Using the

    YAML

    TOML

    1. ## Dynamic configuration
    2. [http.routers]
    3. [http.routers.my-router]
    4. rule = "Path(`/foo`)"
    5. service = "service-foo"

    Forwarding all (non-tls) requests on port 3306 to a database service

    Dynamic Configuration

    File (YAML)

    1. ## Dynamic configuration
    2. tcp:
    3. routers:
    4. to-database:
    5. entryPoints:
    6. - "mysql"
    7. # Catch every request (only available rule for non-tls routers. See below.)
    8. rule: "HostSNI(`*`)"
    9. service: database

    File (TOML)

    1. ## Dynamic configuration
    2. [tcp]
    3. [tcp.routers]
    4. [tcp.routers.to-database]
    5. entryPoints = ["mysql"]
    6. # Catch every request (only available rule for non-tls routers. See below.)
    7. rule = "HostSNI(`*`)"
    8. service = "database"

    Static Configuration

    File (YAML)

    1. ## Static configuration
    2. entryPoints:
    3. web:
    4. address: ":80"
    5. mysql:
    6. address: ":3306"

    File (TOML)

    1. ## Static configuration
    2. [entryPoints]
    3. [entryPoints.web]
    4. address = ":80"
    5. [entryPoints.mysql]
    6. address = ":3306"

    CLI

    1. ## Static configuration
    2. --entryPoints.web.address=:80
    3. --entryPoints.mysql.address=:3306

    The character @ is not authorized in the router name

    If not specified, HTTP routers will accept requests from all defined entry points. If you want to limit the router scope to a set of entry points, set the entryPoints option.

    Listens to Every EntryPoint

    Dynamic Configuration

    File (YAML)

    1. ## Dynamic configuration
    2. http:
    3. routers:
    4. Router-1:
    5. # By default, routers listen to every entry points
    6. rule: "Host(`example.com`)"
    7. service: "service-1"

    File (TOML)

    1. ## Dynamic configuration
    2. [http.routers]
    3. [http.routers.Router-1]
    4. # By default, routers listen to every entry points
    5. rule = "Host(`example.com`)"
    6. service = "service-1"

    Static Configuration

    File (YAML)

    1. ## Static configuration
    2. entryPoints:
    3. web:
    4. address: ":80"
    5. websecure:
    6. address: ":443"
    7. other:
    8. address: ":9090"

    File (TOML)

    1. ## Static configuration
    2. [entryPoints]
    3. [entryPoints.web]
    4. address = ":80"
    5. [entryPoints.websecure]
    6. address = ":443"
    7. [entryPoints.other]
    8. address = ":9090"

    CLI

    1. ## Static configuration
    2. --entrypoints.web.address=:80
    3. --entrypoints.websecure.address=:443
    4. --entrypoints.other.address=:9090

    Listens to Specific EntryPoints

    Dynamic Configuration

    File (YAML)

    1. ## Dynamic configuration
    2. http:
    3. routers:
    4. Router-1:
    5. # won't listen to entry point web
    6. entryPoints:
    7. - "websecure"
    8. - "other"
    9. rule: "Host(`example.com`)"
    10. service: "service-1"

    File (TOML)

    1. ## Dynamic configuration
    2. [http.routers]
    3. [http.routers.Router-1]
    4. # won't listen to entry point web
    5. entryPoints = ["websecure", "other"]
    6. rule = "Host(`example.com`)"
    7. service = "service-1"

    Static Configuration

    File (YAML)

    1. ## Static configuration
    2. entryPoints:
    3. web:
    4. address: ":80"
    5. websecure:
    6. address: ":443"
    7. other:
    8. address: ":9090"

    File (TOML)

    1. ## Static configuration
    2. [entryPoints]
    3. [entryPoints.web]
    4. address = ":80"
    5. [entryPoints.websecure]
    6. address = ":443"
    7. [entryPoints.other]
    8. address = ":9090"

    CLI

    1. ## Static configuration
    2. --entrypoints.web.address=:80
    3. --entrypoints.websecure.address=:443
    4. --entrypoints.other.address=:9090

    Rule

    Rules are a set of matchers configured with values, that determine if a particular request matches specific criteria. If the rule is verified, the router becomes active, calls middlewares, and then forwards the request to the service.

    Backticks or Quotes?

    To set the value of a rule, use ` or escaped double-quotes \".

    Single quotes ' are not accepted as values are Golang’s String Literals.

    Host is example.com

    1. rule = "Host(`example.com`)"

    Host is example.com OR Host is example.org AND path is /traefik

    1. rule = "Host(`example.com`) || (Host(`example.org`) && Path(`/traefik`))"

    The table below lists all the available matchers:

    Non-ASCII Domain Names

    Non-ASCII characters are not supported in Host and HostRegexp expressions, and by doing so the associated router will be invalid. For the Host expression, domain names containing non-ASCII characters must be provided as punycode encoded values (). As well, when using the HostRegexp expressions, in order to match domain names containing non-ASCII characters, the regular expression should match a punycode encoded domain name.

    Regexp Syntax

    HostRegexp, PathPrefix, and Path accept an expression with zero or more groups enclosed by curly braces, which are called named regexps. Named regexps, of the form {name:regexp}, are the only expressions considered for regexp matching. The regexp name (name in the above example) is an arbitrary value, that exists only for historical reasons.

    Any regexp supported by Go’s regexp package may be used.

    Combining Matchers Using Operators and Parenthesis

    You can combine multiple matchers using the AND (&&) and OR (||) operators. You can also use parenthesis.

    Invert a matcher

    You can invert a matcher by using the ! operator.

    Rule, Middleware, and Services

    The rule is evaluated “before” any middleware has the opportunity to work, and “before” the request is forwarded to the service.

    Path Vs PathPrefix

    Use Path if your service listens on the exact path only. For instance, Path: /products would match /products but not /products/shoes.

    Use a *Prefix* matcher if your service listens on a particular base path but also serves requests on sub-paths. For instance, PathPrefix: /products would match /products but also /products/shoes and /products/shirts. Since the path is forwarded as-is, your service is expected to listen on /products.

    ClientIP matcher

    The ClientIP matcher will only match the request client IP and does not use the X-Forwarded-For header for matching.

    Priority

    To avoid path overlap, routes are sorted, by default, in descending order using rules length. The priority is directly equal to the length of the rule, and so the longest length has the highest priority.

    A value of 0 for the priority is ignored: priority = 0 means that the default rules length sorting is used.

    How default priorities are computed

    File (YAML)

    1. ## Dynamic configuration
    2. http:
    3. routers:
    4. Router-1:
    5. rule: "HostRegexp(`.*\.traefik\.com`)"
    6. # ...
    7. Router-2:
    8. rule: "Host(`foobar.traefik.com`)"
    9. # ...

    File (TOML)

    1. ## Dynamic configuration
    2. [http.routers]
    3. [http.routers.Router-1]
    4. rule = "HostRegexp(`.*\.traefik\.com`)"
    5. # ...
    6. [http.routers.Router-2]
    7. rule = "Host(`foobar.traefik.com`)"
    8. # ...

    In this case, all requests with host foobar.traefik.com will be routed through Router-1 instead of Router-2.

    The previous table shows that Router-1 has a higher priority than Router-2.

    To solve this issue, the priority must be set.

    File (YAML)

    1. ## Dynamic configuration
    2. http:
    3. routers:
    4. Router-1:
    5. rule: "HostRegexp(`.*\.traefik\.com`)"
    6. entryPoints:
    7. - "web"
    8. service: service-1
    9. priority: 1
    10. Router-2:
    11. rule: "Host(`foobar.traefik.com`)"
    12. entryPoints:
    13. - "web"
    14. priority: 2
    15. service: service-2

    File (TOML)

    1. ## Dynamic configuration
    2. [http.routers]
    3. [http.routers.Router-1]
    4. rule = "HostRegexp(`.*\.traefik\.com`)"
    5. service = "service-1"
    6. priority = 1
    7. [http.routers.Router-2]
    8. rule = "Host(`foobar.traefik.com`)"
    9. entryPoints = ["web"]
    10. priority = 2
    11. service = "service-2"

    In this configuration, the priority is configured to allow Router-2 to handle requests with the foobar.traefik.com host.

    Middlewares

    You can attach a list of to each HTTP router. The middlewares will take effect only if the rule matches, and before forwarding the request to the service.

    The character @ is not authorized in the middleware name.

    Middlewares order

    Middlewares are applied in the same order as their declaration in router.

    With a middleware — using the

    YAML

    TOML

    1. ## Dynamic configuration
    2. [http.routers]
    3. [http.routers.my-router]
    4. rule = "Path(`/foo`)"
    5. # declared elsewhere
    6. middlewares = ["authentication"]
    7. service = "service-foo"

    Service

    Each request must eventually be handled by a , which is why each router definition should include a service target, which is basically where the request will be passed along to.

    In general, a service assigned to a router should have been defined, but there are exceptions for label-based providers. See the specific docker, , or marathon documentation.

    The character @ is not authorized in the service name.

    HTTP routers can only target HTTP services (not TCP services).

    General

    When a TLS section is specified, it instructs Traefik that the current router is dedicated to HTTPS requests only (and that the router should ignore HTTP (non TLS) requests). Traefik will terminate the SSL connections (meaning that it will send decrypted data to the services).

    Configuring the router to accept HTTPS requests only

    File (YAML)

    1. ## Dynamic configuration
    2. http:
    3. routers:
    4. Router-1:
    5. rule: "Host(`foo-domain`) && Path(`/foo-path/`)"
    6. service: service-id
    7. # will terminate the TLS request
    8. tls: {}

    File (TOML)

    1. ## Dynamic configuration
    2. [http.routers]
    3. rule = "Host(`foo-domain`) && Path(`/foo-path/`)"
    4. service = "service-id"
    5. # will terminate the TLS request
    6. [http.routers.Router-1.tls]

    Routers for HTTP & HTTPS

    If you need to define the same route for both HTTP and HTTPS requests, you will need to define two different routers: one with the tls section, one without.

    HTTP & HTTPS routes

    File (YAML)

    1. ## Dynamic configuration
    2. http:
    3. routers:
    4. my-https-router:
    5. rule: "Host(`foo-domain`) && Path(`/foo-path/`)"
    6. service: service-id
    7. # will terminate the TLS request
    8. tls: {}
    9. my-http-router:
    10. rule: "Host(`foo-domain`) && Path(`/foo-path/`)"
    11. service: service-id

    File (TOML)

    1. ## Dynamic configuration
    2. [http.routers]
    3. [http.routers.my-https-router]
    4. rule = "Host(`foo-domain`) && Path(`/foo-path/`)"
    5. service = "service-id"
    6. # will terminate the TLS request
    7. [http.routers.my-https-router.tls]
    8. [http.routers.my-http-router]
    9. rule = "Host(`foo-domain`) && Path(`/foo-path/`)"
    10. service = "service-id"

    options

    The options field enables fine-grained control of the TLS parameters. It refers to a and will be applied only if a Host rule is defined.

    Server Name Association

    Even though one might get the impression that a TLS options reference is mapped to a router, or a router rule, one should realize that it is actually mapped only to the host name found in the Host part of the rule. Of course, there could also be several Host parts in a rule, in which case the TLS options reference would be mapped to as many host names.

    Another thing to keep in mind is: the TLS option is picked from the mapping mentioned above and based on the server name provided during the TLS handshake, and it all happens before routing actually occurs.

    Domain Fronting

    In the case of domain fronting, if the TLS options associated with the Host Header and the SNI are different then Traefik will respond with a status code 421.

    Configuring the TLS options

    File (YAML)

    1. ## Dynamic configuration
    2. http:
    3. routers:
    4. Router-1:
    5. rule: "Host(`foo-domain`) && Path(`/foo-path/`)"
    6. service: service-id
    7. # will terminate the TLS request
    8. tls:
    9. options: foo
    10. tls:
    11. options:
    12. foo:
    13. minVersion: VersionTLS12
    14. cipherSuites:
    15. - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    16. - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
    17. - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
    18. - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
    19. - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

    File (TOML)

    1. ## Dynamic configuration
    2. [http.routers]
    3. [http.routers.Router-1]
    4. rule = "Host(`foo-domain`) && Path(`/foo-path/`)"
    5. service = "service-id"
    6. # will terminate the TLS request
    7. [http.routers.Router-1.tls]
    8. options = "foo"
    9. [tls.options]
    10. [tls.options.foo]
    11. minVersion = "VersionTLS12"
    12. cipherSuites = [
    13. "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
    14. "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
    15. "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
    16. "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
    17. "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
    18. ]

    Conflicting TLS Options

    Since a TLS options reference is mapped to a host name, if a configuration introduces a situation where the same host name (from a Host rule) gets matched with two TLS options references, a conflict occurs, such as in the example below:

    File (YAML)

    1. ## Dynamic configuration
    2. http:
    3. routers:
    4. routerfoo:
    5. rule: "Host(`snitest.com`) && Path(`/foo`)"
    6. tls:
    7. options: foo
    8. routerbar:
    9. rule: "Host(`snitest.com`) && Path(`/bar`)"
    10. tls:
    11. options: bar

    File (TOML)

    1. ## Dynamic configuration
    2. [http.routers]
    3. [http.routers.routerfoo]
    4. rule = "Host(`snitest.com`) && Path(`/foo`)"
    5. [http.routers.routerfoo.tls]
    6. options = "foo"
    7. [http.routers]
    8. [http.routers.routerbar]
    9. rule = "Host(`snitest.com`) && Path(`/bar`)"
    10. [http.routers.routerbar.tls]
    11. options = "bar"

    If that happens, both mappings are discarded, and the host name (snitest.com in this case) for these routers gets associated with the default TLS options instead.

    certResolver

    If certResolver is defined, Traefik will try to generate certificates based on routers Host & HostSNI rules.

    File (YAML)

    1. ## Dynamic configuration
    2. http:
    3. routers:
    4. routerfoo:
    5. rule: "Host(`snitest.com`) && Path(`/foo`)"
    6. tls:
    7. certResolver: foo

    File (TOML)

    1. ## Dynamic configuration
    2. [http.routers]
    3. [http.routers.routerfoo]
    4. rule = "Host(`snitest.com`) && Path(`/foo`)"
    5. [http.routers.routerfoo.tls]
    6. certResolver = "foo"

    Multiple Hosts in a Rule

    The rule Host(`test1.example.com`,`test2.example.com`) will request a certificate with the main domain test1.example.com and SAN test2.example.com.

    domains

    You can set SANs (alternative domains) for each main domain. Every domain must have A/AAAA records pointing to Traefik. Each domain & SAN will lead to a certificate request.

    File (YAML)

    1. ## Dynamic configuration
    2. http:
    3. routers:
    4. routerbar:
    5. rule: "Host(`snitest.com`) && Path(`/bar`)"
    6. tls:
    7. certResolver: "bar"
    8. domains:
    9. - main: "snitest.com"
    10. sans:
    11. - "*.snitest.com"

    File (TOML)

    1. ## Dynamic configuration
    2. [http.routers]
    3. [http.routers.routerbar]
    4. rule = "Host(`snitest.com`) && Path(`/bar`)"
    5. [http.routers.routerbar.tls]
    6. certResolver = "bar"
    7. [[http.routers.routerbar.tls.domains]]
    8. main = "snitest.com"
    9. sans = ["*.snitest.com"]

    ACME v2 supports wildcard certificates. As described in wildcard certificates can only be generated through a DNS-01 challenge.

    Most likely the root domain should receive a certificate too, so it needs to be specified as SAN and 2 DNS-01 challenges are executed. In this case the generated DNS TXT record for both domains is the same. Even though this behavior is compliant, it can lead to problems as all DNS providers keep DNS records cached for a given time (TTL) and this TTL can be greater than the challenge timeout making the DNS-01 challenge fail.

    The Traefik ACME client library lego supports some but not all DNS providers to work around this issue. The indicates if they allow generating certificates for a wildcard domain and its root domain.

    Wildcard certificates can only be verified through a DNS-01 challenge.

    Double Wildcard Certificates

    It is not possible to request a double wildcard certificate for a domain (for example *.*.local.com).

    The character @ is not authorized in the router name

    General

    If both HTTP routers and TCP routers listen to the same entry points, the TCP routers will apply before the HTTP routers. If no matching route is found for the TCP routers, then the HTTP routers will take over.

    EntryPoints

    If not specified, TCP routers will accept requests from all defined entry points. If you want to limit the router scope to a set of entry points, set the entry points option.

    Listens to Every Entry Point

    Dynamic Configuration

    File (YAML)

    1. ## Dynamic configuration
    2. tcp:
    3. routers:
    4. Router-1:
    5. # By default, routers listen to every entrypoints
    6. rule: "HostSNI(`example.com`)"
    7. service: "service-1"
    8. # will route TLS requests (and ignore non tls requests)
    9. tls: {}

    File (TOML)

    1. ## Dynamic configuration
    2. [tcp.routers]
    3. [tcp.routers.Router-1]
    4. # By default, routers listen to every entrypoints
    5. rule = "HostSNI(`example.com`)"
    6. service = "service-1"
    7. # will route TLS requests (and ignore non tls requests)
    8. [tcp.routers.Router-1.tls]

    Static Configuration

    File (YAML)

    1. ## Static configuration
    2. entryPoints:
    3. web:
    4. address: ":80"
    5. websecure:
    6. address: ":443"
    7. other:
    8. address: ":9090"

    File (TOML)

    1. ## Static configuration
    2. [entryPoints]
    3. [entryPoints.web]
    4. address = ":80"
    5. [entryPoints.websecure]
    6. address = ":443"
    7. [entryPoints.other]
    8. address = ":9090"

    CLI

    1. ## Static configuration
    2. --entrypoints.web.address=:80
    3. --entrypoints.websecure.address=:443
    4. --entrypoints.other.address=:9090

    Dynamic Configuration

    File (YAML)

    1. ## Dynamic configuration
    2. tcp:
    3. routers:
    4. Router-1:
    5. # won't listen to entry point web
    6. entryPoints:
    7. - "websecure"
    8. - "other"
    9. rule: "HostSNI(`example.com`)"
    10. service: "service-1"
    11. # will route TLS requests (and ignore non tls requests)
    12. tls: {}

    File (TOML)

    1. ## Dynamic configuration
    2. [tcp.routers]
    3. [tcp.routers.Router-1]
    4. # won't listen to entry point web
    5. entryPoints = ["websecure", "other"]
    6. rule = "HostSNI(`example.com`)"
    7. service = "service-1"
    8. [tcp.routers.Router-1.tls]

    Static Configuration

    File (YAML)

    1. ## Static configuration
    2. entryPoints:
    3. web:
    4. address: ":80"
    5. websecure:
    6. address: ":443"
    7. other:
    8. address: ":9090"

    File (TOML)

    1. ## Static configuration
    2. [entryPoints]
    3. [entryPoints.web]
    4. [entryPoints.websecure]
    5. address = ":443"
    6. [entryPoints.other]
    7. address = ":9090"

    CLI

    Rule

    Non-ASCII Domain Names

    Non-ASCII characters are not supported in the HostSNI expression, and by doing so the associated TCP router will be invalid. Domain names containing non-ASCII characters must be provided as punycode encoded values (rfc 3492).

    HostSNI & TLS

    It is important to note that the Server Name Indication is an extension of the TLS protocol. Hence, only TLS routers will be able to specify a domain name with that rule. However, non-TLS routers will have to explicitly use that rule with * (every domain) to state that every non-TLS request will be handled by the router.

    Middlewares

    You can attach a list of middlewares to each TCP router. The middlewares will take effect only if the rule matches, and before connecting to the service.

    The character @ is not allowed to be used in the middleware name.

    Middlewares order

    Middlewares are applied in the same order as their declaration in router.

    With a — using the File Provider

    TOML

    1. ## Dynamic configuration
    2. [tcp.routers]
    3. [tcp.routers.my-router]
    4. rule = "HostSNI(`*`)"
    5. # declared elsewhere
    6. middlewares = ["ipwhitelist"]
    7. service = "service-foo"

    YAML

    1. ## Dynamic configuration
    2. tcp:
    3. routers:
    4. my-router:
    5. rule: "HostSNI(`*`)"
    6. # declared elsewhere
    7. middlewares:
    8. - ipwhitelist
    9. service: service-foo

    You must attach a TCP per TCP router. Services are the target for the router.

    TCP routers can only target TCP services (not HTTP services).

    TLS

    General

    When a TLS section is specified, it instructs Traefik that the current router is dedicated to TLS requests only (and that the router should ignore non-TLS requests).

    By default, a router with a TLS section will terminate the TLS connections, meaning that it will send decrypted data to the services.

    Router for TLS requests

    File (YAML)

    1. ## Dynamic configuration
    2. tcp:
    3. routers:
    4. Router-1:
    5. rule: "HostSNI(`foo-domain`)"
    6. service: service-id
    7. # will terminate the TLS request by default
    8. tls: {}

    File (TOML)

    1. ## Dynamic configuration
    2. [tcp.routers]
    3. [tcp.routers.Router-1]
    4. rule = "HostSNI(`foo-domain`)"
    5. service = "service-id"
    6. # will terminate the TLS request by default
    7. [tcp.routers.Router-1.tls]

    passthrough

    As seen above, a TLS router will terminate the TLS connection by default. However, the passthrough option can be specified to set whether the requests should be forwarded “as is”, keeping all data encrypted.

    It defaults to false.

    Configuring passthrough

    File (YAML)

    1. ## Dynamic configuration
    2. tcp:
    3. routers:
    4. Router-1:
    5. rule: "HostSNI(`foo-domain`)"
    6. service: service-id
    7. tls:
    8. passthrough: true

    File (TOML)

    1. ## Dynamic configuration
    2. [tcp.routers]
    3. [tcp.routers.Router-1]
    4. rule = "HostSNI(`foo-domain`)"
    5. service = "service-id"
    6. [tcp.routers.Router-1.tls]
    7. passthrough = true

    options

    The options field enables fine-grained control of the TLS parameters. It refers to a TLS Options and will be applied only if a HostSNI rule is defined.

    Configuring the tls options

    File (YAML)

    1. ## Dynamic configuration
    2. tcp:
    3. routers:
    4. Router-1:
    5. rule: "HostSNI(`foo-domain`)"
    6. service: service-id
    7. # will terminate the TLS request
    8. tls:
    9. options: foo
    10. tls:
    11. options:
    12. foo:
    13. minVersion: VersionTLS12
    14. cipherSuites:
    15. - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    16. - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
    17. - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
    18. - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
    19. - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

    File (TOML)

    1. ## Dynamic configuration
    2. [tcp.routers]
    3. [tcp.routers.Router-1]
    4. rule = "HostSNI(`foo-domain`)"
    5. service = "service-id"
    6. # will terminate the TLS request
    7. [tcp.routers.Router-1.tls]
    8. options = "foo"
    9. [tls.options]
    10. [tls.options.foo]
    11. minVersion = "VersionTLS12"
    12. cipherSuites = [
    13. "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
    14. "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
    15. "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
    16. "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
    17. "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
    18. ]

    certResolver

    See certResolver for HTTP router for more information.

    File (YAML)

    1. ## Dynamic configuration
    2. tcp:
    3. routers:
    4. routerfoo:
    5. rule: "HostSNI(`snitest.com`)"
    6. tls:
    7. certResolver: foo

    File (TOML)

    1. ## Dynamic configuration
    2. [tcp.routers]
    3. [tcp.routers.routerfoo]
    4. rule = "HostSNI(`snitest.com`)"
    5. [tcp.routers.routerfoo.tls]
    6. certResolver = "foo"

    domains

    See domains for HTTP router for more information.

    File (YAML)

    1. ## Dynamic configuration
    2. tcp:
    3. routers:
    4. routerbar:
    5. rule: "HostSNI(`snitest.com`)"
    6. tls:
    7. certResolver: "bar"
    8. domains:
    9. - main: "snitest.com"
    10. sans:
    11. - "*.snitest.com"

    File (TOML)

    1. ## Dynamic configuration
    2. [tcp.routers]
    3. [tcp.routers.routerbar]
    4. rule = "HostSNI(`snitest.com`)"
    5. [tcp.routers.routerbar.tls]
    6. certResolver = "bar"
    7. [[tcp.routers.routerbar.tls.domains]]
    8. main = "snitest.com"
    9. sans = ["*.snitest.com"]

    The character @ is not allowed in the router name

    General

    Similarly to TCP, as UDP is the transport layer, there is no concept of a request, so there is no notion of an URL path prefix to match an incoming UDP packet with. Furthermore, as there is no good TLS support at the moment for multiple hosts, there is no Host SNI notion to match against either. Therefore, there is no criterion that could be used as a rule to match incoming packets in order to route them. So UDP “routers” at this time are pretty much only load-balancers in one form or another.

    Sessions and timeout

    Even though UDP is connectionless (and because of that), the implementation of an UDP router in Traefik relies on what we (and a couple of other implementations) call a session. It basically means that some state is kept about an ongoing communication between a client and a backend, notably so that the proxy knows where to forward a response packet from a backend. As expected, a timeout is associated to each of these sessions, so that they get cleaned out if they go through a period of inactivity longer than a given duration. Timeout can be configured using the entryPoints.name.udp.timeout option as described under entry points.

    EntryPoints

    If not specified, UDP routers will accept packets from all defined (UDP) entry points. If one wants to limit the router scope to a set of entry points, one should set the entry points option.

    Listens to Every Entry Point

    Dynamic Configuration

    File (YAML)

    1. ## Dynamic configuration
    2. udp:
    3. routers:
    4. Router-1:
    5. # By default, routers listen to all UDP entrypoints
    6. # i.e. "other", and "streaming".
    7. service: "service-1"

    File (TOML)

    1. ## Dynamic configuration
    2. [udp.routers]
    3. [udp.routers.Router-1]
    4. # By default, routers listen to all UDP entrypoints,
    5. # i.e. "other", and "streaming".
    6. service = "service-1"

    Static Configuration

    File (YAML)

    1. ## Static configuration
    2. entryPoints:
    3. # not used by UDP routers
    4. web:
    5. address: ":80"
    6. # used by UDP routers
    7. other:
    8. address: ":9090/udp"
    9. streaming:
    10. address: ":9191/udp"

    File (TOML)

    1. ## Static configuration
    2. [entryPoints]
    3. # not used by UDP routers
    4. [entryPoints.web]
    5. address = ":80"
    6. # used by UDP routers
    7. [entryPoints.other]
    8. address = ":9090/udp"
    9. [entryPoints.streaming]
    10. address = ":9191/udp"

    CLI

    1. ## Static configuration
    2. --entrypoints.web.address=":80"
    3. --entrypoints.other.address=":9090/udp"
    4. --entrypoints.streaming.address=":9191/udp"

    Listens to Specific Entry Points

    Dynamic Configuration

    File (YAML)

    1. ## Dynamic configuration
    2. udp:
    3. routers:
    4. Router-1:
    5. # does not listen on "other" entry point
    6. entryPoints:
    7. - "streaming"
    8. service: "service-1"

    File (TOML)

    1. ## Dynamic configuration
    2. [udp.routers]
    3. [udp.routers.Router-1]
    4. # does not listen on "other" entry point
    5. entryPoints = ["streaming"]
    6. service = "service-1"

    Static Configuration

    File (YAML)

    1. ## Static configuration
    2. entryPoints:
    3. web:
    4. address: ":80"
    5. other:
    6. address: ":9090/udp"
    7. streaming:
    8. address: ":9191/udp"

    File (TOML)

    1. ## Static configuration
    2. [entryPoints]
    3. [entryPoints.web]
    4. address = ":80"
    5. [entryPoints.other]
    6. address = ":9090/udp"
    7. [entryPoints.streaming]
    8. address = ":9191/udp"

    CLI

    1. ## Static configuration
    2. --entrypoints.web.address=":80"
    3. --entrypoints.other.address=":9090/udp"

    Services

    There must be one (and only one) UDP referenced per UDP router. Services are the target for the router.