From 17ce295c305dd13349b5d6768e0d4071c4736c06 Mon Sep 17 00:00:00 2001 From: Jan Sauer Date: Fri, 11 Oct 2019 14:34:06 +0200 Subject: [PATCH 01/40] Fix acme storage file docker mounting example --- docs/content/https/acme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/https/acme.md b/docs/content/https/acme.md index 1e3e35680..039c54dd2 100644 --- a/docs/content/https/acme.md +++ b/docs/content/https/acme.md @@ -382,7 +382,7 @@ ACME certificates can be stored in a JSON file that needs to have a `600` file m In Docker you can mount either the JSON file, or the folder containing it: ```bash -docker run -v "/my/host/acme.json:acme.json" traefik +docker run -v "/my/host/acme.json:/acme.json" traefik ``` ```bash From e7b7ae94b0633ff872a9e0948a6f6b0ffc61c900 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Fri, 11 Oct 2019 17:20:05 +0200 Subject: [PATCH 02/40] fix: add filename in the file provider logs. --- docs/content/routing/services/index.md | 2 +- pkg/provider/file/file.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/content/routing/services/index.md b/docs/content/routing/services/index.md index 2e8b4e53e..cd48b5ba8 100644 --- a/docs/content/routing/services/index.md +++ b/docs/content/routing/services/index.md @@ -539,7 +539,7 @@ The `address` option (IP:Port) point to a specific instance. my-service: loadBalancer: servers: - address: "xx.xx.xx.xx:xx" + - address: "xx.xx.xx.xx:xx" ``` #### Termination Delay diff --git a/pkg/provider/file/file.go b/pkg/provider/file/file.go index f8125349d..862b9e1a2 100644 --- a/pkg/provider/file/file.go +++ b/pkg/provider/file/file.go @@ -199,8 +199,6 @@ func flattenCertificates(ctx context.Context, tlsConfig *dynamic.TLSConfiguratio } func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory string, configuration *dynamic.Configuration) (*dynamic.Configuration, error) { - logger := log.FromContext(ctx) - fileList, err := ioutil.ReadDir(directory) if err != nil { return configuration, fmt.Errorf("unable to read directory %s: %v", directory, err) @@ -227,6 +225,8 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st configTLSMaps := make(map[*tls.CertAndStores]struct{}) for _, item := range fileList { + logger := log.FromContext(log.With(ctx, log.Str("filename", item.Name()))) + if item.IsDir() { configuration, err = p.loadFileConfigFromDirectory(ctx, filepath.Join(directory, item.Name()), configuration) if err != nil { @@ -245,7 +245,7 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st var c *dynamic.Configuration c, err = p.loadFileConfig(ctx, filepath.Join(directory, item.Name()), true) if err != nil { - return configuration, err + return configuration, fmt.Errorf("%s: %v", filepath.Join(directory, item.Name()), err) } for name, conf := range c.HTTP.Routers { From cb3328dca30ed09ef462236156c860d0d0eb063b Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 14 Oct 2019 11:18:04 +0200 Subject: [PATCH 03/40] Normalize service and router names for ingress. --- pkg/provider/kubernetes/ingress/kubernetes.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pkg/provider/kubernetes/ingress/kubernetes.go b/pkg/provider/kubernetes/ingress/kubernetes.go index 863711cce..403069895 100644 --- a/pkg/provider/kubernetes/ingress/kubernetes.go +++ b/pkg/provider/kubernetes/ingress/kubernetes.go @@ -16,6 +16,7 @@ import ( "github.com/containous/traefik/v2/pkg/config/dynamic" "github.com/containous/traefik/v2/pkg/job" "github.com/containous/traefik/v2/pkg/log" + "github.com/containous/traefik/v2/pkg/provider" "github.com/containous/traefik/v2/pkg/safe" "github.com/containous/traefik/v2/pkg/tls" "github.com/containous/traefik/v2/pkg/types" @@ -324,8 +325,7 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl continue } - serviceName := ingress.Namespace + "-" + p.Backend.ServiceName + "-" + p.Backend.ServicePort.String() - serviceName = strings.ReplaceAll(serviceName, ".", "-") + serviceName := provider.Normalize(ingress.Namespace + "-" + p.Backend.ServiceName + "-" + p.Backend.ServicePort.String()) var rules []string if len(rule.Host) > 0 { rules = []string{"Host(`" + rule.Host + "`)"} @@ -335,10 +335,7 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl rules = append(rules, "PathPrefix(`"+p.Path+"`)") } - routerKey := strings.Replace(rule.Host, ".", "-", -1) + strings.Replace(p.Path, "/", "-", 1) - if strings.HasPrefix(routerKey, "-") { - routerKey = strings.Replace(routerKey, "-", "", 1) - } + routerKey := strings.TrimPrefix(provider.Normalize(rule.Host+p.Path), "-") conf.HTTP.Routers[routerKey] = &dynamic.Router{ Rule: strings.Join(rules, " && "), Service: serviceName, From 0048156379ccc761b2e56802472dc7059932cff0 Mon Sep 17 00:00:00 2001 From: Antoine Caron Date: Mon, 14 Oct 2019 17:18:04 +0200 Subject: [PATCH 04/40] chore(node/webui): update node to 12.11 version --- exp.Dockerfile | 4 ++-- webui/Dockerfile | 2 +- webui/readme.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/exp.Dockerfile b/exp.Dockerfile index b12c512b8..d13f64a7a 100644 --- a/exp.Dockerfile +++ b/exp.Dockerfile @@ -1,5 +1,5 @@ # WEBUI -FROM node:8.15.0 as webui +FROM node:12.11 as webui ENV WEBUI_DIR /src/webui RUN mkdir -p $WEBUI_DIR @@ -7,7 +7,7 @@ RUN mkdir -p $WEBUI_DIR COPY ./webui/ $WEBUI_DIR/ WORKDIR $WEBUI_DIR -RUN yarn install +RUN npm install RUN npm run build diff --git a/webui/Dockerfile b/webui/Dockerfile index 091cb1909..67e491e5d 100644 --- a/webui/Dockerfile +++ b/webui/Dockerfile @@ -1,4 +1,4 @@ -FROM node:8.15.0 +FROM node:12.11 ENV WEBUI_DIR /src/webui RUN mkdir -p $WEBUI_DIR diff --git a/webui/readme.md b/webui/readme.md index f7e6ad98f..ca205bcef 100644 --- a/webui/readme.md +++ b/webui/readme.md @@ -20,7 +20,7 @@ make generate-webui # Generate static contents in `traefik/static/` folder. ## How to build (only for frontend developer) -- prerequisite: [Node 6+](https://nodejs.org) [Npm](https://www.npmjs.com/) +- prerequisite: [Node 12.11+](https://nodejs.org) [Npm](https://www.npmjs.com/) - Go to the directory `webui` From 8492a702b2e04bdea4f004cb123df7d6d3ba9294 Mon Sep 17 00:00:00 2001 From: Damien Duportal Date: Mon, 14 Oct 2019 17:26:05 +0200 Subject: [PATCH 05/40] Migration guide: pathprefixstrip migration --- docs/content/migration/v1-to-v2.md | 279 +++++++++++++++++++++-------- 1 file changed, 205 insertions(+), 74 deletions(-) diff --git a/docs/content/migration/v1-to-v2.md b/docs/content/migration/v1-to-v2.md index 121ba375b..b2a6d2a3d 100644 --- a/docs/content/migration/v1-to-v2.md +++ b/docs/content/migration/v1-to-v2.md @@ -3,13 +3,13 @@ How to Migrate from Traefik v1 to Traefik v2. {: .subtitle } -The version 2 of Traefik introduces a number of breaking changes, +The version 2 of Traefik introduces a number of breaking changes, which require one to update their configuration when they migrate from v1 to v2. -The goal of this page is to recapitulate all of these changes, and in particular to give examples, +The goal of this page is to recapitulate all of these changes, and in particular to give examples, feature by feature, of how the configuration looked like in v1, and how it now looks like in v2. !!! info "Migration Helper" - + We created a tool to help during the migration: [traefik-migration-tool](https://github.com/containous/traefik-migration-tool) This tool allows to: @@ -32,7 +32,7 @@ Then any router can refer to an instance of the wanted middleware. !!! example "One frontend with basic auth and one backend, become one router, one service, and one basic auth middleware." !!! info "v1" - + ```yaml tab="Docker" labels: - "traefik.frontend.rule=Host:test.localhost;PathPrefix:/test" @@ -92,9 +92,9 @@ Then any router can refer to an instance of the wanted middleware. [backends.backend1.loadBalancer] method = "wrr" ``` - + !!! info "v2" - + ```yaml tab="Docker" labels: - "traefik.http.routers.router0.rule=Host(`bar.com`) && PathPrefix(`/test`)" @@ -103,7 +103,7 @@ Then any router can refer to an instance of the wanted middleware. ``` ```yaml tab="K8s IngressRoute" - # The definitions below require the definitions for the Middleware and IngressRoute kinds. + # The definitions below require the definitions for the Middleware and IngressRoute kinds. # https://docs.traefik.io/v2.0/providers/kubernetes-crd/#traefik-ingressroute-definition apiVersion: traefik.containo.us/v1alpha1 kind: Middleware @@ -155,7 +155,7 @@ Then any router can refer to an instance of the wanted middleware. [http.middlewares] [http.middlewares.auth.basicAuth] users = [ - "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", + "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", ] ``` @@ -184,7 +184,7 @@ Then any router can refer to an instance of the wanted middleware. - "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" ``` -## TLS configuration is now dynamic, per router. +## TLS Configuration Is Now Dynamic, per Router. TLS parameters used to be specified in the static configuration, as an entryPoint field. With Traefik v2, a new dynamic TLS section at the root contains all the desired TLS configurations. @@ -214,13 +214,13 @@ Then, a [router's TLS field](../routing/routers/index.md#tls) can refer to one o certFile = "path/to/my.cert" keyFile = "path/to/my.key" ``` - + ```bash tab="CLI" --entryPoints='Name:web-secure Address::443 TLS:path/to/my.cert,path/to/my.key TLS.MinVersion:VersionTLS12 TLS.CipherSuites:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256' ``` - + !!! info "v2" - + ```toml tab="File (TOML)" # dynamic configuration [http.routers] @@ -250,7 +250,7 @@ Then, a [router's TLS field](../routing/routers/index.md#tls) can refer to one o "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", ] ``` - + ```yaml tab="File (YAML)" http: routers: @@ -275,9 +275,9 @@ Then, a [router's TLS field](../routing/routers/index.md#tls) can refer to one o - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ``` - + ```yaml tab="K8s IngressRoute" - # The definitions below require the definitions for the TLSOption and IngressRoute kinds. + # The definitions below require the definitions for the TLSOption and IngressRoute kinds. # https://docs.traefik.io/v2.0/providers/kubernetes-crd/#traefik-ingressroute-definition apiVersion: traefik.containo.us/v1alpha1 kind: TLSOption @@ -310,11 +310,11 @@ Then, a [router's TLS field](../routing/routers/index.md#tls) can refer to one o - name: whoami port: 80 tls: - options: + options: name: mytlsoption namespace: default ``` - + ```yaml tab="Docker" labels: # myTLSOptions must be defined by another provider, in this instance in the File Provider. @@ -322,7 +322,7 @@ Then, a [router's TLS field](../routing/routers/index.md#tls) can refer to one o - "traefik.http.routers.router0.tls.options=myTLSOptions@file" ``` -## HTTP to HTTPS Redirection is now configured on Routers +## HTTP to HTTPS Redirection Is Now Configured on Routers Previously on Traefik v1, the redirection was applied on an entry point or on a frontend. With Traefik v2 it is applied on a [Router](../routing/routers/index.md). @@ -350,14 +350,14 @@ To apply a redirection, one of the redirect middlewares, [RedirectRegex](../midd certFile = "examples/traefik.crt" keyFile = "examples/traefik.key" ``` - + ```bash tab="CLI" --entrypoints=Name:web Address::80 Redirect.EntryPoint:web-secure --entryPoints='Name:web-secure Address::443 TLS:path/to/my.cert,path/to/my.key' ``` - + !!! info "v2" - + ```yaml tab="Docker" labels: - traefik.http.routers.web.rule=Host(`foo.com`) @@ -454,9 +454,9 @@ To apply a redirection, one of the redirect middlewares, [RedirectRegex](../midd [[tls.certificates]] certFile = "/path/to/domain.cert" - keyFile = "/path/to/domain.key" + keyFile = "/path/to/domain.key" ``` - + ```yaml tab="File (YAML)" ## static configuration # traefik.yml @@ -506,7 +506,138 @@ To apply a redirection, one of the redirect middlewares, [RedirectRegex](../midd certificates: - certFile: /app/certs/server/server.pem keyFile: /app/certs/server/server.pem - ``` + ``` + +## Strip and Rewrite Path Prefixes + +With the new core notions of v2 (introduced earlier in the section +["Frontends and Backends Are Dead... Long Live Routers, Middlewares, and Services"](#frontends-and-backends-are-dead-long-live-routers-middlewares-and-services)), +transforming the URL path prefix of incoming requests is configured with [middlewares](../../middlewares/overview/), +after the routing step with [router rule `PathPrefix`](https://docs.traefik.io/v2.0/routing/routers/#rule). + +Use Case: Incoming requests to `http://company.org/admin` are forwarded to the webapplication "admin", +with the path `/admin` stripped, e.g. to `http://:/`. In this case, you must: + +* First, configure a router named `admin` with a rule matching at least the path prefix with the `PathPrefix` keyword, +* Then, define a middlware of type [`stripprefix`](../../middlewares/stripprefix/), which remove the prefix `/admin`, associated to the router `admin`. + +!!! example "Strip Path Prefix When Forwarding to Backend" + + !!! info "v1" + + ```yaml tab="Docker" + labels: + - "traefik.frontend.rule=Host:company.org;PathPrefixStrip:/admin" + ``` + + ```yaml tab="Kubernetes Ingress" + apiVersion: networking.k8s.io/v1beta1 + kind: Ingress + metadata: + name: traefik + annotations: + kubernetes.io/ingress.class: traefik + traefik.ingress.kubernetes.io/rule-type: PathPrefixStrip + spec: + rules: + - host: company.org + http: + paths: + - path: /admin + backend: + serviceName: admin-svc + servicePort: admin + ``` + + ```toml tab="File (TOML)" + [frontends.admin] + [frontends.admin.routes.admin_1] + rule = "Host:company.org;PathPrefixStrip:/admin" + ``` + + !!! info "v2" + + ```yaml tab="Docker" + labels: + - "traefik.http.routers.admin.rule=Host(`company.org`) && PathPrefix(`/admin`)" + - "traefik.http.middlewares.admin-stripprefix.stripprefix.prefixes=/admin" + - "traefik.http.routers.web.middlewares=admin-stripprefix@docker" + ``` + + ```yaml tab="Kubernetes IngressRoute" + --- + apiVersion: traefik.containo.us/v1alpha1 + kind: IngressRoute + metadata: + name: http-redirect-ingressRoute + namespace: admin-web + spec: + entryPoints: + - web + routes: + - match: Host(`company.org`) && PathPrefix(`/admin`) + kind: Rule + services: + - name: admin-svc + port: admin + middlewares: + - name: admin-stripprefix + --- + kind: Middleware + metadata: + name: admin-stripprefix + spec: + stripPrefix: + prefixes: + - /admin + ``` + + ```toml tab="File (TOML)" + ## Dynamic configuration + # dynamic-conf.toml + + [http.routers.router1] + rule = "Host(`company.org`) && PathPrefix(`/admin`)" + service = "admin-svc" + entrypoints = ["web"] + middlewares = ["admin-stripprefix"] + + [http.middlewares] + [http.middlewares.admin-stripprefix.stripPrefix] + prefixes = ["/admin"] + + # ... + ``` + + ```yaml tab="File (YAML)" + ## Dynamic Configuration + # dynamic-conf.yml + + # As YAML Configuration File + http: + routers: + admin: + service: admin-svc + middlewares: + - "admin-stripprefix" + rule: "Host(`company.org`) && PathPrefix(`/admin`)" + + middlewares: + admin-stripprefix: + addPrefix: + prefix: "/admin" + + # ... + ``` + +??? question "What About Other Path Transformations?" + + Instead of removing the path prefix with the [`stripprefix` middleware](../../middlewares/stripprefix/), you can also: + + * Add a path prefix with the [`addprefix` middleware](../../middlewares/addprefix/) + * Replace the complete path of the request with the [`replacepath` middleware](../../middlewares/replacepath/) + * ReplaceRewrite path using Regexp with the [`replacepathregex` middleware](../../middlewares/replacepathregex/) + * And a lot more on the [`middlewares` page](../../middlewares/overview/) ## ACME (LetsEncrypt) @@ -536,7 +667,7 @@ To apply a redirection, one of the redirect middlewares, [RedirectRegex](../midd [acme.httpChallenge] entryPoint = "web" ``` - + ```bash tab="CLI" --defaultentrypoints=web-secure,web --entryPoints=Name:web Address::80 Redirect.EntryPoint:web-secure @@ -547,9 +678,9 @@ To apply a redirection, one of the redirect middlewares, [RedirectRegex](../midd --acme.onHostRule=true --acme.httpchallenge.entrypoint=http ``` - + !!! info "v2" - + ```toml tab="File (TOML)" # static configuration [entryPoints] @@ -566,7 +697,7 @@ To apply a redirection, one of the redirect middlewares, [RedirectRegex](../midd # used during the challenge entryPoint = "web" ``` - + ```yaml tab="File (YAML)" entryPoints: web: @@ -583,8 +714,8 @@ To apply a redirection, one of the redirect middlewares, [RedirectRegex](../midd httpChallenge: # used during the challenge entryPoint: web - ``` - + ``` + ```bash tab="CLI" --entryPoints.web.address=":80" --entryPoints.websecure.address=":443" @@ -601,7 +732,7 @@ There is no more log configuration at the root level. !!! example "Simple log configuration" !!! info "v1" - + ```toml tab="File (TOML)" # static configuration logLevel = "DEBUG" @@ -610,15 +741,15 @@ There is no more log configuration at the root level. filePath = "/path/to/traefik.log" format = "json" ``` - + ```bash tab="CLI" --logLevel="DEBUG" --traefikLog.filePath="/path/to/traefik.log" --traefikLog.format="json" ``` - + !!! info "v2" - + ```toml tab="File (TOML)" # static configuration [log] @@ -626,15 +757,15 @@ There is no more log configuration at the root level. filePath = "/path/to/log-file.log" format = "json" ``` - + ```yaml tab="File (YAML)" # static configuration log: level: DEBUG filePath: /path/to/log-file.log format: json - ``` - + ``` + ```bash tab="CLI" --log.level="DEBUG" --log.filePath="/path/to/traefik.log" @@ -644,11 +775,11 @@ There is no more log configuration at the root level. ## Tracing Traefik v2 retains OpenTracing support. The `backend` root option from the v1 is gone, you just have to set your [tracing configuration](../observability/tracing/overview.md). - + !!! example "Simple Jaeger tracing configuration" !!! info "v1" - + ```toml tab="File (TOML)" # static configuration [tracing] @@ -660,18 +791,18 @@ Traefik v2 retains OpenTracing support. The `backend` root option from the v1 is samplingType = "const" localAgentHostPort = "12.0.0.1:6831" ``` - + ```bash tab="CLI" --tracing.backend="jaeger" --tracing.servicename="tracing" --tracing.jaeger.localagenthostport="12.0.0.1:6831" --tracing.jaeger.samplingparam="1.0" --tracing.jaeger.samplingserverurl="http://12.0.0.1:5778/sampling" - --tracing.jaeger.samplingtype="const" + --tracing.jaeger.samplingtype="const" ``` - + !!! info "v2" - + ```toml tab="File (TOML)" # static configuration [tracing] @@ -682,7 +813,7 @@ Traefik v2 retains OpenTracing support. The `backend` root option from the v1 is samplingType = "const" localAgentHostPort = "12.0.0.1:6831" ``` - + ```yaml tab="File (YAML)" # static configuration tracing: @@ -692,8 +823,8 @@ Traefik v2 retains OpenTracing support. The `backend` root option from the v1 is samplingServerURL: 'http://12.0.0.1:5778/sampling' samplingType: const localAgentHostPort: '12.0.0.1:6831' - ``` - + ``` + ```bash tab="CLI" --tracing.servicename="tracing" --tracing.jaeger.localagenthostport="12.0.0.1:6831" @@ -705,33 +836,33 @@ Traefik v2 retains OpenTracing support. The `backend` root option from the v1 is ## Metrics The v2 retains metrics tools and allows metrics to be configured for the entrypoints and/or services. -For a basic configuration, the [metrics configuration](../observability/metrics/overview.md) remains the same. +For a basic configuration, the [metrics configuration](../observability/metrics/overview.md) remains the same. !!! example "Simple Prometheus metrics configuration" !!! info "v1" - + ```toml tab="File (TOML)" # static configuration [metrics.prometheus] buckets = [0.1,0.3,1.2,5.0] entryPoint = "traefik" ``` - + ```bash tab="CLI" --metrics.prometheus.buckets=[0.1,0.3,1.2,5.0] --metrics.prometheus.entrypoint="traefik" ``` - + !!! info "v2" - + ```toml tab="File (TOML)" # static configuration [metrics.prometheus] buckets = [0.1,0.3,1.2,5.0] entryPoint = "metrics" ``` - + ```yaml tab="File (YAML)" # static configuration metrics: @@ -742,22 +873,22 @@ For a basic configuration, the [metrics configuration](../observability/metrics/ - 1.2 - 5 entryPoint: metrics - ``` - + ``` + ```bash tab="CLI" --metrics.prometheus.buckets=[0.1,0.3,1.2,5.0] --metrics.prometheus.entrypoint="metrics" ``` -## No more root level key/values +## No More Root Level Key/Values To avoid any source of confusion, there are no more configuration at the root level. Each root item has been moved to a related section or removed. !!! example "From root to dedicated section" - + !!! info "v1" - + ```toml tab="File (TOML)" # static configuration checkNewVersion = false @@ -772,7 +903,7 @@ Each root item has been moved to a related section or removed. defaultEntryPoints = ["web", "web-secure"] keepTrailingSlash = false ``` - + ```bash tab="CLI" --checknewversion=false --sendanonymoususage=true @@ -786,9 +917,9 @@ Each root item has been moved to a related section or removed. --defaultentrypoints="web","web-secure" --keeptrailingslash=true ``` - + !!! info "v2" - + ```toml tab="File (TOML)" # static configuration [global] @@ -804,9 +935,9 @@ Each root item has been moved to a related section or removed. maxIdleConnsPerHost = 42 [providers] - providersThrottleDuration = 42 + providersThrottleDuration = 42 ``` - + ```yaml tab="File (YAML)" # static configuration global: @@ -824,8 +955,8 @@ Each root item has been moved to a related section or removed. providers: providersThrottleDuration: 42 - ``` - + ``` + ```bash tab="CLI" --global.checknewversion=true --global.sendanonymoususage=true @@ -835,7 +966,7 @@ Each root item has been moved to a related section or removed. --serverstransport.maxidleconnsperhost=42 --providers.providersthrottleduration=42 ``` - + ## Dashboard You need to activate the API to access the [dashboard](../operations/dashboard.md). @@ -847,11 +978,11 @@ As the dashboard access is now secured by default you can either: !!! info "Dashboard with k8s and dedicated router" As `api@internal` is not a Kubernetes service, you have to use the file provider or the `insecure` API option. - + !!! example "Activate and access the dashboard" !!! info "v1" - + ```toml tab="File (TOML)" ## static configuration # traefik.toml @@ -868,14 +999,14 @@ As the dashboard access is now secured by default you can either: [api] entryPoint = "web-secure" ``` - + ```bash tab="CLI" --entryPoints='Name:web-secure Address::443 TLS Auth.Basic.Users:test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/' --api ``` - + !!! info "v2" - + ```yaml tab="Docker" # dynamic configuration labels: @@ -916,7 +1047,7 @@ As the dashboard access is now secured by default you can either: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" ] ``` - + ```yaml tab="File (YAML)" ## static configuration # traefik.yaml @@ -952,8 +1083,8 @@ As the dashboard access is now secured by default you can either: basicAuth: users: - 'test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/' - ``` - + ``` + ## Providers Supported [providers](../providers/overview.md), for now: @@ -976,7 +1107,7 @@ Supported [providers](../providers/overview.md), for now: * [x] Rest * [ ] Zookeeper -## Some Tips You Should Known +## Some Tips You Should Know * Different sources of static configuration (file, CLI flags, ...) cannot be [mixed](../getting-started/configuration-overview.md#the-static-configuration). * Now, configuration elements can be referenced between different providers by using the provider namespace notation: `@`. From b586ae2f2597531837efdd99c4d309d4c6b7a17c Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Tue, 15 Oct 2019 16:36:05 +0200 Subject: [PATCH 06/40] Remove deadcode. --- pkg/hostresolver/hostresolver.go | 123 -------------------------- pkg/hostresolver/hostresolver_test.go | 61 ------------- 2 files changed, 184 deletions(-) delete mode 100644 pkg/hostresolver/hostresolver.go delete mode 100644 pkg/hostresolver/hostresolver_test.go diff --git a/pkg/hostresolver/hostresolver.go b/pkg/hostresolver/hostresolver.go deleted file mode 100644 index 2a7c7dcee..000000000 --- a/pkg/hostresolver/hostresolver.go +++ /dev/null @@ -1,123 +0,0 @@ -package hostresolver - -import ( - "fmt" - "net" - "sort" - "strings" - "time" - - "github.com/containous/traefik/v2/pkg/log" - "github.com/miekg/dns" - "github.com/patrickmn/go-cache" -) - -type cnameResolv struct { - TTL time.Duration - Record string -} - -type byTTL []*cnameResolv - -func (a byTTL) Len() int { return len(a) } -func (a byTTL) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a byTTL) Less(i, j int) bool { return a[i].TTL > a[j].TTL } - -// Resolver used for host resolver -type Resolver struct { - CnameFlattening bool - ResolvConfig string - ResolvDepth int - cache *cache.Cache -} - -// CNAMEFlatten check if CNAME record exists, flatten if possible -func (hr *Resolver) CNAMEFlatten(host string) (string, string) { - if hr.cache == nil { - hr.cache = cache.New(30*time.Minute, 5*time.Minute) - } - - result := []string{host} - request := host - - value, found := hr.cache.Get(host) - if found { - result = strings.Split(value.(string), ",") - } else { - var cacheDuration = 0 * time.Second - - for depth := 0; depth < hr.ResolvDepth; depth++ { - resolv, err := cnameResolve(request, hr.ResolvConfig) - if err != nil { - log.Error(err) - break - } - if resolv == nil { - break - } - - result = append(result, resolv.Record) - if depth == 0 { - cacheDuration = resolv.TTL - } - request = resolv.Record - } - - if err := hr.cache.Add(host, strings.Join(result, ","), cacheDuration); err != nil { - log.Error(err) - } - } - - return result[0], result[len(result)-1] -} - -// cnameResolve resolves CNAME if exists, and return with the highest TTL -func cnameResolve(host string, resolvPath string) (*cnameResolv, error) { - config, err := dns.ClientConfigFromFile(resolvPath) - if err != nil { - return nil, fmt.Errorf("invalid resolver configuration file: %s", resolvPath) - } - - client := &dns.Client{Timeout: 30 * time.Second} - - m := &dns.Msg{} - m.SetQuestion(dns.Fqdn(host), dns.TypeCNAME) - - var result []*cnameResolv - for _, server := range config.Servers { - tempRecord, err := getRecord(client, m, server, config.Port) - if err != nil { - log.Errorf("Failed to resolve host %s: %v", host, err) - continue - } - result = append(result, tempRecord) - } - - if len(result) == 0 { - return nil, nil - } - - sort.Sort(byTTL(result)) - return result[0], nil -} - -func getRecord(client *dns.Client, msg *dns.Msg, server string, port string) (*cnameResolv, error) { - resp, _, err := client.Exchange(msg, net.JoinHostPort(server, port)) - if err != nil { - return nil, fmt.Errorf("exchange error for server %s: %v", server, err) - } - - if resp == nil || len(resp.Answer) == 0 { - return nil, fmt.Errorf("empty answer for server %s", server) - } - - rr, ok := resp.Answer[0].(*dns.CNAME) - if !ok { - return nil, fmt.Errorf("invalid response type for server %s", server) - } - - return &cnameResolv{ - TTL: time.Duration(rr.Hdr.Ttl) * time.Second, - Record: strings.TrimSuffix(rr.Target, "."), - }, nil -} diff --git a/pkg/hostresolver/hostresolver_test.go b/pkg/hostresolver/hostresolver_test.go deleted file mode 100644 index ee6029f7d..000000000 --- a/pkg/hostresolver/hostresolver_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package hostresolver - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestCNAMEFlatten(t *testing.T) { - testCase := []struct { - desc string - resolvFile string - domain string - expectedDomain string - isCNAME bool - }{ - { - desc: "host request is CNAME record", - resolvFile: "/etc/resolv.conf", - domain: "www.github.com", - expectedDomain: "github.com", - isCNAME: true, - }, - { - desc: "resolve file not found", - resolvFile: "/etc/resolv.oops", - domain: "www.github.com", - expectedDomain: "www.github.com", - isCNAME: false, - }, - { - desc: "host request is not CNAME record", - resolvFile: "/etc/resolv.conf", - domain: "github.com", - expectedDomain: "github.com", - isCNAME: false, - }, - } - - for _, test := range testCase { - test := test - t.Run(test.desc, func(t *testing.T) { - t.Parallel() - - hostResolver := &Resolver{ - ResolvConfig: test.resolvFile, - ResolvDepth: 5, - } - - reqH, flatH := hostResolver.CNAMEFlatten(test.domain) - assert.Equal(t, test.domain, reqH) - assert.Equal(t, test.expectedDomain, flatH) - - if test.isCNAME { - assert.NotEqual(t, test.expectedDomain, reqH) - } else { - assert.Equal(t, test.expectedDomain, reqH) - } - }) - } -} From 02bdc1dcb9108e0635e70ac5e09f28757944069e Mon Sep 17 00:00:00 2001 From: Peter Stalman Date: Wed, 16 Oct 2019 01:34:04 -0700 Subject: [PATCH 07/40] Clarify unit of duration field in access log --- docs/content/observability/access-logs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/observability/access-logs.md b/docs/content/observability/access-logs.md index 418532f74..5a27efc17 100644 --- a/docs/content/observability/access-logs.md +++ b/docs/content/observability/access-logs.md @@ -180,7 +180,7 @@ accessLog: |-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `StartUTC` | The time at which request processing started. | | `StartLocal` | The local time at which request processing started. | - | `Duration` | The total time taken by processing the response, including the origin server's time but not the log writing time. | + | `Duration` | The total time taken (in nanoseconds) by processing the response, including the origin server's time but not the log writing time. | | `FrontendName` | The name of the Traefik frontend. | | `BackendName` | The name of the Traefik backend. | | `BackendURL` | The URL of the Traefik backend. | From 904b3b5b0bc7a98c2e0fe84ca79cae8ab836ebb0 Mon Sep 17 00:00:00 2001 From: Michael G Date: Wed, 16 Oct 2019 16:26:05 +0200 Subject: [PATCH 08/40] Remove obsolete v2 remark from README --- README.md | 9 +++++---- docs/content/getting-started/configuration-overview.md | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ac1ad3fbb..4c7574e8e 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Pointing Traefik at your orchestrator should be the _only_ configuration step yo --- -:warning: Please be aware that the old configurations for Traefik v1.X are NOT compatible with the v2.X config as of now. If you're running v2, please ensure you are using a [v2 configuration](https://docs.traefik.io/). +:warning: Please be aware that the old configurations for Traefik v1.x are NOT compatible with the v2.x config as of now. If you're running v2, please ensure you are using a [v2 configuration](https://docs.traefik.io/). ## Overview @@ -87,10 +87,11 @@ You can access the simple HTML frontend of Traefik. ## Documentation -You can find the complete documentation at [https://docs.traefik.io](https://docs.traefik.io). -A collection of contributions around Traefik can be found at [https://awesome.traefik.io](https://awesome.traefik.io). +You can find the complete documentation of Traefik v2 at [https://docs.traefik.io](https://docs.traefik.io). -:warning: If you're testing out v2, please ensure you are using the [v2 documentation](https://docs.traefik.io/). +If you are using Traefik v1, you can find the complete documentation at [https://docs.traefik.io/v1.7/](https://docs.traefik.io/v1.7/) + +A collection of contributions around Traefik can be found at [https://awesome.traefik.io](https://awesome.traefik.io). ## Support diff --git a/docs/content/getting-started/configuration-overview.md b/docs/content/getting-started/configuration-overview.md index 8a6b87a4c..581a60a03 100644 --- a/docs/content/getting-started/configuration-overview.md +++ b/docs/content/getting-started/configuration-overview.md @@ -16,8 +16,8 @@ The _dynamic configuration_ contains everything that defines how the requests ar This configuration can change and is seamlessly hot-reloaded, without any request interruption or connection loss. !!! warning "Incompatible Configuration" - Please be aware that the old configurations for Traefik v1.X are NOT compatible with the v2.X config as of now. - If you're testing out v2, please ensure you are using a v2 configuration. + Please be aware that the old configurations for Traefik v1.x are NOT compatible with the v2.x config as of now. + If you are running v2, please ensure you are using a v2 configuration. ## The Dynamic Configuration From 554e3e9e6ee1cdd28d1d7c5b20f58e9beac5ecab Mon Sep 17 00:00:00 2001 From: Adrian Goins Date: Wed, 16 Oct 2019 11:40:04 -0300 Subject: [PATCH 09/40] fix incorrect DNS reference --- docs/content/user-guides/crd-acme/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/user-guides/crd-acme/index.md b/docs/content/user-guides/crd-acme/index.md index c26946223..0eb47705b 100644 --- a/docs/content/user-guides/crd-acme/index.md +++ b/docs/content/user-guides/crd-acme/index.md @@ -101,4 +101,4 @@ curl [-k] https://your.domain.com/tls curl [-k] http://your.domain.com:8000/notls ``` -Note that you'll have to use `-k` as long as you're using the staging server of Let's Encrypt, since it is not in the root DNS servers. +Note that you'll have to use `-k` as long as you're using the staging server of Let's Encrypt, since it is not an authorized certificate authority on systems where it hasn't been manually added. From a829d44b514661ef054bc1801bca68fb099eec62 Mon Sep 17 00:00:00 2001 From: Sylvain Rabot Date: Wed, 16 Oct 2019 22:30:05 +0200 Subject: [PATCH 10/40] Let instana/go-sensor handle default agent host --- docs/content/reference/static-configuration/cli-ref.md | 2 +- docs/content/reference/static-configuration/env-ref.md | 2 +- pkg/tracing/instana/instana.go | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index e2b6322e2..54ddd8cd8 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -529,7 +529,7 @@ Specifies the header name that will be used to store the trace ID. Settings for Instana. (Default: ```false```) `--tracing.instana.localagenthost`: -Set instana-agent's host that the reporter will used. (Default: ```localhost```) +Set instana-agent's host that the reporter will used. `--tracing.instana.localagentport`: Set instana-agent's port that the reporter will used. (Default: ```42699```) diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index 1e7a79b83..60327d5db 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -529,7 +529,7 @@ Specifies the header name that will be used to store the trace ID. Settings for Instana. (Default: ```false```) `TRAEFIK_TRACING_INSTANA_LOCALAGENTHOST`: -Set instana-agent's host that the reporter will used. (Default: ```localhost```) +Set instana-agent's host that the reporter will used. `TRAEFIK_TRACING_INSTANA_LOCALAGENTPORT`: Set instana-agent's port that the reporter will used. (Default: ```42699```) diff --git a/pkg/tracing/instana/instana.go b/pkg/tracing/instana/instana.go index e2912bbdd..8bd86944e 100644 --- a/pkg/tracing/instana/instana.go +++ b/pkg/tracing/instana/instana.go @@ -20,7 +20,6 @@ type Config struct { // SetDefaults sets the default values. func (c *Config) SetDefaults() { - c.LocalAgentHost = "localhost" c.LocalAgentPort = 42699 c.LogLevel = "info" } From 6a9d21e9aaff9745f0afc191d9b48bb4881f9c7b Mon Sep 17 00:00:00 2001 From: Oisin Canty Date: Fri, 18 Oct 2019 09:54:05 +0100 Subject: [PATCH 11/40] Fix spelling mistake: "founded" -> "found" --- pkg/provider/acme/provider.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/provider/acme/provider.go b/pkg/provider/acme/provider.go index 300a81899..5a4278320 100644 --- a/pkg/provider/acme/provider.go +++ b/pkg/provider/acme/provider.go @@ -323,7 +323,7 @@ func (p *Provider) resolveDomains(ctx context.Context, domains []string, tlsStor return } - log.FromContext(ctx).Debugf("Try to challenge certificate for domain %v founded in HostSNI rule", domains) + log.FromContext(ctx).Debugf("Try to challenge certificate for domain %v found in HostSNI rule", domains) var domain types.Domain if len(domains) > 0 { From 0ec84ec597ff98a11e3517aa947bc4e1d7d8fc23 Mon Sep 17 00:00:00 2001 From: Kenneth Peiruza Date: Fri, 18 Oct 2019 11:12:05 +0200 Subject: [PATCH 12/40] Adding support for HTTPs backends with Kubernetes ExternalName services --- pkg/provider/kubernetes/crd/kubernetes_http.go | 7 ++++++- pkg/provider/kubernetes/ingress/kubernetes.go | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/pkg/provider/kubernetes/crd/kubernetes_http.go b/pkg/provider/kubernetes/crd/kubernetes_http.go index 2a6f13b13..bd894fe3d 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_http.go +++ b/pkg/provider/kubernetes/crd/kubernetes_http.go @@ -209,8 +209,13 @@ func loadServers(client Client, namespace string, svc v1alpha1.Service) ([]dynam var servers []dynamic.Server if service.Spec.Type == corev1.ServiceTypeExternalName { + protocol := "http" + if portSpec.Port == 443 || strings.HasPrefix(portSpec.Name, "https") { + protocol = "https" + } + servers = append(servers, dynamic.Server{ - URL: fmt.Sprintf("http://%s:%d", service.Spec.ExternalName, portSpec.Port), + URL: fmt.Sprintf("%s://%s:%d", protocol, service.Spec.ExternalName, portSpec.Port), }) } else { endpoints, endpointsExists, endpointsErr := client.GetEndpoints(namespace, svc.Name) diff --git a/pkg/provider/kubernetes/ingress/kubernetes.go b/pkg/provider/kubernetes/ingress/kubernetes.go index 403069895..2c47bbc1c 100644 --- a/pkg/provider/kubernetes/ingress/kubernetes.go +++ b/pkg/provider/kubernetes/ingress/kubernetes.go @@ -203,8 +203,13 @@ func loadService(client Client, namespace string, backend v1beta1.IngressBackend } if service.Spec.Type == corev1.ServiceTypeExternalName { + protocol := "http" + if portSpec.Port == 443 || strings.HasPrefix(portSpec.Name, "https") { + protocol = "https" + } + servers = append(servers, dynamic.Server{ - URL: fmt.Sprintf("http://%s:%d", service.Spec.ExternalName, portSpec.Port), + URL: fmt.Sprintf("%s://%s:%d", protocol, service.Spec.ExternalName, portSpec.Port), }) } else { endpoints, endpointsExists, endpointsErr := client.GetEndpoints(namespace, backend.ServiceName) From 3884a68889e0419373e637cf03f53471b57ac07c Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Fri, 18 Oct 2019 11:30:05 +0200 Subject: [PATCH 13/40] fix: add stacktrace when recover. --- pkg/middlewares/recovery/recovery.go | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/pkg/middlewares/recovery/recovery.go b/pkg/middlewares/recovery/recovery.go index 563d52e66..b7e83f673 100644 --- a/pkg/middlewares/recovery/recovery.go +++ b/pkg/middlewares/recovery/recovery.go @@ -3,6 +3,7 @@ package recovery import ( "context" "net/http" + "runtime" "github.com/containous/traefik/v2/pkg/log" "github.com/containous/traefik/v2/pkg/middlewares" @@ -28,13 +29,30 @@ func New(ctx context.Context, next http.Handler, name string) (http.Handler, err } func (re *recovery) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - defer recoverFunc(middlewares.GetLoggerCtx(req.Context(), re.name, typeName), rw) + defer recoverFunc(middlewares.GetLoggerCtx(req.Context(), re.name, typeName), rw, req) re.next.ServeHTTP(rw, req) } -func recoverFunc(ctx context.Context, rw http.ResponseWriter) { +func recoverFunc(ctx context.Context, rw http.ResponseWriter, r *http.Request) { if err := recover(); err != nil { - log.FromContext(ctx).Errorf("Recovered from panic in http handler: %+v", err) + if !shouldLogPanic(err) { + log.FromContext(ctx).Debugf("Request has been aborted [%s - %s]: %v", r.RemoteAddr, r.URL, err) + return + } + + log.FromContext(ctx).Errorf("Recovered from panic in HTTP handler [%s - %s]: %+v", r.RemoteAddr, r.URL, err) + + const size = 64 << 10 + buf := make([]byte, size) + buf = buf[:runtime.Stack(buf, false)] + log.FromContext(ctx).Errorf("Stack: %s", buf) + http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } } + +// https://github.com/golang/go/blob/a0d6420d8be2ae7164797051ec74fa2a2df466a1/src/net/http/server.go#L1761-L1775 +// https://github.com/golang/go/blob/c33153f7b416c03983324b3e8f869ce1116d84bc/src/net/http/httputil/reverseproxy.go#L284 +func shouldLogPanic(panicValue interface{}) bool { + return panicValue != nil && panicValue != http.ErrAbortHandler +} From d1c3372dc40e6e6a995c504fbe8d4b6dbcb9f057 Mon Sep 17 00:00:00 2001 From: remche Date: Fri, 18 Oct 2019 11:50:05 +0200 Subject: [PATCH 14/40] fix ForwardAuth tls.skipverify examples --- docs/content/middlewares/forwardauth.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/content/middlewares/forwardauth.md b/docs/content/middlewares/forwardauth.md index fd8324756..41b52a44b 100644 --- a/docs/content/middlewares/forwardauth.md +++ b/docs/content/middlewares/forwardauth.md @@ -474,7 +474,8 @@ metadata: spec: forwardAuth: address: https://authserver.com/auth - insecureSkipVerify: true + tls: + insecureSkipVerify: true ``` ```json tab="Marathon" @@ -492,7 +493,8 @@ labels: [http.middlewares] [http.middlewares.test-auth.forwardAuth] address = "https://authserver.com/auth" - insecureSkipVerify: true + [http.middlewares.test-auth.forwardAuth.tls] + insecureSkipVerify: true ``` ```yaml tab="File (YAML)" @@ -501,5 +503,6 @@ http: test-auth: forwardAuth: address: "https://authserver.com/auth" - insecureSkipVerify: true + tls: + insecureSkipVerify: true ``` From 2042fdf3bd1d5ba1b4abcddc594cbb6c12d4bff2 Mon Sep 17 00:00:00 2001 From: sumarsono Date: Mon, 21 Oct 2019 04:40:03 +0700 Subject: [PATCH 15/40] fix typo for stripPrefix in tab File (YAML) --- docs/content/migration/v1-to-v2.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/content/migration/v1-to-v2.md b/docs/content/migration/v1-to-v2.md index b2a6d2a3d..d98318e51 100644 --- a/docs/content/migration/v1-to-v2.md +++ b/docs/content/migration/v1-to-v2.md @@ -624,8 +624,9 @@ with the path `/admin` stripped, e.g. to `http://:/`. In this case, yo middlewares: admin-stripprefix: - addPrefix: - prefix: "/admin" + stripPrefix: + prefixes: + - "/admin" # ... ``` From 9179aa52cf6fd542d191507c33e143695b935231 Mon Sep 17 00:00:00 2001 From: Florian Perrot <2372161+FlorianPerrot@users.noreply.github.com> Date: Wed, 23 Oct 2019 11:48:05 +0200 Subject: [PATCH 16/40] Fix Security Headers Doc --- docs/content/middlewares/headers.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/content/middlewares/headers.md b/docs/content/middlewares/headers.md index 20fdffcc8..5ffdd7640 100644 --- a/docs/content/middlewares/headers.md +++ b/docs/content/middlewares/headers.md @@ -162,8 +162,8 @@ labels: ```toml tab="File (TOML)" [http.middlewares] [http.middlewares.testHeader.headers] - FrameDeny = true - SSLRedirect = true + frameDeny = true + sslRedirect = true ``` ```yaml tab="File (YAML)" @@ -171,8 +171,8 @@ http: middlewares: testHeader: headers: - FrameDeny: true - SSLRedirect: true + frameDeny: true + sslRedirect: true ``` ### CORS Headers From c8984e6a6abdc8feb304e9e27db6f86f55c7ce77 Mon Sep 17 00:00:00 2001 From: Sylvain Rabot Date: Thu, 24 Oct 2019 01:10:04 +0200 Subject: [PATCH 17/40] Use debug for log about skipping addition of cert --- pkg/tls/certificate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/tls/certificate.go b/pkg/tls/certificate.go index 4a43f2a2c..1e700f111 100644 --- a/pkg/tls/certificate.go +++ b/pkg/tls/certificate.go @@ -189,7 +189,7 @@ func (c *Certificate) AppendCertificate(certs map[string]map[string]*tls.Certifi } } if certExists { - log.Warnf("Skipping addition of certificate for domain(s) %q, to EntryPoint %s, as it already exists for this Entrypoint.", certKey, ep) + log.Debugf("Skipping addition of certificate for domain(s) %q, to EntryPoint %s, as it already exists for this Entrypoint.", certKey, ep) } else { log.Debugf("Adding certificate for domain(s) %s", certKey) certs[ep][certKey] = &tlsCert From a6cdd701e2dbf0be899a574566e5c593006dba08 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 24 Oct 2019 10:02:06 +0200 Subject: [PATCH 18/40] Set proxy protocol logger to DEBUG level --- pkg/server/server_entrypoint_tcp.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pkg/server/server_entrypoint_tcp.go b/pkg/server/server_entrypoint_tcp.go index 59db9ba85..51043403d 100644 --- a/pkg/server/server_entrypoint_tcp.go +++ b/pkg/server/server_entrypoint_tcp.go @@ -254,6 +254,15 @@ func (ln tcpKeepAliveListener) Accept() (net.Conn, error) { return tc, nil } +type proxyProtocolLogger struct { + log.Logger +} + +// Printf force log level to debug. +func (p proxyProtocolLogger) Printf(format string, v ...interface{}) { + p.Debugf(format, v...) +} + func buildProxyProtocolListener(ctx context.Context, entryPoint *static.EntryPoint, listener net.Listener) (net.Listener, error) { var sourceCheck func(addr net.Addr) (bool, error) if entryPoint.ProxyProtocol.Insecure { @@ -280,7 +289,7 @@ func buildProxyProtocolListener(ctx context.Context, entryPoint *static.EntryPoi return proxyprotocol.NewDefaultListener(listener). WithSourceChecker(sourceCheck). - WithLogger(log.FromContext(ctx)), nil + WithLogger(proxyProtocolLogger{Logger: log.FromContext(ctx)}), nil } func buildListener(ctx context.Context, entryPoint *static.EntryPoint) (net.Listener, error) { From 2b00ab3432ea60b0a0b6037fdbf0904e75140505 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Fri, 25 Oct 2019 14:02:09 +0200 Subject: [PATCH 19/40] fix: skip akamai url verify. --- docs/scripts/verify.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/scripts/verify.sh b/docs/scripts/verify.sh index 5fe02c155..b7830b24c 100755 --- a/docs/scripts/verify.sh +++ b/docs/scripts/verify.sh @@ -21,7 +21,7 @@ find "${PATH_TO_SITE}" -type f -not -path "/app/site/theme/*" \ --check_external_hash \ --alt_ignore="/traefik.logo.png/" \ --http_status_ignore="0,500,501,503" \ - --url_ignore="/https://groups.google.com/a/traefik.io/forum/#!forum/security/,/localhost:/,/127.0.0.1:/,/fonts.gstatic.com/,/.minikube/,/github.com\/containous\/traefik\/*edit*/,/github.com\/containous\/traefik\/$/,/docs.traefik.io/,/github\.com\/golang\/oauth2\/blob\/36a7019397c4c86cf59eeab3bc0d188bac444277\/.+/" \ + --url_ignore="/https://groups.google.com/a/traefik.io/forum/#!forum/security/,/localhost:/,/127.0.0.1:/,/fonts.gstatic.com/,/.minikube/,/github.com\/containous\/traefik\/*edit*/,/github.com\/containous\/traefik\/$/,/docs.traefik.io/,/github\.com\/golang\/oauth2\/blob\/36a7019397c4c86cf59eeab3bc0d188bac444277\/.+/,/www.akamai.com/" \ '{}' 1>/dev/null ## HTML-proofer options at https://github.com/gjtorikian/html-proofer#configuration From 3747eb59eac703aab2cfc789034fe5586e286b2a Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Fri, 25 Oct 2019 14:40:05 +0200 Subject: [PATCH 20/40] fix: deep copy of passHostHeader on ServersLoadBalancer. --- pkg/config/dynamic/zz_generated.deepcopy.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/config/dynamic/zz_generated.deepcopy.go b/pkg/config/dynamic/zz_generated.deepcopy.go index 36635949d..5e3285895 100644 --- a/pkg/config/dynamic/zz_generated.deepcopy.go +++ b/pkg/config/dynamic/zz_generated.deepcopy.go @@ -973,6 +973,11 @@ func (in *ServersLoadBalancer) DeepCopyInto(out *ServersLoadBalancer) { *out = new(HealthCheck) (*in).DeepCopyInto(*out) } + if in.PassHostHeader != nil { + in, out := &in.PassHostHeader, &out.PassHostHeader + *out = new(bool) + **out = **in + } if in.ResponseForwarding != nil { in, out := &in.ResponseForwarding, &out.ResponseForwarding *out = new(ResponseForwarding) From 5327ce543b9853131b77ba01d363f3db87df9952 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Fri, 25 Oct 2019 15:46:05 +0200 Subject: [PATCH 21/40] Remove unnecessary reload of the configuration. --- pkg/provider/kubernetes/crd/kubernetes.go | 12 ++++++++---- pkg/provider/kubernetes/ingress/kubernetes.go | 12 ++++++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/pkg/provider/kubernetes/crd/kubernetes.go b/pkg/provider/kubernetes/crd/kubernetes.go index 7c7d59a74..73f9062fe 100644 --- a/pkg/provider/kubernetes/crd/kubernetes.go +++ b/pkg/provider/kubernetes/crd/kubernetes.go @@ -7,7 +7,6 @@ import ( "crypto/sha256" "fmt" "os" - "reflect" "sort" "strconv" "strings" @@ -21,6 +20,7 @@ import ( "github.com/containous/traefik/v2/pkg/safe" "github.com/containous/traefik/v2/pkg/tls" "github.com/containous/traefik/v2/pkg/types" + "github.com/mitchellh/hashstructure" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" ) @@ -127,10 +127,14 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. // track more information about the dropped events. conf := p.loadConfigurationFromCRD(ctxLog, k8sClient) - if reflect.DeepEqual(p.lastConfiguration.Get(), conf) { + confHash, err := hashstructure.Hash(conf, nil) + switch { + case err != nil: + logger.Error("Unable to hash the configuration") + case p.lastConfiguration.Get() == confHash: logger.Debugf("Skipping Kubernetes event kind %T", event) - } else { - p.lastConfiguration.Set(conf) + default: + p.lastConfiguration.Set(confHash) configurationChan <- dynamic.Message{ ProviderName: "kubernetescrd", Configuration: conf, diff --git a/pkg/provider/kubernetes/ingress/kubernetes.go b/pkg/provider/kubernetes/ingress/kubernetes.go index 2c47bbc1c..f81bf6369 100644 --- a/pkg/provider/kubernetes/ingress/kubernetes.go +++ b/pkg/provider/kubernetes/ingress/kubernetes.go @@ -6,7 +6,6 @@ import ( "fmt" "math" "os" - "reflect" "sort" "strconv" "strings" @@ -20,6 +19,7 @@ import ( "github.com/containous/traefik/v2/pkg/safe" "github.com/containous/traefik/v2/pkg/tls" "github.com/containous/traefik/v2/pkg/types" + "github.com/mitchellh/hashstructure" corev1 "k8s.io/api/core/v1" "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/labels" @@ -139,10 +139,14 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. // track more information about the dropped events. conf := p.loadConfigurationFromIngresses(ctxLog, k8sClient) - if reflect.DeepEqual(p.lastConfiguration.Get(), conf) { + confHash, err := hashstructure.Hash(conf, nil) + switch { + case err != nil: + logger.Error("Unable to hash the configuration") + case p.lastConfiguration.Get() == confHash: logger.Debugf("Skipping Kubernetes event kind %T", event) - } else { - p.lastConfiguration.Set(conf) + default: + p.lastConfiguration.Set(confHash) configurationChan <- dynamic.Message{ ProviderName: "kubernetes", Configuration: conf, From d22bd5b42d304767e68c3f180e0f965370f9ab5c Mon Sep 17 00:00:00 2001 From: Sylvain Rabot Date: Fri, 25 Oct 2019 16:48:06 +0200 Subject: [PATCH 22/40] Fix ldflags using incorrect pkg url --- script/binary | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/script/binary b/script/binary index 82c6ebe3b..8d407c36c 100755 --- a/script/binary +++ b/script/binary @@ -28,7 +28,7 @@ fi # Build binaries # shellcheck disable=SC2086 CGO_ENABLED=0 GOGC=off go build ${FLAGS[*]} -ldflags "-s -w \ - -X github.com/containous/traefik/pkg/v2/version.Version=$VERSION \ - -X github.com/containous/traefik/pkg/v2/version.Codename=$CODENAME \ - -X github.com/containous/traefik/pkg/v2/version.BuildDate=$DATE" \ + -X github.com/containous/traefik/v2/pkg/version.Version=$VERSION \ + -X github.com/containous/traefik/v2/pkg/version.Codename=$CODENAME \ + -X github.com/containous/traefik/v2/pkg/version.BuildDate=$DATE" \ -a -installsuffix nocgo -o dist/traefik ./cmd/traefik From 355fe6195e77ef23050a5a53b97a6cd4e0f35ce0 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Fri, 25 Oct 2019 17:16:05 +0200 Subject: [PATCH 23/40] Add documentation about backtick for rule definition. --- docs/content/routing/routers/index.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/content/routing/routers/index.md b/docs/content/routing/routers/index.md index 22186a5c0..d9290d28f 100644 --- a/docs/content/routing/routers/index.md +++ b/docs/content/routing/routers/index.md @@ -203,9 +203,14 @@ If you want to limit the router scope to a set of entry points, set the `entryPo ### Rule -Rules are a set of matchers that determine if a particular request matches specific criteria. +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. +??? tip "Backticks or Quotes?" + To set the value of a rule, use [backticks](https://en.wiktionary.org/wiki/backtick) ``` ` ``` or escaped double-quotes `\"`. + + Single quotes `'` are not accepted as values are [Golang's String Literals](https://golang.org/ref/spec#String_literals). + !!! example "Host is traefik.io" ```toml From 1f734630b95228dc845a83536a5de19314dc193e Mon Sep 17 00:00:00 2001 From: Damien Duportal Date: Fri, 25 Oct 2019 17:32:04 +0200 Subject: [PATCH 24/40] Improve documentation of the router rules for API and dashboard --- docs/content/operations/.markdownlint.json | 4 + docs/content/operations/api.md | 58 ++++++++++--- docs/content/operations/dashboard.md | 99 ++++++++++++++++++++-- 3 files changed, 142 insertions(+), 19 deletions(-) create mode 100644 docs/content/operations/.markdownlint.json diff --git a/docs/content/operations/.markdownlint.json b/docs/content/operations/.markdownlint.json new file mode 100644 index 000000000..3cd5e9a07 --- /dev/null +++ b/docs/content/operations/.markdownlint.json @@ -0,0 +1,4 @@ +{ + "extends": "../../.markdownlint.json", + "MD046": false +} diff --git a/docs/content/operations/api.md b/docs/content/operations/api.md index 24911b440..f1500293a 100644 --- a/docs/content/operations/api.md +++ b/docs/content/operations/api.md @@ -14,7 +14,7 @@ In production, it should be at least secured by authentication and authorization A good sane default (non exhaustive) set of recommendations would be to apply the following protection mechanisms: -* At the transport level: +* At the transport level: NOT publicly exposing the API's port, keeping it restricted to internal networks (as in the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege), applied to networks). @@ -23,13 +23,16 @@ would be to apply the following protection mechanisms: If you enable the API, a new special `service` named `api@internal` is created and can then be referenced in a router. -To enable the API handler: +To enable the API handler, use the following option on the +[static configuration](../getting-started/configuration-overview.md#the-static-configuration): ```toml tab="File (TOML)" +# Static Configuration [api] ``` ```yaml tab="File (YAML)" +# Static Configuration api: {} ``` @@ -37,11 +40,13 @@ api: {} --api=true ``` -And then you will be able to reference it like this: +And then define a routing configuration on Traefik itself with the +[dynamic configuration](../getting-started/configuration-overview.md#the-dynamic-configuration): ```yaml tab="Docker" +# Dynamic Configuration labels: - - "traefik.http.routers.api.rule=PathPrefix(`/api`) || PathPrefix(`/dashboard`)" + - "traefik.http.routers.api.rule=Host(`traefik.domain.com`) - "traefik.http.routers.api.service=api@internal" - "traefik.http.routers.api.middlewares=auth" - "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" @@ -49,40 +54,42 @@ labels: ```json tab="Marathon" "labels": { - "traefik.http.routers.api.rule": "PathPrefix(`/api`) || PathPrefix(`/dashboard`)" - "traefik.http.routers.api.service": "api@internal" - "traefik.http.routers.api.middlewares": "auth" + "traefik.http.routers.api.rule": "Host(`traefik.domain.com`)", + "traefik.http.routers.api.service": "api@internal", + "traefik.http.routers.api.middlewares": "auth", "traefik.http.middlewares.auth.basicauth.users": "test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" } ``` ```yaml tab="Rancher" -# Declaring the user list +# Dynamic Configuration labels: - - "traefik.http.routers.api.rule=PathPrefix(`/api`) || PathPrefix(`/dashboard`)" + - "traefik.http.routers.api.rule=Host(`traefik.domain.com`) - "traefik.http.routers.api.service=api@internal" - "traefik.http.routers.api.middlewares=auth" - "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" ``` ```toml tab="File (TOML)" +# Dynamic Configuration [http.routers.my-api] - rule="PathPrefix(`/api`) || PathPrefix(`/dashboard`)" + rule="Host(`traefik.domain.com`) service="api@internal" middlewares=["auth"] [http.middlewares.auth.basicAuth] users = [ - "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", + "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", ] ``` ```yaml tab="File (YAML)" +# Dynamic Configuration http: routers: api: - rule: PathPrefix(`/api`) || PathPrefix(`/dashboard`) + rule: Host(`traefik.domain.com`) service: api@internal middlewares: - auth @@ -90,10 +97,32 @@ http: auth: basicAuth: users: - - "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" + - "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" - "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" ``` +??? warning "The router's [rule](../../routing/routers#rule) must catch requests for the URI path `/api`" + Using an "Host" rule is recommended, by catching all the incoming traffic on this host domain to the API. + However, you can also use "path prefix" rule or any combination or rules. + + ```bash tab="Host Rule" + # Matches http://traefik.domain.com, http://traefik.domain.com/api + # or http://traefik.domain.com/hello + rule = "Host(`traefik.domain.com`)" + ``` + + ```bash tab="Path Prefix Rule" + # Matches http://api.traefik.domain.com/api or http://domain.com/api + # but does not match http://api.traefik.domain.com/hello + rule = "PathPrefix(`/api`)" + ``` + + ```bash tab="Combination of Rules" + # Matches http://traefik.domain.com/api or http://traefik.domain.com/dashboard + # but does not match http://traefik.domain.com/hello + rule = "Host(`traefik.domain.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))" + ``` + ### `insecure` Enable the API in `insecure` mode, which means that the API will be available directly on the entryPoint named `traefik`. @@ -135,6 +164,9 @@ api: --api.dashboard=true ``` +!!! warning "With Dashboard enabled, the router [rule](../../routing/routers#rule) must catch requests for both `/api` and `/dashboard`" + Please check the [Dashboard documentation](./dashboard.md#dashboard-router-rule) to learn more about this and to get examples. + ### `debug` _Optional, Default=false_ diff --git a/docs/content/operations/dashboard.md b/docs/content/operations/dashboard.md index 9dc77bb5e..169e136f2 100644 --- a/docs/content/operations/dashboard.md +++ b/docs/content/operations/dashboard.md @@ -28,7 +28,8 @@ There are 2 ways to configure and access the dashboard: This is the **recommended** method. -Start by enabling the dashboard by using the following option from [Traefik's API](./api.md): +Start by enabling the dashboard by using the following option from [Traefik's API](./api.md) +on the [static configuration](../getting-started/configuration-overview.md#the-static-configuration): ```toml tab="File (TOML)" [api] @@ -59,17 +60,103 @@ api: --api.dashboard=true ``` -Then specify a router associated to the service `api@internal` to allow: +Then define a routing configuration on Traefik itself, +with a router attached to the service `api@internal` in the +[dynamic configuration](../getting-started/configuration-overview.md#the-dynamic-configuration), +to allow defining: -- Defining one or more security features through [middlewares](../middlewares/overview.md) +- One or more security features through [middlewares](../middlewares/overview.md) like authentication ([basicAuth](../middlewares/basicauth.md) , [digestAuth](../middlewares/digestauth.md), [forwardAuth](../middlewares/forwardauth.md)) or [whitelisting](../middlewares/ipwhitelist.md). -- Defining your own [HTTP routing rule](../../routing/routers/#rule) for accessing the dashboard, +- A [router rule](#dashboard-router-rule) for accessing the dashboard, through Traefik itself (sometimes referred as "Traefik-ception"). -Please visit the ["Configuration" section of the API documentation](./api.md#configuration) -to learn about configuring a router with the service `api@internal` and enabling the security features. +??? example "Dashboard Dynamic Configuration Examples" + + ```yaml tab="Docker" + # Dynamic Configuration + labels: + - "traefik.http.routers.api.rule=Host(`traefik.domain.com`) + - "traefik.http.routers.api.service=api@internal" + - "traefik.http.routers.api.middlewares=auth" + - "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" + ``` + + ```json tab="Marathon" + "labels": { + "traefik.http.routers.api.rule": "Host(`traefik.domain.com`)", + "traefik.http.routers.api.service": "api@internal", + "traefik.http.routers.api.middlewares": "auth", + "traefik.http.middlewares.auth.basicauth.users": "test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" + } + ``` + + ```yaml tab="Rancher" + # Dynamic Configuration + labels: + - "traefik.http.routers.api.rule=Host(`traefik.domain.com`) + - "traefik.http.routers.api.service=api@internal" + - "traefik.http.routers.api.middlewares=auth" + - "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" + ``` + + ```toml tab="File (TOML)" + # Dynamic Configuration + [http.routers.my-api] + rule="Host(`traefik.domain.com`) + service="api@internal" + middlewares=["auth"] + + [http.middlewares.auth.basicAuth] + users = [ + "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", + "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", + ] + ``` + + ```yaml tab="File (YAML)" + # Dynamic Configuration + http: + routers: + api: + rule: Host(`traefik.domain.com`) + service: api@internal + middlewares: + - auth + middlewares: + auth: + basicAuth: + users: + - "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" + - "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" + ``` + +### Dashboard Router Rule + +As underlined in the [documentation for the `api.dashboard` option](./api.md#dashboard), +the [router rule](../routing/routers/index.md#rule) defined for Traefik must match +the path prefixes `/api` and `/dashboard`. + +We recommend to use a "Host Based rule" as ```Host(`traefik.domain.com`)``` to match everything on the host domain, +or to make sure that the defined rule captures both prefixes: + +```bash tab="Host Rule" +# Matches http://traefik.domain.com/api or http://traefik.domain.com/dashboard +rule = "Host(`traefik.domain.com`)" +``` + +```bash tab="Path Prefix Rule" +# Matches http://traefik.domain.com/api , http://domain.com/api or http://traefik.domain.com/dashboard +# but does not match http://traefik.domain.com/hello +rule = "PathPrefix(`/api`) || PathPrefix(`/dashboard`)" +``` + +```bash tab="Combination of Rules" +# Matches http://traefik.domain.com/api or http://traefik.domain.com/dashboard +# but does not match http://traefik.domain.com/hello +rule = "Host(`traefik.domain.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))" +``` ## Insecure Mode From 743d772a804327e843a740a37040f37577e4b994 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 28 Oct 2019 11:04:05 +0100 Subject: [PATCH 25/40] doc: @ is not authorized in names definition. --- docs/content/providers/docker.md | 2 +- docs/content/routing/providers/docker.md | 6 ++++++ docs/content/routing/providers/marathon.md | 6 ++++++ docs/content/routing/providers/rancher.md | 6 ++++++ docs/content/routing/providers/service-by-label.md | 5 ++--- docs/content/routing/routers/index.md | 8 ++++++++ docs/content/routing/services/index.md | 4 ++-- 7 files changed, 31 insertions(+), 6 deletions(-) diff --git a/docs/content/providers/docker.md b/docs/content/providers/docker.md index 9e0715175..af39fc68b 100644 --- a/docs/content/providers/docker.md +++ b/docs/content/providers/docker.md @@ -128,7 +128,7 @@ Traefik requires access to the docker socket to get its dynamic configuration. ??? info "Resources about Docker's Security" - [KubeCon EU 2018 Keynote, Running with Scissors, from Liz Rice](https://www.youtube.com/watch?v=ltrV-Qmh3oY) - - [Don't expose the Docker socket (not even to a container)](https://www.lvh.io/posts/dont-expose-the-docker-socket-not-even-to-a-container.html) + - [Don't expose the Docker socket (not even to a container)](https://www.lvh.io/posts/dont-expose-the-docker-socket-not-even-to-a-container/) - [A thread on Stack Overflow about sharing the `/var/run/docker.sock` file](https://news.ycombinator.com/item?id=17983623) - [To DinD or not to DinD](https://blog.loof.fr/2018/01/to-dind-or-not-do-dind.html) diff --git a/docs/content/routing/providers/docker.md b/docs/content/routing/providers/docker.md index eade358c5..9fc796b87 100644 --- a/docs/content/routing/providers/docker.md +++ b/docs/content/routing/providers/docker.md @@ -129,6 +129,8 @@ add labels starting with `traefik.http.routers..` and follo For example, to change the rule, you could add the label ```traefik.http.routers.my-container.rule=Host(`mydomain.com`)```. +!!! warning "The character `@` is not authorized in the router name ``." + ??? info "`traefik.http.routers..rule`" See [rule](../routers/index.md#rule) for more information. @@ -217,6 +219,8 @@ add labels starting with `traefik.http.services..`, followe For example, to change the `passHostHeader` behavior, you'd add the label `traefik.http.services..loadbalancer.passhostheader=false`. +!!! warning "The character `@` is not authorized in the service name ``." + ??? info "`traefik.http.services..loadbalancer.server.port`" Registers a port. @@ -350,6 +354,8 @@ you'd write `traefik.http.middlewares.my-redirect.redirectscheme.scheme=https`. More information about available middlewares in the dedicated [middlewares section](../../middlewares/overview.md). +!!! warning "The character `@` is not authorized in the middleware name." + ??? example "Declaring and Referencing a Middleware" ```yaml diff --git a/docs/content/routing/providers/marathon.md b/docs/content/routing/providers/marathon.md index 10478c39e..72881f156 100644 --- a/docs/content/routing/providers/marathon.md +++ b/docs/content/routing/providers/marathon.md @@ -52,6 +52,8 @@ add labels starting with `traefik.http.routers.{router-name-of-your-choice}.` an For example, to change the routing rule, you could add the label ```"traefik.http.routers.routername.rule": "Host(`mydomain.com`)"```. +!!! warning "The character `@` is not authorized in the router name ``." + ??? info "`traefik.http.routers..rule`" See [rule](../routers/index.md#rule) for more information. @@ -139,6 +141,8 @@ add labels starting with `traefik.http.services.{service-name-of-your-choice}.`, For example, to change the passHostHeader behavior, you'd add the label `"traefik.http.services.servicename.loadbalancer.passhostheader": "false"`. +!!! warning "The character `@` is not authorized in the service name ``." + ??? info "`traefik.http.services..loadbalancer.server.port`" Registers a port. @@ -268,6 +272,8 @@ For example, to declare a middleware [`redirectscheme`](../../middlewares/redire More information about available middlewares in the dedicated [middlewares section](../../middlewares/overview.md). +!!! warning "The character `@` is not authorized in the middleware name." + ??? example "Declaring and Referencing a Middleware" ```json diff --git a/docs/content/routing/providers/rancher.md b/docs/content/routing/providers/rancher.md index 4adb45614..d523221f8 100644 --- a/docs/content/routing/providers/rancher.md +++ b/docs/content/routing/providers/rancher.md @@ -57,6 +57,8 @@ To update the configuration of the Router automatically attached to the containe For example, to change the rule, you could add the label ```traefik.http.routers.my-container.rule=Host(`mydomain.com`)```. +!!! warning "The character `@` is not authorized in the router name ``." + ??? info "`traefik.http.routers..rule`" See [rule](../routers/index.md#rule) for more information. @@ -145,6 +147,8 @@ add labels starting with `traefik.http.services.{name-of-your-choice}.`, followe For example, to change the `passHostHeader` behavior, you'd add the label `traefik.http.services.{name-of-your-choice}.loadbalancer.passhostheader=false`. +!!! warning "The character `@` is not authorized in the service name ``." + ??? info "`traefik.http.services..loadbalancer.server.port`" Registers a port. @@ -274,6 +278,8 @@ For example, to declare a middleware [`redirectscheme`](../../middlewares/redire More information about available middlewares in the dedicated [middlewares section](../../middlewares/overview.md). +!!! warning "The character `@` is not authorized in the middleware name." + ??? example "Declaring and Referencing a Middleware" ```yaml diff --git a/docs/content/routing/providers/service-by-label.md b/docs/content/routing/providers/service-by-label.md index bd16fd43e..611f1ad2e 100644 --- a/docs/content/routing/providers/service-by-label.md +++ b/docs/content/routing/providers/service-by-label.md @@ -7,9 +7,8 @@ There are, however, exceptions when using label-based configurations: and a label defines a service (e.g. implicitly through a loadbalancer server port value), but the router does not specify any service, then that service is automatically assigned to the router. -1. If a label defines a router (e.g. through a router Rule) -but no service is defined, then a service is automatically created -and assigned to the router. +1. If a label defines a router (e.g. through a router Rule) but no service is defined, +then a service is automatically created and assigned to the router. !!! info "" As one would expect, in either of these cases, if in addition a service is specified for the router, diff --git a/docs/content/routing/routers/index.md b/docs/content/routing/routers/index.md index d9290d28f..4e00a72cc 100644 --- a/docs/content/routing/routers/index.md +++ b/docs/content/routing/routers/index.md @@ -84,6 +84,8 @@ In the process, routers may use pieces of [middleware](../../middlewares/overvie ## Configuring HTTP Routers +!!! warning "The character `@` is not authorized in the router name" + ### EntryPoints If not specified, HTTP routers will accept requests from all defined entry points. @@ -342,6 +344,8 @@ A value of `0` for the priority is ignored: `priority = 0` means that the defaul You can attach a list of [middlewares](../../middlewares/overview.md) to each HTTP router. The middlewares will take effect only if the rule matches, and before forwarding the request to the service. +!!! warning "The character `@` is not authorized in the middleware name." + !!! tip "Middlewares order" Middlewares are applied in the same order as their declaration in **router**. @@ -381,6 +385,8 @@ but there are exceptions for label-based providers. See the specific [docker](../providers/docker.md#service-definition), [rancher](../providers/rancher.md#service-definition), or [marathon](../providers/marathon.md#service-definition) documentation. +!!! warning "The character `@` is not authorized in the middleware name." + !!! important "HTTP routers can only target HTTP services (not TCP services)." ### TLS @@ -629,6 +635,8 @@ The [supported `provider` table](../../https/acme.md#providers) indicates if the ## Configuring TCP Routers +!!! warning "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. diff --git a/docs/content/routing/services/index.md b/docs/content/routing/services/index.md index cd48b5ba8..212754fe0 100644 --- a/docs/content/routing/services/index.md +++ b/docs/content/routing/services/index.md @@ -346,7 +346,7 @@ By default, `passHostHeader` is true. loadBalancer: passHostHeader: false ``` - + #### Response Forwarding This section is about configuring how Traefik forwards the response from the backend server to the client. @@ -378,7 +378,7 @@ Below are the available options for the Response Forwarding mechanism: responseForwarding: flushInterval: 1s ``` - + ### Weighted Round Robin (service) The WRR is able to load balance the requests between multiple services based on weights. From a239e3fba6dcb9107204f5fce3cca9c961bcfe4d Mon Sep 17 00:00:00 2001 From: mpl Date: Thu, 12 Sep 2019 16:20:05 +0200 Subject: [PATCH 26/40] error pages: do not buffer response when it's not an error --- pkg/middlewares/customerrors/custom_errors.go | 159 ++++++++++++++++-- .../customerrors/custom_errors_test.go | 27 +++ 2 files changed, 169 insertions(+), 17 deletions(-) diff --git a/pkg/middlewares/customerrors/custom_errors.go b/pkg/middlewares/customerrors/custom_errors.go index 72c70a631..ee50f6dda 100644 --- a/pkg/middlewares/customerrors/custom_errors.go +++ b/pkg/middlewares/customerrors/custom_errors.go @@ -22,7 +22,10 @@ import ( ) // Compile time validation that the response recorder implements http interfaces correctly. -var _ middlewares.Stateful = &responseRecorderWithCloseNotify{} +var ( + _ middlewares.Stateful = &responseRecorderWithCloseNotify{} + _ middlewares.Stateful = &codeCatcherWithCloseNotify{} +) const ( typeName = "customError" @@ -80,25 +83,29 @@ func (c *customErrors) ServeHTTP(rw http.ResponseWriter, req *http.Request) { return } - recorder := newResponseRecorder(ctx, rw) - c.next.ServeHTTP(recorder, req) + catcher := newCodeCatcher(rw, c.httpCodeRanges) + c.next.ServeHTTP(catcher, req) + if !catcher.isFilteredCode() { + return + } // check the recorder code against the configured http status code ranges + code := catcher.getCode() for _, block := range c.httpCodeRanges { - if recorder.GetCode() >= block[0] && recorder.GetCode() <= block[1] { - logger.Errorf("Caught HTTP Status Code %d, returning error page", recorder.GetCode()) + if code >= block[0] && code <= block[1] { + logger.Errorf("Caught HTTP Status Code %d, returning error page", code) var query string if len(c.backendQuery) > 0 { query = "/" + strings.TrimPrefix(c.backendQuery, "/") - query = strings.Replace(query, "{status}", strconv.Itoa(recorder.GetCode()), -1) + query = strings.Replace(query, "{status}", strconv.Itoa(code), -1) } pageReq, err := newRequest(backendURL + query) if err != nil { logger.Error(err) - rw.WriteHeader(recorder.GetCode()) - _, err = fmt.Fprint(rw, http.StatusText(recorder.GetCode())) + rw.WriteHeader(code) + _, err = fmt.Fprint(rw, http.StatusText(code)) if err != nil { http.Error(rw, err.Error(), http.StatusInternalServerError) } @@ -111,7 +118,7 @@ func (c *customErrors) ServeHTTP(rw http.ResponseWriter, req *http.Request) { c.backendHandler.ServeHTTP(recorderErrorPage, pageReq.WithContext(req.Context())) utils.CopyHeaders(rw.Header(), recorderErrorPage.Header()) - rw.WriteHeader(recorder.GetCode()) + rw.WriteHeader(code) if _, err = rw.Write(recorderErrorPage.GetBody().Bytes()); err != nil { logger.Error(err) @@ -119,14 +126,6 @@ func (c *customErrors) ServeHTTP(rw http.ResponseWriter, req *http.Request) { return } } - - // did not catch a configured status code so proceed with the request - utils.CopyHeaders(rw.Header(), recorder.Header()) - rw.WriteHeader(recorder.GetCode()) - _, err := rw.Write(recorder.GetBody().Bytes()) - if err != nil { - http.Error(rw, err.Error(), http.StatusInternalServerError) - } } func newRequest(baseURL string) (*http.Request, error) { @@ -144,6 +143,132 @@ func newRequest(baseURL string) (*http.Request, error) { return req, nil } +type responseInterceptor interface { + http.ResponseWriter + http.Flusher + getCode() int + isFilteredCode() bool +} + +// codeCatcher is a response writer that detects as soon as possible whether the +// response is a code within the ranges of codes it watches for. If it is, it +// simply drops the data from the response. Otherwise, it forwards it directly to +// the original client (its responseWriter) without any buffering. +type codeCatcher struct { + headerMap http.Header + code int + httpCodeRanges types.HTTPCodeRanges + firstWrite bool + caughtFilteredCode bool + responseWriter http.ResponseWriter + headersSent bool +} + +type codeCatcherWithCloseNotify struct { + *codeCatcher +} + +// CloseNotify returns a channel that receives at most a +// single value (true) when the client connection has gone away. +func (cc *codeCatcherWithCloseNotify) CloseNotify() <-chan bool { + return cc.responseWriter.(http.CloseNotifier).CloseNotify() +} + +func newCodeCatcher(rw http.ResponseWriter, httpCodeRanges types.HTTPCodeRanges) responseInterceptor { + catcher := &codeCatcher{ + headerMap: make(http.Header), + code: http.StatusOK, // If backend does not call WriteHeader on us, we consider it's a 200. + responseWriter: rw, + httpCodeRanges: httpCodeRanges, + firstWrite: true, + } + if _, ok := rw.(http.CloseNotifier); ok { + return &codeCatcherWithCloseNotify{catcher} + } + return catcher +} + +func (cc *codeCatcher) Header() http.Header { + if cc.headerMap == nil { + cc.headerMap = make(http.Header) + } + + return cc.headerMap +} + +func (cc *codeCatcher) getCode() int { + return cc.code +} + +// isFilteredCode returns whether the codeCatcher received a response code among the ones it is watching, +// and for which the response should be deferred to the error handler. +func (cc *codeCatcher) isFilteredCode() bool { + return cc.caughtFilteredCode +} + +func (cc *codeCatcher) Write(buf []byte) (int, error) { + if !cc.firstWrite { + if cc.caughtFilteredCode { + // We don't care about the contents of the response, + // since we want to serve the ones from the error page, + // so we just drop them. + return len(buf), nil + } + return cc.responseWriter.Write(buf) + } + cc.firstWrite = false + + // If WriteHeader was already called from the caller, this is a NOOP. + // Otherwise, cc.code is actually a 200 here. + cc.WriteHeader(cc.code) + + if cc.caughtFilteredCode { + return len(buf), nil + } + return cc.responseWriter.Write(buf) +} + +func (cc *codeCatcher) WriteHeader(code int) { + if cc.headersSent || cc.caughtFilteredCode { + return + } + + cc.code = code + for _, block := range cc.httpCodeRanges { + if cc.code >= block[0] && cc.code <= block[1] { + cc.caughtFilteredCode = true + break + } + } + // it will be up to the other response recorder to send the headers, + // so it is out of our hands now. + if cc.caughtFilteredCode { + return + } + utils.CopyHeaders(cc.responseWriter.Header(), cc.Header()) + cc.responseWriter.WriteHeader(cc.code) + cc.headersSent = true +} + +// Hijack hijacks the connection +func (cc *codeCatcher) Hijack() (net.Conn, *bufio.ReadWriter, error) { + if hj, ok := cc.responseWriter.(http.Hijacker); ok { + return hj.Hijack() + } + return nil, nil, fmt.Errorf("%T is not a http.Hijacker", cc.responseWriter) +} + +// Flush sends any buffered data to the client. +func (cc *codeCatcher) Flush() { + // If WriteHeader was already called from the caller, this is a NOOP. + // Otherwise, cc.code is actually a 200 here. + cc.WriteHeader(cc.code) + + if flusher, ok := cc.responseWriter.(http.Flusher); ok { + flusher.Flush() + } +} + type responseRecorder interface { http.ResponseWriter http.Flusher diff --git a/pkg/middlewares/customerrors/custom_errors_test.go b/pkg/middlewares/customerrors/custom_errors_test.go index 5dbb22f30..58a3a1673 100644 --- a/pkg/middlewares/customerrors/custom_errors_test.go +++ b/pkg/middlewares/customerrors/custom_errors_test.go @@ -33,6 +33,30 @@ func TestHandler(t *testing.T) { assert.Contains(t, recorder.Body.String(), http.StatusText(http.StatusOK)) }, }, + { + desc: "no error, but not a 200", + errorPage: &dynamic.ErrorPage{Service: "error", Query: "/test", Status: []string{"500-501", "503-599"}}, + backendCode: http.StatusPartialContent, + backendErrorHandler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, "My error page.") + }), + validate: func(t *testing.T, recorder *httptest.ResponseRecorder) { + assert.Equal(t, http.StatusPartialContent, recorder.Code, "HTTP status") + assert.Contains(t, recorder.Body.String(), http.StatusText(http.StatusPartialContent)) + }, + }, + { + desc: "a 304, so no Write called", + errorPage: &dynamic.ErrorPage{Service: "error", Query: "/test", Status: []string{"500-501", "503-599"}}, + backendCode: http.StatusNotModified, + backendErrorHandler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, "whatever, should not be called") + }), + validate: func(t *testing.T, recorder *httptest.ResponseRecorder) { + assert.Equal(t, http.StatusNotModified, recorder.Code, "HTTP status") + assert.Contains(t, recorder.Body.String(), "") + }, + }, { desc: "in the range", errorPage: &dynamic.ErrorPage{Service: "error", Query: "/test", Status: []string{"500-501", "503-599"}}, @@ -104,6 +128,9 @@ func TestHandler(t *testing.T) { handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(test.backendCode) + if test.backendCode == http.StatusNotModified { + return + } fmt.Fprintln(w, http.StatusText(test.backendCode)) }) errorPageHandler, err := New(context.Background(), handler, *test.errorPage, serviceBuilderMock, "test") From 43e5092c4608504e828d8242073b19570e76af43 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Thu, 12 Sep 2019 18:10:05 +0200 Subject: [PATCH 27/40] Prepare release v1.7.15 --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dfc989d2c..93d1f5bd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -414,6 +414,23 @@ - fix a service with one server .yaml example ([#5373](https://github.com/containous/traefik/pull/5373) by [zaverden](https://github.com/zaverden)) - fix: services configuration documentation. ([#5359](https://github.com/containous/traefik/pull/5359) by [ldez](https://github.com/ldez)) +## [v1.7.15](https://github.com/containous/traefik/tree/v1.7.15) (2019-09-12) +[All Commits](https://github.com/containous/traefik/compare/v1.7.14...v1.7.15) + +**Bug fixes:** +- **[authentication,k8s/ingress]** Kubernetes support for Auth.HeaderField ([#5235](https://github.com/containous/traefik/pull/5235) by [ErikWegner](https://github.com/ErikWegner)) +- **[k8s,k8s/ingress]** Finish kubernetes throttling refactoring ([#5269](https://github.com/containous/traefik/pull/5269) by [mpl](https://github.com/mpl)) +- **[k8s]** Throttle Kubernetes config refresh ([#4716](https://github.com/containous/traefik/pull/4716) by [benweissmann](https://github.com/benweissmann)) +- **[k8s]** Fix wrong handling of insecure tls auth forward ingress annotation ([#5319](https://github.com/containous/traefik/pull/5319) by [majkrzak](https://github.com/majkrzak)) +- **[middleware]** error pages: do not buffer response when it's not an error ([#5285](https://github.com/containous/traefik/pull/5285) by [mpl](https://github.com/mpl)) +- **[tls]** Consider default cert domain in certificate store ([#5353](https://github.com/containous/traefik/pull/5353) by [nrwiersma](https://github.com/nrwiersma)) +- **[tls]** Add TLS minversion constraint ([#5356](https://github.com/containous/traefik/pull/5356) by [dtomcej](https://github.com/dtomcej)) + +**Documentation:** +- **[acme]** Update Acme doc - Vultr Wildcard & Root ([#5320](https://github.com/containous/traefik/pull/5320) by [ddymko](https://github.com/ddymko)) +- **[consulcatalog]** Typo in basic auth usersFile label consul-catalog ([#5230](https://github.com/containous/traefik/pull/5230) by [pitan](https://github.com/pitan)) +- **[logs]** Improve Access Logs Documentation page ([#5238](https://github.com/containous/traefik/pull/5238) by [dduportal](https://github.com/dduportal)) + ## [v2.0.0-rc3](https://github.com/containous/traefik/tree/v2.0.0-rc3) (2019-09-10) [All Commits](https://github.com/containous/traefik/compare/v2.0.0-rc2...v2.0.0-rc3) From 5cd06c03f00192add5cfd2d6ba599fd72dbc36e0 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Fri, 13 Sep 2019 15:04:04 +0200 Subject: [PATCH 28/40] Prepare release v1.7.16 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93d1f5bd1..1ba816c30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -414,6 +414,12 @@ - fix a service with one server .yaml example ([#5373](https://github.com/containous/traefik/pull/5373) by [zaverden](https://github.com/zaverden)) - fix: services configuration documentation. ([#5359](https://github.com/containous/traefik/pull/5359) by [ldez](https://github.com/ldez)) +## [v1.7.16](https://github.com/containous/traefik/tree/v1.7.16) (2019-09-13) +[All Commits](https://github.com/containous/traefik/compare/v1.7.15...v1.7.16) + +**Bug fixes:** +- **[middleware,websocket]** implement Flusher and Hijacker for codeCatcher ([#5376](https://github.com/containous/traefik/pull/5376) by [mpl](https://github.com/mpl)) + ## [v1.7.15](https://github.com/containous/traefik/tree/v1.7.15) (2019-09-12) [All Commits](https://github.com/containous/traefik/compare/v1.7.14...v1.7.15) From 27a65f8745a1b9b151bb4cdc9ba54fb110eb6a67 Mon Sep 17 00:00:00 2001 From: Brad Jones Date: Thu, 19 Sep 2019 01:06:03 -0600 Subject: [PATCH 29/40] Add note clarifying client certificate header --- docs/content/middlewares/passtlsclientcert.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/content/middlewares/passtlsclientcert.md b/docs/content/middlewares/passtlsclientcert.md index 511adac35..9da4dbed0 100644 --- a/docs/content/middlewares/passtlsclientcert.md +++ b/docs/content/middlewares/passtlsclientcert.md @@ -219,7 +219,10 @@ PassTLSClientCert can add two headers to the request: - `X-Forwarded-Tls-Client-Cert-Info` that contains all the selected certificate information in an escaped string. !!! info - The headers are filled with escaped string so it can be safely placed inside a URL query. + + * The headers are filled with escaped string so it can be safely placed inside a URL query. + * These options only work accordingly to the [MutualTLS configuration](../https/tls.md#client-authentication-mtls). + That is to say, only the certificates that match the `clientAuth.clientAuthType` policy are passed. In the following example, you can see a complete certificate. We will use each part of it to explain the middleware options. From 770a7f11a79288fbaff19547cdc45fa4ee97888b Mon Sep 17 00:00:00 2001 From: Nicholas Wiersma Date: Mon, 23 Sep 2019 14:50:06 +0200 Subject: [PATCH 30/40] Avoid closing stdout when the accesslog handler is closed Co-authored-by: Ludovic Fernandez Co-authored-by: jlevesy --- pkg/middlewares/accesslog/logger.go | 31 +++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/pkg/middlewares/accesslog/logger.go b/pkg/middlewares/accesslog/logger.go index 1f6b80b4b..53bebac6e 100644 --- a/pkg/middlewares/accesslog/logger.go +++ b/pkg/middlewares/accesslog/logger.go @@ -3,6 +3,7 @@ package accesslog import ( "context" "fmt" + "io" "net" "net/http" "net/url" @@ -31,6 +32,19 @@ const ( JSONFormat string = "json" ) +type noopCloser struct { + *os.File +} + +func (n noopCloser) Write(p []byte) (int, error) { + return n.File.Write(p) +} + +func (n noopCloser) Close() error { + // noop + return nil +} + type handlerParams struct { logDataTable *LogData crr *captureRequestReader @@ -41,7 +55,7 @@ type handlerParams struct { type Handler struct { config *types.AccessLog logger *logrus.Logger - file *os.File + file io.WriteCloser mu sync.Mutex httpCodeRanges types.HTTPCodeRanges logHandlerChan chan handlerParams @@ -59,7 +73,7 @@ func WrapHandler(handler *Handler) alice.Constructor { // NewHandler creates a new Handler. func NewHandler(config *types.AccessLog) (*Handler, error) { - file := os.Stdout + var file io.WriteCloser = noopCloser{os.Stdout} if len(config.FilePath) > 0 { f, err := openAccessLogFile(config.FilePath) if err != nil { @@ -213,14 +227,15 @@ func (h *Handler) Close() error { // Rotate closes and reopens the log file to allow for rotation by an external source. func (h *Handler) Rotate() error { - var err error - - if h.file != nil { - defer func(f *os.File) { - f.Close() - }(h.file) + if h.config.FilePath == "" { + return nil } + if h.file != nil { + defer func(f io.Closer) { _ = f.Close() }(h.file) + } + + var err error h.file, err = os.OpenFile(h.config.FilePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0664) if err != nil { return err From cbecfad4dfc980f3f024cd3a990a227f3a325dd8 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 23 Sep 2019 19:48:04 +0200 Subject: [PATCH 31/40] Prepare release v1.7.17 --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ba816c30..edf6a52fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,6 +70,18 @@ - Add the router priority documentation ([#5481](https://github.com/containous/traefik/pull/5481) by [jbdoumenjou](https://github.com/jbdoumenjou)) - Improve the Migration Guide ([#5391](https://github.com/containous/traefik/pull/5391) by [jbdoumenjou](https://github.com/jbdoumenjou)) +## [v1.7.17](https://github.com/containous/traefik/tree/v1.7.17) (2019-09-23) +[All Commits](https://github.com/containous/traefik/compare/v1.7.16...v1.7.17) + +**Bug fixes:** +- **[logs,middleware]** Avoid closing stdout when the accesslog handler is closed ([#5459](https://github.com/containous/traefik/pull/5459) by [nrwiersma](https://github.com/nrwiersma)) +- **[middleware]** Actually send header and code during WriteHeader, if needed ([#5404](https://github.com/containous/traefik/pull/5404) by [mpl](https://github.com/mpl)) + +**Documentation:** +- **[k8s]** Add note clarifying client certificate header ([#5362](https://github.com/containous/traefik/pull/5362) by [bradjones1](https://github.com/bradjones1)) +- **[webui]** Update docs links. ([#5412](https://github.com/containous/traefik/pull/5412) by [ldez](https://github.com/ldez)) +- Update Traefik image version. ([#5399](https://github.com/containous/traefik/pull/5399) by [ldez](https://github.com/ldez)) + ## [v2.0.0](https://github.com/containous/traefik/tree/v2.0.0) (2019-09-16) [All Commits](https://github.com/containous/traefik/compare/v2.0.0-alpha1...v2.0.0) From d447a50b739bfb8794c176ca118dbcd1340b726d Mon Sep 17 00:00:00 2001 From: mpl Date: Thu, 26 Sep 2019 15:46:05 +0200 Subject: [PATCH 32/40] Prepare release v1.7.18 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index edf6a52fc..f56408d77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,6 +70,12 @@ - Add the router priority documentation ([#5481](https://github.com/containous/traefik/pull/5481) by [jbdoumenjou](https://github.com/jbdoumenjou)) - Improve the Migration Guide ([#5391](https://github.com/containous/traefik/pull/5391) by [jbdoumenjou](https://github.com/jbdoumenjou)) +## [v1.7.18](https://github.com/containous/traefik/tree/v1.7.18) (2019-09-23) +[All Commits](https://github.com/containous/traefik/compare/v1.7.17...v1.7.18) + +**Bug fixes:** +- **[go,security]** This version is compiled with [Go 1.12.10](https://groups.google.com/d/msg/golang-announce/cszieYyuL9Q/g4Z7pKaqAgAJ), which fixes a vulnerability in previous versions. See the [CVE](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-16276) about it for more details. + ## [v1.7.17](https://github.com/containous/traefik/tree/v1.7.17) (2019-09-23) [All Commits](https://github.com/containous/traefik/compare/v1.7.16...v1.7.17) From 4990f6c22ddb44d250f3e6a1013909ef344cf93c Mon Sep 17 00:00:00 2001 From: Daniel Tomcej Date: Fri, 25 Oct 2019 10:08:05 -0500 Subject: [PATCH 33/40] Allow Default Certificate to work on macOS 10.15 --- pkg/tls/generate/generate.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/tls/generate/generate.go b/pkg/tls/generate/generate.go index fd0744ade..8dbfa00aa 100644 --- a/pkg/tls/generate/generate.go +++ b/pkg/tls/generate/generate.go @@ -86,6 +86,7 @@ func derCert(privKey *rsa.PrivateKey, expiration time.Time, domain string) ([]by NotAfter: expiration, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageKeyAgreement | x509.KeyUsageDataEncipherment, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, DNSNames: []string{domain}, } From 8f000423ed8b92be4c35337bfaa0ae900aebc118 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 28 Oct 2019 12:26:05 +0100 Subject: [PATCH 34/40] fix: default tracing backend. --- pkg/server/server.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/server/server.go b/pkg/server/server.go index 234d66e0d..b7bc15817 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -94,8 +94,9 @@ func setupTracing(conf *static.Tracing) tracing.Backend { if backend == nil { log.WithoutContext().Debug("Could not initialize tracing, use Jaeger by default") - backend := &jaeger.Config{} - backend.SetDefaults() + bcd := &jaeger.Config{} + bcd.SetDefaults() + backend = bcd } return backend From f790b9aa546ba449218a929d3fcac5df3875bf53 Mon Sep 17 00:00:00 2001 From: Robert Baker <51850403+robertbaker@users.noreply.github.com> Date: Mon, 28 Oct 2019 07:50:06 -0700 Subject: [PATCH 35/40] Add example for changing the port used by traefik to connect to a service --- docs/content/routing/providers/docker.md | 187 ++++++++++-------- .../routing/services/.markdownlint.json | 3 +- docs/content/routing/services/index.md | 64 +++--- 3 files changed, 139 insertions(+), 115 deletions(-) diff --git a/docs/content/routing/providers/docker.md b/docs/content/routing/providers/docker.md index 9fc796b87..f81d0daaa 100644 --- a/docs/content/routing/providers/docker.md +++ b/docs/content/routing/providers/docker.md @@ -12,16 +12,16 @@ Attach labels to your containers and let Traefik do the rest! ??? example "Configuring Docker & Deploying / Exposing Services" Enabling the docker provider - + ```toml tab="File (TOML)" [providers.docker] ``` - + ```yaml tab="File (YAML)" providers: docker: {} ``` - + ```bash tab="CLI" --providers.docker=true ``` @@ -37,6 +37,27 @@ Attach labels to your containers and let Traefik do the rest! - traefik.http.routers.my-container.rule=Host(`mydomain.com`) ``` +??? example "Specify a Custom Port for the Container" + + Forward requests for `http://mydomain.com` to `http://:12345`: + + ```yaml + version: "3" + services: + my-container: + # ... + labels: + - traefik.http.routers.my-container.rule=Host(`mydomain.com`) + # Tell Traefik to use the port 12345 to connect to `my-container` + - traefik.http.services.my-service.loadbalancer.server.port=12345 + ``` + + !!! important "Traefik Connecting to the Wrong Port: `HTTP/502 Gateway Error`" + By default, Traefik uses the first exposed port of a container. + + Setting the label `raefik.http.services.xxx.loadbalancer.server.port` + overrides that behavior. + ??? example "Configuring Docker Swarm & Deploying / Exposing Services" Enabling the docker provider (Swarm Mode) @@ -49,7 +70,7 @@ Attach labels to your containers and let Traefik do the rest! endpoint = "tcp://127.0.0.1:2377" swarmMode = true ``` - + ```yaml tab="File (YAML)" providers: docker: @@ -59,7 +80,7 @@ Attach labels to your containers and let Traefik do the rest! endpoint: "tcp://127.0.0.1:2375" swarmMode: true ``` - + ```bash tab="CLI" --providers.docker.endpoint="tcp://127.0.0.1:2375" --providers.docker.swarmMode=true @@ -85,7 +106,7 @@ Attach labels to your containers and let Traefik do the rest! ## Routing Configuration !!! info "Labels" - + - Labels are case insensitive. - The complete list of labels can be found in [the reference page](../../reference/dynamic-configuration/docker.md). @@ -132,81 +153,81 @@ For example, to change the rule, you could add the label ```traefik.http.routers !!! warning "The character `@` is not authorized in the router name ``." ??? info "`traefik.http.routers..rule`" - - See [rule](../routers/index.md#rule) for more information. - + + See [rule](../routers/index.md#rule) for more information. + ```yaml - "traefik.http.routers.myrouter.rule=Host(`mydomain.com`)" ``` ??? info "`traefik.http.routers..entrypoints`" - - See [entry points](../routers/index.md#entrypoints) for more information. - + + See [entry points](../routers/index.md#entrypoints) for more information. + ```yaml - "traefik.http.routers.myrouter.entrypoints=web,websecure" ``` ??? info "`traefik.http.routers..middlewares`" - - See [middlewares](../routers/index.md#middlewares) and [middlewares overview](../../middlewares/overview.md) for more information. - + + See [middlewares](../routers/index.md#middlewares) and [middlewares overview](../../middlewares/overview.md) for more information. + ```yaml - "traefik.http.routers.myrouter.middlewares=auth,prefix,cb" ``` ??? info "`traefik.http.routers..service`" - - See [rule](../routers/index.md#service) for more information. - + + See [rule](../routers/index.md#service) for more information. + ```yaml - "traefik.http.routers.myrouter.service=myservice" ``` ??? info "`traefik.http.routers..tls`" - + See [tls](../routers/index.md#tls) for more information. - + ```yaml - "traefik.http.routers.myrouter.tls=true" ``` ??? info "`traefik.http.routers..tls.certresolver`" - + See [certResolver](../routers/index.md#certresolver) for more information. - + ```yaml - "traefik.http.routers.myrouter.tls.certresolver=myresolver" ``` ??? info "`traefik.http.routers..tls.domains[n].main`" - + See [domains](../routers/index.md#domains) for more information. - + ```yaml - "traefik.http.routers.myrouter.tls.domains[0].main=foobar.com" ``` ??? info "`traefik.http.routers..tls.domains[n].sans`" - + See [domains](../routers/index.md#domains) for more information. - + ```yaml - "traefik.http.routers.myrouter.tls.domains[0].sans=test.foobar.com,dev.foobar.com" ``` ??? info "`traefik.http.routers..tls.options`" - + See [options](../routers/index.md#options) for more information. - + ```yaml - "traefik.http.routers.myrouter.tls.options=foobar" ``` ??? info "`traefik.http.routers..priority`" - + See [options](../routers/index.md#priority) for more information. - + ```yaml - "traefik.http.routers.myrouter.priority=42" ``` @@ -222,124 +243,124 @@ you'd add the label `traefik.http.services..loadbalancer.pa !!! warning "The character `@` is not authorized in the service name ``." ??? info "`traefik.http.services..loadbalancer.server.port`" - + Registers a port. Useful when the container exposes multiples ports. - + Mandatory for Docker Swarm. - + ```yaml - "traefik.http.services.myservice.loadbalancer.server.port=8080" ``` ??? info "`traefik.http.services..loadbalancer.server.scheme`" - + Overrides the default scheme. - + ```yaml - "traefik.http.services.myservice.loadbalancer.server.scheme=http" ``` ??? info "`traefik.http.services..loadbalancer.passhostheader`" - + See [pass Host header](../services/index.md#pass-host-header) for more information. - + ```yaml - "traefik.http.services.myservice.loadbalancer.passhostheader=true" ``` ??? info "`traefik.http.services..loadbalancer.healthcheck.headers.`" - + See [health check](../services/index.md#health-check) for more information. - + ```yaml - "traefik.http.services.myservice.loadbalancer.healthcheck.headers.X-Foo=foobar" ``` ??? info "`traefik.http.services..loadbalancer.healthcheck.hostname`" - + See [health check](../services/index.md#health-check) for more information. - + ```yaml - "traefik.http.services.myservice.loadbalancer.healthcheck.hostname=foobar.com" ``` ??? info "`traefik.http.services..loadbalancer.healthcheck.interval`" - + See [health check](../services/index.md#health-check) for more information. - + ```yaml - "traefik.http.services.myservice.loadbalancer.healthcheck.interval=10" ``` ??? info "`traefik.http.services..loadbalancer.healthcheck.path`" - + See [health check](../services/index.md#health-check) for more information. - + ```yaml - "traefik.http.services.myservice.loadbalancer.healthcheck.path=/foo" ``` ??? info "`traefik.http.services..loadbalancer.healthcheck.port`" - + See [health check](../services/index.md#health-check) for more information. - + ```yaml - "traefik.http.services.myservice.loadbalancer.healthcheck.port=42" ``` ??? info "`traefik.http.services..loadbalancer.healthcheck.scheme`" - + See [health check](../services/index.md#health-check) for more information. - + ```yaml - "traefik.http.services.myservice.loadbalancer.healthcheck.scheme=http" ``` ??? info "`traefik.http.services..loadbalancer.healthcheck.timeout`" - + See [health check](../services/index.md#health-check) for more information. - + ```yaml - "traefik.http.services.myservice.loadbalancer.healthcheck.timeout=10" ``` ??? info "`traefik.http.services..loadbalancer.sticky`" - + See [sticky sessions](../services/index.md#sticky-sessions) for more information. - + ```yaml - "traefik.http.services.myservice.loadbalancer.sticky=true" ``` ??? info "`traefik.http.services..loadbalancer.sticky.cookie.httponly`" - + See [sticky sessions](../services/index.md#sticky-sessions) for more information. - + ```yaml - "traefik.http.services.myservice.loadbalancer.sticky.cookie.httponly=true" ``` ??? info "`traefik.http.services..loadbalancer.sticky.cookie.name`" - + See [sticky sessions](../services/index.md#sticky-sessions) for more information. - + ```yaml - "traefik.http.services.myservice.loadbalancer.sticky.cookie.name=foobar" ``` ??? info "`traefik.http.services..loadbalancer.sticky.cookie.secure`" - + See [sticky sessions](../services/index.md#sticky-sessions) for more information. - + ```yaml - "traefik.http.services.myservice.loadbalancer.sticky.cookie.secure=true" ``` ??? info "`traefik.http.services..loadbalancer.responseforwarding.flushinterval`" - + See [response forwarding](../services/index.md#response-forwarding) for more information. - + ```yaml - "traefik.http.services.myservice.loadbalancer.responseforwarding.flushinterval=10" ``` @@ -397,73 +418,73 @@ You can declare TCP Routers and/or Services using labels. #### TCP Routers ??? info "`traefik.tcp.routers..entrypoints`" - + See [entry points](../routers/index.md#entrypoints_1) for more information. - + ```yaml - "traefik.tcp.routers.mytcprouter.entrypoints=ep1,ep2" ``` ??? info "`traefik.tcp.routers..rule`" - + See [rule](../routers/index.md#rule_1) for more information. - + ```yaml - "traefik.tcp.routers.mytcprouter.rule=HostSNI(`myhost.com`)" ``` ??? info "`traefik.tcp.routers..service`" - + See [service](../routers/index.md#services) for more information. - + ```yaml - "traefik.tcp.routers.mytcprouter.service=myservice" ``` ??? info "`traefik.tcp.routers..tls`" - + See [TLS](../routers/index.md#tls_1) for more information. - + ```yaml - "traefik.tcp.routers.mytcprouter.tls=true" ``` ??? info "`traefik.tcp.routers..tls.certresolver`" - + See [certResolver](../routers/index.md#certresolver_1) for more information. - + ```yaml - "traefik.tcp.routers.mytcprouter.tls.certresolver=myresolver" ``` ??? info "`traefik.tcp.routers..tls.domains[n].main`" - + See [domains](../routers/index.md#domains_1) for more information. - + ```yaml - "traefik.tcp.routers.mytcprouter.tls.domains[0].main=foobar.com" ``` ??? info "`traefik.tcp.routers..tls.domains[n].sans`" - + See [domains](../routers/index.md#domains_1) for more information. - + ```yaml - "traefik.tcp.routers.mytcprouter.tls.domains[0].sans=test.foobar.com,dev.foobar.com" ``` ??? info "`traefik.tcp.routers..tls.options`" - + See [options](../routers/index.md#options_1) for more information. - + ```yaml - "traefik.tcp.routers.mytcprouter.tls.options=mysoptions" ``` ??? info "`traefik.tcp.routers..tls.passthrough`" - + See [TLS](../routers/index.md#tls_1) for more information. - + ```yaml - "traefik.tcp.routers.mytcprouter.tls.passthrough=true" ``` @@ -471,17 +492,17 @@ You can declare TCP Routers and/or Services using labels. #### TCP Services ??? info "`traefik.tcp.services..loadbalancer.server.port`" - + Registers a port of the application. - + ```yaml - "traefik.tcp.services.mytcpservice.loadbalancer.server.port=423" ``` ??? info "`traefik.tcp.services..loadbalancer.terminationdelay`" - + See [termination delay](../services/index.md#termination-delay) for more information. - + ```yaml - "traefik.tcp.services.mytcpservice.loadbalancer.terminationdelay=100" ``` diff --git a/docs/content/routing/services/.markdownlint.json b/docs/content/routing/services/.markdownlint.json index e803880c0..dd98ee65a 100644 --- a/docs/content/routing/services/.markdownlint.json +++ b/docs/content/routing/services/.markdownlint.json @@ -1,4 +1,5 @@ { "extends": "../../../.markdownlint.json", - "MD024": false + "MD024": false, + "MD046": false } diff --git a/docs/content/routing/services/index.md b/docs/content/routing/services/index.md index 212754fe0..0b582918d 100644 --- a/docs/content/routing/services/index.md +++ b/docs/content/routing/services/index.md @@ -5,9 +5,9 @@ Configuring How to Reach the Services ![services](../../assets/img/services.png) -The `Services` are responsible for configuring how to reach the actual services that will eventually handle the incoming requests. +The `Services` are responsible for configuring how to reach the actual services that will eventually handle the incoming requests. -## Configuration Example +## Configuration Examples ??? example "Declaring an HTTP Service with Two Servers -- Using the [File Provider](../../providers/file.md)" @@ -17,11 +17,11 @@ The `Services` are responsible for configuring how to reach the actual services [http.services.my-service.loadBalancer] [[http.services.my-service.loadBalancer.servers]] - url = "http://private-ip-server-1/" + url = "http://:/" [[http.services.my-service.loadBalancer.servers]] - url = "http://private-ip-server-2/" + url = "http://:/" ``` - + ```yaml tab="YAML" ## Dynamic configuration http: @@ -29,8 +29,8 @@ The `Services` are responsible for configuring how to reach the actual services my-service: loadBalancer: servers: - - url: "http://private-ip-server-1/" - - url: "http://private-ip-server-2/" + - url: "http://:/" + - url: "http://:/" ``` ??? example "Declaring a TCP Service with Two Servers -- Using the [File Provider](../../providers/file.md)" @@ -40,26 +40,28 @@ The `Services` are responsible for configuring how to reach the actual services [tcp.services] [tcp.services.my-service.loadBalancer] [[tcp.services.my-service.loadBalancer.servers]] - address = "xx.xx.xx.xx:xx" + address = ":" [[tcp.services.my-service.loadBalancer.servers]] - address = "xx.xx.xx.xx:xx" + address = ":" ``` - + ```yaml tab="YAML" tcp: services: my-service: - loadBalancer: + loadBalancer: servers: - - address: "xx.xx.xx.xx:xx" - - address: "xx.xx.xx.xx:xx" + - address: ":" + - address: ":" ``` ## Configuring HTTP Services ### Servers Load Balancer -The load balancers are able to load balance the requests between multiple instances of your programs. +The load balancers are able to load balance the requests between multiple instances of your programs. + +Each service has a load-balancer, even if there is only one server to forward traffic to. ??? example "Declaring a Service with Two Servers (with Load Balancing) -- Using the [File Provider](../../providers/file.md)" @@ -87,10 +89,10 @@ The load balancers are able to load balance the requests between multiple instan #### Servers Servers declare a single instance of your program. -The `url` option point to a specific instance. +The `url` option point to a specific instance. !!! info "" - Paths in the servers' `url` have no effect. + Paths in the servers' `url` have no effect. If you want the requests to be sent to a specific path on your servers, configure your [`routers`](../routers/index.md) to use a corresponding [middleware](../../middlewares/overview.md) (e.g. the [AddPrefix](../../middlewares/addprefix.md) or [ReplacePath](../../middlewares/replacepath.md)) middlewares. @@ -103,7 +105,7 @@ The `url` option point to a specific instance. [[http.services.my-service.loadBalancer.servers]] url = "http://private-ip-server-1/" ``` - + ```yaml tab="YAML" ## Dynamic configuration http: @@ -142,21 +144,21 @@ For now, only round robin load balancing is supported: ``` #### Sticky sessions - + When sticky sessions are enabled, a cookie is set on the initial request to track which server handles the first response. On subsequent requests, the client is forwarded to the same server. !!! info "Stickiness & Unhealthy Servers" - + If the server specified in the cookie becomes unhealthy, the request will be forwarded to a new server (and the cookie will keep track of the new server). -!!! info "Cookie Name" - +!!! info "Cookie Name" + The default cookie name is an abbreviation of a sha1 (ex: `_1d52e`). !!! info "Secure & HTTPOnly flags" - By default, the affinity cookie is created without those flags. One however can change that through configuration. + By default, the affinity cookie is created without those flags. One however can change that through configuration. ??? example "Adding Stickiness -- Using the [File Provider](../../providers/file.md)" @@ -166,7 +168,7 @@ On subsequent requests, the client is forwarded to the same server. [http.services.my-service] [http.services.my-service.loadBalancer.sticky.cookie] ``` - + ```yaml tab="YAML" ## Dynamic configuration http: @@ -223,8 +225,8 @@ Below are the available options for the health check mechanism: The interval must be greater than the timeout. If configuration doesn't reflect this, the interval will be set to timeout + 1 second. !!! info "Recovering Servers" - - Traefik keeps monitoring the health of unhealthy servers. + + Traefik keeps monitoring the health of unhealthy servers. If a server has recovered (returning `2xx` -> `3xx` responses again), it will be added back to the load balacer rotation pool. ??? example "Custom Interval & Timeout -- Using the [File Provider](../../providers/file.md)" @@ -261,7 +263,7 @@ Below are the available options for the health check mechanism: path = "/health" port = 8080 ``` - + ```yaml tab="YAML" ## Dynamic configuration http: @@ -283,7 +285,7 @@ Below are the available options for the health check mechanism: path = "/health" scheme = "http" ``` - + ```yaml tab="YAML" ## Dynamic configuration http: @@ -308,7 +310,7 @@ Below are the available options for the health check mechanism: My-Custom-Header = "foo" My-Header = "bar" ``` - + ```yaml tab="YAML" ## Dynamic configuration http: @@ -337,7 +339,7 @@ By default, `passHostHeader` is true. [http.services.Service01.loadBalancer] passHostHeader = false ``` - + ```yaml tab="YAML" ## Dynamic configuration http: @@ -358,7 +360,7 @@ Below are the available options for the Response Forwarding mechanism: A negative value means to flush immediately after each write to the client. The FlushInterval is ignored when ReverseProxy recognizes a response as a streaming response; for such responses, writes are flushed to the client immediately. - + ??? example "Using a custom FlushInterval -- Using the [File Provider](../../providers/file.md)" ```toml tab="TOML" @@ -368,7 +370,7 @@ Below are the available options for the Response Forwarding mechanism: [http.services.Service-1.loadBalancer.responseForwarding] flushInterval = "1s" ``` - + ```yaml tab="YAML" ## Dynamic configuration http: From 531c581cd5c99dd953e4336916e4e8bd190763f4 Mon Sep 17 00:00:00 2001 From: Damien Duportal Date: Mon, 28 Oct 2019 17:42:05 +0100 Subject: [PATCH 36/40] Fix a typo in routing documentation for Docker --- docs/content/routing/providers/docker.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/routing/providers/docker.md b/docs/content/routing/providers/docker.md index f81d0daaa..b3b63a997 100644 --- a/docs/content/routing/providers/docker.md +++ b/docs/content/routing/providers/docker.md @@ -55,7 +55,7 @@ Attach labels to your containers and let Traefik do the rest! !!! important "Traefik Connecting to the Wrong Port: `HTTP/502 Gateway Error`" By default, Traefik uses the first exposed port of a container. - Setting the label `raefik.http.services.xxx.loadbalancer.server.port` + Setting the label `traefik.http.services.xxx.loadbalancer.server.port` overrides that behavior. ??? example "Configuring Docker Swarm & Deploying / Exposing Services" From 9d17e8826bd1c76acafcf819228c88e82a8f7e3a Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 28 Oct 2019 17:50:05 +0100 Subject: [PATCH 37/40] Prepare release v2.0.3 --- CHANGELOG.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f56408d77..6fbaa5f5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,36 @@ +## [v2.0.3](https://github.com/containous/traefik/tree/v2.0.3) (2019-10-28) +[All Commits](https://github.com/containous/traefik/compare/v2.0.2...v2.0.3) + +**Bug fixes:** +- **[acme,logs]** Use debug for log about skipping addition of cert ([#5641](https://github.com/containous/traefik/pull/5641) by [sylr](https://github.com/sylr)) +- **[file]** fix: add filename in the file provider logs. ([#5636](https://github.com/containous/traefik/pull/5636) by [ldez](https://github.com/ldez)) +- **[k8s,k8s/crd,k8s/ingress]** Remove unnecessary reload of the configuration. ([#5707](https://github.com/containous/traefik/pull/5707) by [ldez](https://github.com/ldez)) +- **[k8s,k8s/crd,k8s/ingress]** Fixing support for HTTPs backends with Kubernetes ExternalName services ([#5660](https://github.com/containous/traefik/pull/5660) by [kpeiruza](https://github.com/kpeiruza)) +- **[k8s,k8s/ingress]** Normalize service and router names for ingress. ([#5623](https://github.com/containous/traefik/pull/5623) by [ldez](https://github.com/ldez)) +- **[logs]** Set proxy protocol logger to DEBUG level ([#5712](https://github.com/containous/traefik/pull/5712) by [mmatur](https://github.com/mmatur)) +- **[middleware]** fix: add stacktrace when recover. ([#5654](https://github.com/containous/traefik/pull/5654) by [ldez](https://github.com/ldez)) +- **[tracing]** Let instana/go-sensor handle default agent host ([#5658](https://github.com/containous/traefik/pull/5658) by [sylr](https://github.com/sylr)) +- **[tracing]** fix: default tracing backend. ([#5717](https://github.com/containous/traefik/pull/5717) by [ldez](https://github.com/ldez)) +- fix: deep copy of passHostHeader on ServersLoadBalancer. ([#5720](https://github.com/containous/traefik/pull/5720) by [ldez](https://github.com/ldez)) + +**Documentation:** +- **[acme]** Fix acme storage file docker mounting example ([#5633](https://github.com/containous/traefik/pull/5633) by [jansauer](https://github.com/jansauer)) +- **[acme]** fix incorrect DNS reference ([#5666](https://github.com/containous/traefik/pull/5666) by [oskapt](https://github.com/oskapt)) +- **[logs]** Clarify unit of duration field in access log ([#5664](https://github.com/containous/traefik/pull/5664) by [Sarke](https://github.com/Sarke)) +- **[middleware]** Fix Security Headers Doc ([#5706](https://github.com/containous/traefik/pull/5706) by [FlorianPerrot](https://github.com/FlorianPerrot)) +- **[middleware]** Migration guide: pathprefixstrip migration ([#5600](https://github.com/containous/traefik/pull/5600) by [dduportal](https://github.com/dduportal)) +- **[middleware]** fix ForwardAuth tls.skipverify examples ([#5683](https://github.com/containous/traefik/pull/5683) by [remche](https://github.com/remche)) +- **[rules]** Add documentation about backtick for rule definition. ([#5714](https://github.com/containous/traefik/pull/5714) by [ldez](https://github.com/ldez)) +- **[webui]** Improve documentation of the router rules for API and dashboard ([#5625](https://github.com/containous/traefik/pull/5625) by [dduportal](https://github.com/dduportal)) +- doc: @ is not authorized in names definition. ([#5734](https://github.com/containous/traefik/pull/5734) by [ldez](https://github.com/ldez)) +- Remove obsolete v2 remark from README ([#5669](https://github.com/containous/traefik/pull/5669) by [dragetd](https://github.com/dragetd)) +- Fix spelling mistake: "founded" -> "found" ([#5674](https://github.com/containous/traefik/pull/5674) by [ocanty](https://github.com/ocanty)) +- fix typo for stripPrefix in tab File (YAML) ([#5694](https://github.com/containous/traefik/pull/5694) by [nalakawula](https://github.com/nalakawula)) +- Add example for changing the port used by traefik to connect to a service ([#5224](https://github.com/containous/traefik/pull/5224) by [robertbaker](https://github.com/robertbaker)) + +**Misc:** +- **[logs,middleware]** Cherry pick v1.7 into v2.0 ([#5735](https://github.com/containous/traefik/pull/5735) by [jbdoumenjou](https://github.com/jbdoumenjou)) + ## [v2.0.2](https://github.com/containous/traefik/tree/v2.0.2) (2019-10-09) [All Commits](https://github.com/containous/traefik/compare/v2.0.1...v2.0.2) From e2d971f20ee238cbf0c1afc56d705e77a3689954 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 28 Oct 2019 20:58:05 +0100 Subject: [PATCH 38/40] fix: release timeout. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index daf2cbae3..0608d8304 100644 --- a/Makefile +++ b/Makefile @@ -131,7 +131,7 @@ generate-crd: ## Create packages for the release release-packages: generate-webui build-dev-image rm -rf dist - $(DOCKER_RUN_TRAEFIK_NOTTY) goreleaser release --skip-publish + $(DOCKER_RUN_TRAEFIK_NOTTY) goreleaser release --skip-publish --timeout="60m" $(DOCKER_RUN_TRAEFIK_NOTTY) tar cfz dist/traefik-${VERSION}.src.tar.gz \ --exclude-vcs \ --exclude .idea \ From 8b8b1427f678c2a8b0a759da377ca84c9522f0f6 Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Mon, 28 Oct 2019 21:10:50 +0100 Subject: [PATCH 39/40] Prepare release v2.0.4 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fbaa5f5d..96f36e5ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [v2.0.4](https://github.com/containous/traefik/tree/v2.0.4) (2019-10-28) +[All Commits](https://github.com/containous/traefik/compare/v2.0.3...v2.0.4) + +Fixes releases system. +Same changelog as v2.0.3. + ## [v2.0.3](https://github.com/containous/traefik/tree/v2.0.3) (2019-10-28) [All Commits](https://github.com/containous/traefik/compare/v2.0.2...v2.0.3) From 6d3bad1ae01934cecdb207e5b9cdc0981cf718fe Mon Sep 17 00:00:00 2001 From: ASDFGamer Date: Mon, 28 Oct 2019 23:20:03 +0100 Subject: [PATCH 40/40] Fix error in link description for priority --- docs/content/routing/providers/docker.md | 2 +- docs/content/routing/providers/marathon.md | 2 +- docs/content/routing/providers/rancher.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/content/routing/providers/docker.md b/docs/content/routing/providers/docker.md index b3b63a997..7af257d6b 100644 --- a/docs/content/routing/providers/docker.md +++ b/docs/content/routing/providers/docker.md @@ -226,7 +226,7 @@ For example, to change the rule, you could add the label ```traefik.http.routers ??? info "`traefik.http.routers..priority`" - See [options](../routers/index.md#priority) for more information. + See [priority](../routers/index.md#priority) for more information. ```yaml - "traefik.http.routers.myrouter.priority=42" diff --git a/docs/content/routing/providers/marathon.md b/docs/content/routing/providers/marathon.md index 72881f156..f8a50ac5f 100644 --- a/docs/content/routing/providers/marathon.md +++ b/docs/content/routing/providers/marathon.md @@ -128,7 +128,7 @@ For example, to change the routing rule, you could add the label ```"traefik.htt ??? info "`traefik.http.routers..priority`" - See [options](../routers/index.md#priority) for more information. + See [priority](../routers/index.md#priority) for more information. ```json "traefik.http.routers.myrouter.priority": "42" diff --git a/docs/content/routing/providers/rancher.md b/docs/content/routing/providers/rancher.md index d523221f8..f8255b0ac 100644 --- a/docs/content/routing/providers/rancher.md +++ b/docs/content/routing/providers/rancher.md @@ -133,7 +133,7 @@ For example, to change the rule, you could add the label ```traefik.http.routers ??? info "`traefik.http.routers..priority`" - See [options](../routers/index.md#priority) for more information. + See [priority](../routers/index.md#priority) for more information. ```yaml - "traefik.http.routers.myrouter.priority=42"