mirror of
				https://github.com/containous/traefik.git
				synced 2025-10-30 20:24:28 +03:00 
			
		
		
		
	Compare commits
	
		
			120 Commits
		
	
	
		
			v2.10.0
			...
			v3.0.0-bet
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 52d2d959af | ||
|  | 0a35fa096a | ||
|  | a7ef965412 | ||
|  | 0a861716d4 | ||
|  | 4fbe9b81ec | ||
|  | 5fd6913ee5 | ||
|  | 7741c68eaa | ||
|  | 18077ff69a | ||
|  | fa555d0d29 | ||
|  | 0e5898b2f8 | ||
|  | aae76408e2 | ||
|  | 9cc9ed6a0c | ||
|  | fecaec7a4a | ||
|  | e62fe64ec9 | ||
|  | 6885e410f0 | ||
|  | 68ed875966 | ||
|  | d1bdeb3a92 | ||
|  | 878e7de56a | ||
|  | 27353d0740 | ||
|  | 606281a4a5 | ||
|  | c5f23493ab | ||
|  | db515195f0 | ||
|  | 9aa57f362b | ||
|  | 6977b68b72 | ||
|  | 8d8717d421 | ||
|  | 981ad74870 | ||
|  | 021f37ff71 | ||
|  | 511762cbf3 | ||
|  | 466d7461b7 | ||
|  | 1522afe2ec | ||
|  | 9c73c4c584 | ||
|  | 8f206ce319 | ||
|  | 65c59c9a09 | ||
|  | e044e2b765 | ||
|  | 7805c683e3 | ||
|  | e38c0c3969 | ||
|  | 2cebd0a083 | ||
|  | c0e03ae17d | ||
|  | 9060522414 | ||
|  | fc071a5ebe | ||
|  | 79c5f34156 | ||
|  | 928db9bc42 | ||
|  | 598caf6f78 | ||
|  | 8b47c5adf7 | ||
|  | a3bcf0f39e | ||
|  | 7875826bd9 | ||
|  | 7c2af10bbd | ||
|  | 598a257ae1 | ||
|  | 20e47d9102 | ||
|  | f26e250648 | ||
|  | 80790cba17 | ||
|  | 241fb5093a | ||
|  | 044dc6a221 | ||
|  | 707f84e2e4 | ||
|  | f94298e867 | ||
|  | e1abf103c0 | ||
|  | 8cd4923e72 | ||
|  | cd90b9761a | ||
|  | f0f5f41fb9 | ||
|  | 8bf68b7efd | ||
|  | b22aef7fff | ||
|  | a2016a2953 | ||
|  | c38d405cfd | ||
|  | 8c98234c07 | ||
|  | d046af2e91 | ||
|  | 943238faba | ||
|  | 2b67f1f66f | ||
|  | 2ad1fd725a | ||
|  | 7129f03dc9 | ||
|  | 748254b6c5 | ||
|  | a08a428787 | ||
|  | 3eeea2bb2b | ||
|  | c2dac39da1 | ||
|  | e54ee89330 | ||
|  | fdd3f2abef | ||
|  | 517917cd7c | ||
|  | 6c75052a13 | ||
|  | 8cf9385938 | ||
|  | 519ed8bde5 | ||
|  | 46a61ce9c8 | ||
|  | c57876c116 | ||
|  | 0d81fac3fc | ||
|  | db287c4d31 | ||
|  | 4d86668af3 | ||
|  | b93141992e | ||
|  | a3e4c85ec0 | ||
|  | bee86b5ac7 | ||
|  | 0ba51d62fa | ||
|  | 268d1edc8f | ||
|  | 580e7fa774 | ||
|  | 46c266661c | ||
|  | 61325d7b91 | ||
|  | 3f8aa13e68 | ||
|  | 08279047ae | ||
|  | 3dd4968c41 | ||
|  | ba1ca68977 | ||
|  | 56f7515ecd | ||
|  | 27c02b5a56 | ||
|  | 630de7481e | ||
|  | fadee5e87b | ||
|  | 67d9c8da0b | ||
|  | 1a1cfd1adc | ||
|  | 240fb871b6 | ||
|  | d131ef57da | ||
|  | 281fa25844 | ||
|  | bd3eaf4f5e | ||
|  | 7a6bfd3336 | ||
|  | 1b9873cae9 | ||
|  | e86f21ae7b | ||
|  | 194247caae | ||
|  | cd0654026a | ||
|  | b39ce8cc58 | ||
|  | 33f0aed5ea | ||
|  | 188ef84c4f | ||
|  | a5c520664a | ||
|  | 38d7011487 | ||
|  | 033fccccc7 | ||
|  | df99a9fb57 | ||
|  | d6b69e1347 | ||
|  | 4bd055cf97 | 
							
								
								
									
										4
									
								
								.github/workflows/documentation.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/documentation.yml
									
									
									
									
										vendored
									
									
								
							| @@ -7,7 +7,7 @@ on: | ||||
|       - v* | ||||
|  | ||||
| env: | ||||
|   STRUCTOR_VERSION: v1.13.1 | ||||
|   STRUCTOR_VERSION: v1.13.2 | ||||
|   MIXTUS_VERSION: v0.4.1 | ||||
|  | ||||
| jobs: | ||||
| @@ -47,6 +47,6 @@ jobs: | ||||
|         run: $HOME/bin/seo -path=./site -product=traefik | ||||
|  | ||||
|       - name: Publish documentation | ||||
|         run: $HOME/bin/mixtus --dst-doc-path="./traefik" --dst-owner=traefik --dst-repo-name=doc --git-user-email="30906710+traefiker@users.noreply.github.com" --git-user-name=traefiker --src-doc-path="./site" --src-owner=containous --src-repo-name=traefik | ||||
|         run: $HOME/bin/mixtus --dst-doc-path="./traefik" --dst-owner=traefik --dst-repo-name=doc --git-user-email="30906710+traefiker@users.noreply.github.com" --git-user-name=traefiker --src-doc-path="./site" --src-owner=traefik --src-repo-name=traefik | ||||
|         env: | ||||
|           GITHUB_TOKEN: ${{ secrets.GH_TOKEN_REPO }} | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/validate.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/validate.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -7,7 +7,7 @@ on: | ||||
|  | ||||
| env: | ||||
|   GO_VERSION: '1.20' | ||||
|   GOLANGCI_LINT_VERSION: v1.52.2 | ||||
|   GOLANGCI_LINT_VERSION: v1.53.1 | ||||
|   MISSSPELL_VERSION: v0.4.0 | ||||
|   IN_DOCKER: "" | ||||
|  | ||||
|   | ||||
| @@ -26,10 +26,17 @@ linters-settings: | ||||
|       - ^spew\.Print(f|ln)?$ | ||||
|       - ^spew\.Dump$ | ||||
|   depguard: | ||||
|     list-type: denylist | ||||
|     include-go-root: false | ||||
|     packages: | ||||
|       - github.com/pkg/errors | ||||
|     rules: | ||||
|       main: | ||||
|         deny: | ||||
|           - pkg: "github.com/instana/testify" | ||||
|             desc: not allowed | ||||
|           - pkg: "github.com/pkg/errors" | ||||
|             desc: Should be replaced by standard lib errors package | ||||
|           - pkg: "k8s.io/api/networking/v1beta1" | ||||
|             desc: This API is deprecated | ||||
|           - pkg: "k8s.io/api/extensions/v1beta1" | ||||
|             desc: This API is deprecated | ||||
|   godox: | ||||
|     keywords: | ||||
|       - FIXME | ||||
| @@ -44,14 +51,10 @@ linters-settings: | ||||
|         pkg: "k8s.io/api/core/v1" | ||||
|       - alias: netv1 | ||||
|         pkg: "k8s.io/api/networking/v1" | ||||
|       - alias: netv1beta1 | ||||
|         pkg: "k8s.io/api/networking/v1beta1" | ||||
|       - alias: admv1 | ||||
|         pkg: "k8s.io/api/admission/v1" | ||||
|       - alias: admv1beta1 | ||||
|         pkg: "k8s.io/api/admission/v1beta1" | ||||
|       - alias: extv1beta1 | ||||
|         pkg: "k8s.io/api/extensions/v1beta1" | ||||
|       - alias: metav1 | ||||
|         pkg: "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
|       - alias: ktypes | ||||
| @@ -85,17 +88,17 @@ linters-settings: | ||||
|  | ||||
|       # Traefik Kubernetes rewrites: | ||||
|       - alias: containousv1alpha1 | ||||
|         pkg: "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1" | ||||
|         pkg: "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1" | ||||
|       - alias: traefikv1alpha1 | ||||
|         pkg: "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefikio/v1alpha1" | ||||
|         pkg: "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" | ||||
|       - alias: traefikclientset | ||||
|         pkg: "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/clientset/versioned" | ||||
|         pkg: "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned" | ||||
|       - alias: traefikinformers | ||||
|         pkg: "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/informers/externalversions" | ||||
|         pkg: "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions" | ||||
|       - alias: traefikscheme | ||||
|         pkg: "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme" | ||||
|         pkg: "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme" | ||||
|       - alias: traefikcrdfake | ||||
|         pkg: "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake" | ||||
|         pkg: "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake" | ||||
|   tagalign: | ||||
|     align: false | ||||
|     sort: true | ||||
| @@ -199,6 +202,7 @@ linters: | ||||
|     - containedctx # too many false-positive | ||||
|     - maintidx # kind of duplicate of gocyclo | ||||
|     - nonamedreturns # Too strict | ||||
|     - gosmopolitan  # not relevant | ||||
|  | ||||
| issues: | ||||
|   exclude-use-default: false | ||||
| @@ -207,15 +211,6 @@ issues: | ||||
|   exclude: | ||||
|     - 'Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked' | ||||
|     - "should have a package comment, unless it's in another file for this package" | ||||
|     - 'SA1019: http.CloseNotifier has been deprecated' # FIXME must be fixed | ||||
|     - 'SA1019: cfg.SSLRedirect is deprecated' | ||||
|     - 'SA1019: cfg.SSLTemporaryRedirect is deprecated' | ||||
|     - 'SA1019: cfg.SSLHost is deprecated' | ||||
|     - 'SA1019: cfg.SSLForceHost is deprecated' | ||||
|     - 'SA1019: cfg.FeaturePolicy is deprecated' | ||||
|     - 'SA1019: c.Providers.ConsulCatalog.Namespace is deprecated' | ||||
|     - 'SA1019: c.Providers.Consul.Namespace is deprecated' | ||||
|     - 'SA1019: c.Providers.Nomad.Namespace is deprecated' | ||||
|   exclude-rules: | ||||
|     - path: '(.+)_test.go' | ||||
|       linters: | ||||
| @@ -236,7 +231,7 @@ issues: | ||||
|       text: "Function 'buildConstructor' has too many statements" | ||||
|       linters: | ||||
|         - funlen | ||||
|     - path: pkg/tracing/haystack/logger.go | ||||
|     - path: pkg/logs/haystack.go | ||||
|       linters: | ||||
|         - goprintffuncname | ||||
|     - path: pkg/tracing/tracing.go | ||||
| @@ -261,6 +256,10 @@ issues: | ||||
|       text: 'Duplicate words \(sub\) found' | ||||
|       linters: | ||||
|         - dupword | ||||
|     - path: pkg/provider/kubernetes/crd/kubernetes.go | ||||
|       text: "Function 'loadConfigurationFromCRD' has too many statements" | ||||
|       linters: | ||||
|         - funlen | ||||
|     - path: pkg/provider/kubernetes/gateway/client_mock_test.go | ||||
|       text: 'unusedwrite: unused write to field' | ||||
|       linters: | ||||
|   | ||||
| @@ -11,7 +11,7 @@ builds: | ||||
|     env: | ||||
|       - CGO_ENABLED=0 | ||||
|     ldflags: | ||||
|       - -s -w -X github.com/traefik/traefik/v2/pkg/version.Version={{.Version}} -X github.com/traefik/traefik/v2/pkg/version.Codename={{.Env.CODENAME}} -X github.com/traefik/traefik/v2/pkg/version.BuildDate={{.Date}} | ||||
|       - -s -w -X github.com/traefik/traefik/v3/pkg/version.Version={{.Version}} -X github.com/traefik/traefik/v3/pkg/version.Codename={{.Env.CODENAME}} -X github.com/traefik/traefik/v3/pkg/version.BuildDate={{.Date}} | ||||
|     flags: | ||||
|       - -trimpath | ||||
|     goos: | ||||
|   | ||||
| @@ -3,7 +3,7 @@ name: Traefik | ||||
| agent: | ||||
|   machine: | ||||
|     type: e1-standard-4 | ||||
|     os_image: ubuntu1804 | ||||
|     os_image: ubuntu2004 | ||||
|  | ||||
| fail_fast: | ||||
|   stop: | ||||
| @@ -57,14 +57,14 @@ blocks: | ||||
|       agent: | ||||
|         machine: | ||||
|           type: e1-standard-8 | ||||
|           os_image: ubuntu1804 | ||||
|           os_image: ubuntu2004 | ||||
|       secrets: | ||||
|         - name: traefik | ||||
|       env_vars: | ||||
|         - name: GH_VERSION | ||||
|           value: 1.12.1 | ||||
|         - name: CODENAME | ||||
|           value: "saintmarcelin" | ||||
|           value: "beaufort" | ||||
|         - name: IN_DOCKER | ||||
|           value: "" | ||||
|       prologue: | ||||
| @@ -73,7 +73,7 @@ blocks: | ||||
|           - curl -sSL -o /tmp/gh_${GH_VERSION}_linux_amd64.tar.gz https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_amd64.tar.gz | ||||
|           - tar -zxvf /tmp/gh_${GH_VERSION}_linux_amd64.tar.gz -C /tmp | ||||
|           - sudo mv /tmp/gh_${GH_VERSION}_linux_amd64/bin/gh /usr/local/bin/gh | ||||
|           - sudo rm -rf ~/.phpbrew ~/.kerl ~/.sbt ~/.nvm ~/.npm ~/.kiex /usr/lib/jvm /opt/az /opt/firefox # Remove unnecessary data. | ||||
|           - sudo rm -rf ~/.phpbrew ~/.kerl ~/.sbt ~/.nvm ~/.npm ~/.kiex /usr/lib/jvm /opt/az /opt/firefox /usr/lib/google-cloud-sdk ~/.rbenv ~/.pip_download_cache # Remove unnecessary data. | ||||
|           - sudo service docker stop && sudo umount /var/lib/docker && sudo service docker start # Unmounts the docker disk and the whole system disk is usable. | ||||
|       jobs: | ||||
|         - name: Release | ||||
|   | ||||
							
								
								
									
										144
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										144
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -1,3 +1,88 @@ | ||||
| ## [v3.0.0-beta3](https://github.com/traefik/traefik/tree/v3.0.0-beta3) (2023-06-21) | ||||
| [All Commits](https://github.com/traefik/traefik/compare/v3.0.0-beta2...v3.0.0-beta3) | ||||
|  | ||||
| **Enhancements:** | ||||
| - **[docker,docker/swarm]** Split Docker provider ([#9652](https://github.com/traefik/traefik/pull/9652) by [ldez](https://github.com/ldez)) | ||||
| - **[k8s,hub]** Remove deprecated code ([#9804](https://github.com/traefik/traefik/pull/9804) by [ldez](https://github.com/ldez)) | ||||
| - **[k8s,k8s/gatewayapi]** Support HostSNIRegexp in GatewayAPI TLS routes ([#9486](https://github.com/traefik/traefik/pull/9486) by [ddtmachado](https://github.com/ddtmachado)) | ||||
| - **[k8s/gatewayapi]** Add support for HTTPRequestRedirectFilter in k8s Gateway API ([#9408](https://github.com/traefik/traefik/pull/9408) by [romantomjak](https://github.com/romantomjak)) | ||||
| - **[k8s/ingress,k8s]** Remove support of the networking.k8s.io/v1beta1 APIVersion ([#9949](https://github.com/traefik/traefik/pull/9949) by [rtribotte](https://github.com/rtribotte)) | ||||
| - **[k8s/ingress,k8s]** Add option to the Ingress provider to disable IngressClass lookup ([#9281](https://github.com/traefik/traefik/pull/9281) by [jandillenkofer](https://github.com/jandillenkofer)) | ||||
| - **[marathon]** Remove Marathon provider ([#9614](https://github.com/traefik/traefik/pull/9614) by [rtribotte](https://github.com/rtribotte)) | ||||
| - **[metrics]** Remove InfluxDB v1 metrics middleware ([#9612](https://github.com/traefik/traefik/pull/9612) by [tomMoulard](https://github.com/tomMoulard)) | ||||
| - **[rancher]** Remove Rancher v1 provider ([#9613](https://github.com/traefik/traefik/pull/9613) by [tomMoulard](https://github.com/tomMoulard)) | ||||
| - **[rules]** Remove containous/mux from HTTP muxer ([#9558](https://github.com/traefik/traefik/pull/9558) by [tomMoulard](https://github.com/tomMoulard)) | ||||
| - **[tls,tcp,service]** Add TCP Servers Transports support ([#9465](https://github.com/traefik/traefik/pull/9465) by [sdelicata](https://github.com/sdelicata)) | ||||
| - **[webui]** Added router priority to webui's list and detail page ([#9004](https://github.com/traefik/traefik/pull/9004) by [bendre90](https://github.com/bendre90)) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - **[metrics]** Fix OpenTelemetry metrics ([#9962](https://github.com/traefik/traefik/pull/9962) by [rtribotte](https://github.com/rtribotte)) | ||||
| - **[metrics]** Remove config reload failure metrics ([#9660](https://github.com/traefik/traefik/pull/9660) by [rtribotte](https://github.com/rtribotte)) | ||||
| - **[metrics]** Fix open connections metric ([#9656](https://github.com/traefik/traefik/pull/9656) by [mpl](https://github.com/mpl)) | ||||
| - **[metrics]** Fix OpenTelemetry service name ([#9619](https://github.com/traefik/traefik/pull/9619) by [tomMoulard](https://github.com/tomMoulard)) | ||||
| - **[tcp]** Don't log EOF or timeout errors while peeking first bytes in Postgres StartTLS hook ([#9663](https://github.com/traefik/traefik/pull/9663) by [rtribotte](https://github.com/rtribotte)) | ||||
| - **[webui]** Detect dashboard assets content types ([#9622](https://github.com/traefik/traefik/pull/9622) by [tomMoulard](https://github.com/tomMoulard)) | ||||
| - **[webui]** fix: detect dashboard content types ([#9594](https://github.com/traefik/traefik/pull/9594) by [ldez](https://github.com/ldez)) | ||||
|  | ||||
| **Documentation:** | ||||
| - **[k8s]** Improve Kubernetes support documentation ([#9974](https://github.com/traefik/traefik/pull/9974) by [rtribotte](https://github.com/rtribotte)) | ||||
| - Adjust quick start ([#9790](https://github.com/traefik/traefik/pull/9790) by [svx](https://github.com/svx)) | ||||
| - Mention PathPrefix matcher changes in V3 Migration Guide ([#9727](https://github.com/traefik/traefik/pull/9727) by [aofei](https://github.com/aofei)) | ||||
| - Fix yaml indentation in the HTTP3 example ([#9724](https://github.com/traefik/traefik/pull/9724) by [benwaffle](https://github.com/benwaffle)) | ||||
| - Add OpenTelemetry in observability overview ([#9654](https://github.com/traefik/traefik/pull/9654) by [tomMoulard](https://github.com/tomMoulard)) | ||||
|  | ||||
| **Misc:** | ||||
| - Merge branch v2.10 into v3.0 ([#9977](https://github.com/traefik/traefik/pull/9977) by [ldez](https://github.com/ldez)) | ||||
| - Merge branch v2.10 into v3.0 ([#9931](https://github.com/traefik/traefik/pull/9931) by [ldez](https://github.com/ldez)) | ||||
| - Merge branch v2.10 into v3.0 ([#9896](https://github.com/traefik/traefik/pull/9896) by [ldez](https://github.com/ldez)) | ||||
| - Merge branch v2.10 into v3.0 ([#9867](https://github.com/traefik/traefik/pull/9867) by [ldez](https://github.com/ldez)) | ||||
| - Merge branch v2.10 into v3.0 ([#9850](https://github.com/traefik/traefik/pull/9850) by [ldez](https://github.com/ldez)) | ||||
| - Merge branch v2.10 into v3.0 ([#9845](https://github.com/traefik/traefik/pull/9845) by [ldez](https://github.com/ldez)) | ||||
| - Merge branch v2.10 into v3.0 ([#9803](https://github.com/traefik/traefik/pull/9803) by [ldez](https://github.com/ldez)) | ||||
| - Merge branch v2.10 into v3.0 ([#9793](https://github.com/traefik/traefik/pull/9793) by [ldez](https://github.com/ldez)) | ||||
| - Merge branch v2.9 into v3.0 ([#9722](https://github.com/traefik/traefik/pull/9722) by [rtribotte](https://github.com/rtribotte)) | ||||
| - Merge branch v2.9 into v3.0 ([#9650](https://github.com/traefik/traefik/pull/9650) by [tomMoulard](https://github.com/tomMoulard)) | ||||
| - Merge branch v2.9 into v3.0 ([#9632](https://github.com/traefik/traefik/pull/9632) by [kevinpollet](https://github.com/kevinpollet)) | ||||
|  | ||||
| ## [v2.10.3](https://github.com/traefik/traefik/tree/v2.10.3) (2023-06-17) | ||||
| [All Commits](https://github.com/traefik/traefik/compare/v2.10.2...v2.10.3) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - **[acme]** Update go-acme/lego to v4.12.2 ([#9935](https://github.com/traefik/traefik/pull/9971) by [ldez](https://github.com/ldez)) | ||||
|  | ||||
| ## [v2.10.2](https://github.com/traefik/traefik/tree/v2.10.2) (2023-06-17) | ||||
| [All Commits](https://github.com/traefik/traefik/compare/v2.10.1...v2.10.2) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - **[acme]** Update go-acme/lego to v4.12.1 ([#9935](https://github.com/traefik/traefik/pull/9935) by [ldez](https://github.com/ldez)) | ||||
| - **[acme]** Update go-acme/lego to v4.12.0 ([#9918](https://github.com/traefik/traefik/pull/9918) by [ldez](https://github.com/ldez)) | ||||
| - **[acme]** Update go-acme/lego to v4.11.0 ([#9883](https://github.com/traefik/traefik/pull/9883) by [ldez](https://github.com/ldez)) | ||||
| - **[acme]** Do not check for wildcard domains for non DNS challenge ([#9881](https://github.com/traefik/traefik/pull/9881) by [erkexzcx](https://github.com/erkexzcx)) | ||||
| - **[k8s/crd]** Fix multiple subsets endpoint ([#9914](https://github.com/traefik/traefik/pull/9914) by [joaosilva15](https://github.com/joaosilva15)) | ||||
| - **[k8s/ingress,k8s/crd,k8s,hub]** Clean code related to Hub ([#9894](https://github.com/traefik/traefik/pull/9894) by [ldez](https://github.com/ldez)) | ||||
| - **[metrics]** Enable Prometheus provider cleanup when only the router's metrics level is activated ([#9887](https://github.com/traefik/traefik/pull/9887) by [rtribotte](https://github.com/rtribotte)) | ||||
| - **[middleware]** Encode query semicolons ([#9943](https://github.com/traefik/traefik/pull/9943) by [LandryBe](https://github.com/LandryBe)) | ||||
| - **[middleware]** Missing trailer with custom errors middleware ([#9942](https://github.com/traefik/traefik/pull/9942) by [rtribotte](https://github.com/rtribotte)) | ||||
| - **[middleware]** Support informational headers in middlewares redefining the response writer. ([#9938](https://github.com/traefik/traefik/pull/9938) by [rtribotte](https://github.com/rtribotte)) | ||||
| - **[plugins]** Improve error messages related to plugins ([#9924](https://github.com/traefik/traefik/pull/9924) by [ldez](https://github.com/ldez)) | ||||
| - **[tracing]** Update DataDog tracing dependency to v1.50.1 ([#9953](https://github.com/traefik/traefik/pull/9953) by [der-eismann](https://github.com/der-eismann)) | ||||
|  | ||||
| **Documentation:** | ||||
| - **[accesslogs]** Fix over-indented yaml configuration of access logs ([#9930](https://github.com/traefik/traefik/pull/9930) by [ufUNnxagpM](https://github.com/ufUNnxagpM)) | ||||
| - **[tls]** Add FAQ documentation about TLS certificates ([#9868](https://github.com/traefik/traefik/pull/9868) by [rtribotte](https://github.com/rtribotte)) | ||||
| - Fix typo ([#9966](https://github.com/traefik/traefik/pull/9966) by [green1052](https://github.com/green1052)) | ||||
| - Add business callouts ([#9940](https://github.com/traefik/traefik/pull/9940) by [tomatokoolaid](https://github.com/tomatokoolaid)) | ||||
| - Add logo for GitHub dark mode ([#9890](https://github.com/traefik/traefik/pull/9890) by [ldez](https://github.com/ldez)) | ||||
|  | ||||
| ## [v2.10.1](https://github.com/traefik/traefik/tree/v2.10.1) (2023-04-27) | ||||
| [All Commits](https://github.com/traefik/traefik/compare/v2.10.0...v2.10.1) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - **[middleware,oxy]** Update vulcand/oxy to be5cf38 ([#9874](https://github.com/traefik/traefik/pull/9874) by [rtribotte](https://github.com/rtribotte)) | ||||
|  | ||||
| **Documentation:** | ||||
| - Fix v2.10 migration guide ([#9863](https://github.com/traefik/traefik/pull/9863) by [rtribotte](https://github.com/rtribotte)) | ||||
|  | ||||
| ## [v2.10.0](https://github.com/traefik/traefik/tree/v2.10.0) (2023-04-24) | ||||
| [All Commits](https://github.com/traefik/traefik/compare/v2.9.0-rc1...v2.10.0) | ||||
|  | ||||
| @@ -121,6 +206,19 @@ | ||||
| - Update copyright for 2023 ([#9631](https://github.com/traefik/traefik/pull/9631) by [kevinpollet](https://github.com/kevinpollet)) | ||||
| - Update submitting pull requests to include language about drafts ([#9609](https://github.com/traefik/traefik/pull/9609) by [tfny](https://github.com/tfny)) | ||||
|  | ||||
| ## [v3.0.0-beta2](https://github.com/traefik/traefik/tree/v3.0.0-beta2) (2022-12-07) | ||||
| [All Commits](https://github.com/traefik/traefik/compare/v3.0.0-beta1...v3.0.0-beta2) | ||||
|  | ||||
| **Enhancements:** | ||||
| - **[http3]** Moves HTTP/3 outside the experimental section ([#9570](https://github.com/traefik/traefik/pull/9570) by [sdelicata](https://github.com/sdelicata)) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - **[logs]** Change traefik cmd error log to error level ([#9569](https://github.com/traefik/traefik/pull/9569) by [tomMoulard](https://github.com/tomMoulard)) | ||||
| - **[rules]** Rework Host and HostRegexp matchers ([#9559](https://github.com/traefik/traefik/pull/9559) by [tomMoulard](https://github.com/tomMoulard)) | ||||
|  | ||||
| **Misc:** | ||||
| - Merge current v2.9 into master ([#9586](https://github.com/traefik/traefik/pull/9586) by [tomMoulard](https://github.com/tomMoulard)) | ||||
|  | ||||
| ## [v2.9.6](https://github.com/traefik/traefik/tree/v2.9.6) (2022-12-07) | ||||
| [All Commits](https://github.com/traefik/traefik/compare/v2.9.5...v2.9.6) | ||||
|  | ||||
| @@ -140,6 +238,52 @@ | ||||
| - **[k8s/helm]** Update Helm installation section ([#9564](https://github.com/traefik/traefik/pull/9564) by [mloiseleur](https://github.com/mloiseleur)) | ||||
| - **[middleware]** Clarify PathPrefix matcher greediness ([#9519](https://github.com/traefik/traefik/pull/9519) by [mpl](https://github.com/mpl)) | ||||
|  | ||||
| ## [v3.0.0-beta1](https://github.com/traefik/traefik/tree/v3.0.0-beta1) (2022-12-05) | ||||
| [All Commits](https://github.com/traefik/traefik/compare/v2.9.0-rc1...v3.0.0-beta1) | ||||
|  | ||||
| **Enhancements:** | ||||
| - **[ecs]** Add option to keep only healthy ECS tasks ([#8027](https://github.com/traefik/traefik/pull/8027) by [Michampt](https://github.com/Michampt)) | ||||
| - **[healthcheck]** Support gRPC healthcheck ([#8583](https://github.com/traefik/traefik/pull/8583) by [jjacque](https://github.com/jjacque)) | ||||
| - **[healthcheck]** Add a status option to the service health check ([#9463](https://github.com/traefik/traefik/pull/9463) by [guoard](https://github.com/guoard)) | ||||
| - **[http]** Support custom headers when fetching configuration through HTTP ([#9421](https://github.com/traefik/traefik/pull/9421) by [kevinpollet](https://github.com/kevinpollet)) | ||||
| - **[logs,performance]** New logger for the Traefik logs ([#9515](https://github.com/traefik/traefik/pull/9515) by [ldez](https://github.com/ldez)) | ||||
| - **[logs,plugins]** Retry on plugin API calls ([#9530](https://github.com/traefik/traefik/pull/9530) by [ldez](https://github.com/ldez)) | ||||
| - **[logs,provider]** Improve provider logs ([#9562](https://github.com/traefik/traefik/pull/9562) by [ldez](https://github.com/ldez)) | ||||
| - **[logs]** Improve test logger assertions ([#9533](https://github.com/traefik/traefik/pull/9533) by [ldez](https://github.com/ldez)) | ||||
| - **[metrics]** Support gRPC and gRPC-Web protocol in metrics ([#9483](https://github.com/traefik/traefik/pull/9483) by [longit644](https://github.com/longit644)) | ||||
| - **[middleware,accesslogs]** Log TLS client subject ([#9285](https://github.com/traefik/traefik/pull/9285) by [xmessi](https://github.com/xmessi)) | ||||
| - **[middleware,metrics,tracing]** Add OpenTelemetry tracing and metrics support ([#8999](https://github.com/traefik/traefik/pull/8999) by [tomMoulard](https://github.com/tomMoulard)) | ||||
| - **[middleware]** Disable Content-Type auto-detection by default ([#9546](https://github.com/traefik/traefik/pull/9546) by [sdelicata](https://github.com/sdelicata)) | ||||
| - **[middleware]** Add gRPC-Web middleware ([#9451](https://github.com/traefik/traefik/pull/9451) by [juliens](https://github.com/juliens)) | ||||
| - **[middleware]** Add support for Brotli ([#9387](https://github.com/traefik/traefik/pull/9387) by [glinton](https://github.com/glinton)) | ||||
| - **[middleware]** Renaming IPWhiteList to IPAllowList  ([#9457](https://github.com/traefik/traefik/pull/9457) by [wxmbugu](https://github.com/wxmbugu)) | ||||
| - **[nomad]** Support multiple namespaces in the Nomad Provider ([#9332](https://github.com/traefik/traefik/pull/9332) by [0teh](https://github.com/0teh)) | ||||
| - **[rules]** Update routing syntax ([#9531](https://github.com/traefik/traefik/pull/9531) by [skwair](https://github.com/skwair)) | ||||
| - **[server]** Rework servers load-balancer to use the WRR ([#9431](https://github.com/traefik/traefik/pull/9431) by [juliens](https://github.com/juliens)) | ||||
| - **[server]** Allow default entrypoints definition ([#9100](https://github.com/traefik/traefik/pull/9100) by [jilleJr](https://github.com/jilleJr)) | ||||
| - **[tls,service]** Support SPIFFE mTLS between Traefik and Backend servers ([#9394](https://github.com/traefik/traefik/pull/9394) by [jlevesy](https://github.com/jlevesy)) | ||||
| - **[tls]** Add Tailscale certificate resolver ([#9237](https://github.com/traefik/traefik/pull/9237) by [kevinpollet](https://github.com/kevinpollet)) | ||||
| - **[tls]** Support SNI routing with Postgres STARTTLS connections ([#9377](https://github.com/traefik/traefik/pull/9377) by [rtribotte](https://github.com/rtribotte)) | ||||
| - Remove deprecated options ([#9527](https://github.com/traefik/traefik/pull/9527) by [sdelicata](https://github.com/sdelicata)) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - **[logs]** Fix log level ([#9545](https://github.com/traefik/traefik/pull/9545) by [ldez](https://github.com/ldez)) | ||||
| - **[metrics]** Fix ServerUp metric ([#9534](https://github.com/traefik/traefik/pull/9534) by [kevinpollet](https://github.com/kevinpollet)) | ||||
| - **[tls,service]** Enforce default servers transport SPIFFE config ([#9444](https://github.com/traefik/traefik/pull/9444) by [jlevesy](https://github.com/jlevesy)) | ||||
|  | ||||
| **Documentation:** | ||||
| - **[metrics]** Update and publish official Grafana Dashboard ([#9493](https://github.com/traefik/traefik/pull/9493) by [mloiseleur](https://github.com/mloiseleur)) | ||||
|  | ||||
| **Misc:** | ||||
| - Merge branch v2.9 into master ([#9554](https://github.com/traefik/traefik/pull/9554) by [ldez](https://github.com/ldez)) | ||||
| - Merge branch v2.9 into master ([#9536](https://github.com/traefik/traefik/pull/9536) by [ldez](https://github.com/ldez)) | ||||
| - Merge branch v2.9 into master ([#9532](https://github.com/traefik/traefik/pull/9532) by [ldez](https://github.com/ldez)) | ||||
| - Merge branch v2.9 into master ([#9482](https://github.com/traefik/traefik/pull/9482) by [kevinpollet](https://github.com/kevinpollet)) | ||||
| - Merge branch v2.9 into master ([#9464](https://github.com/traefik/traefik/pull/9464) by [ldez](https://github.com/ldez)) | ||||
| - Merge branch v2.9 into master ([#9449](https://github.com/traefik/traefik/pull/9449) by [kevinpollet](https://github.com/kevinpollet)) | ||||
| - Merge branch v2.9 into master ([#9419](https://github.com/traefik/traefik/pull/9419) by [kevinpollet](https://github.com/kevinpollet)) | ||||
| - Merge branch v2.9 into master ([#9351](https://github.com/traefik/traefik/pull/9351) by [rtribotte](https://github.com/rtribotte)) | ||||
|  | ||||
| ## [v2.9.5](https://github.com/traefik/traefik/tree/v2.9.5) (2022-11-17) | ||||
| [All Commits](https://github.com/traefik/traefik/compare/v2.9.4...v2.9.5) | ||||
|  | ||||
|   | ||||
							
								
								
									
										14
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,6 +1,10 @@ | ||||
|  | ||||
| <p align="center"> | ||||
| <img src="docs/content/assets/img/traefik.logo.png" alt="Traefik" title="Traefik" /> | ||||
|     <picture> | ||||
|       <source media="(prefers-color-scheme: dark)" srcset="docs/content/assets/img/traefik.logo-dark.png"> | ||||
|       <source media="(prefers-color-scheme: light)" srcset="docs/content/assets/img/traefik.logo.png"> | ||||
|       <img alt="Traefik" title="Traefik" src="docs/content/assets/img/traefik.logo.png"> | ||||
|     </picture> | ||||
| </p> | ||||
|  | ||||
| [](https://semaphoreci.com/containous/traefik) | ||||
| @@ -11,7 +15,7 @@ | ||||
| [](https://twitter.com/intent/follow?screen_name=traefik) | ||||
|  | ||||
| Traefik (pronounced _traffic_) is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy. | ||||
| Traefik integrates with your existing infrastructure components ([Docker](https://www.docker.com/), [Swarm mode](https://docs.docker.com/engine/swarm/), [Kubernetes](https://kubernetes.io), [Marathon](https://mesosphere.github.io/marathon/), [Consul](https://www.consul.io/), [Etcd](https://coreos.com/etcd/), [Rancher](https://rancher.com), [Amazon ECS](https://aws.amazon.com/ecs), ...) and configures itself automatically and dynamically. | ||||
| Traefik integrates with your existing infrastructure components ([Docker](https://www.docker.com/), [Swarm mode](https://docs.docker.com/engine/swarm/), [Kubernetes](https://kubernetes.io), [Consul](https://www.consul.io/), [Etcd](https://coreos.com/etcd/), [Rancher v2](https://rancher.com), [Amazon ECS](https://aws.amazon.com/ecs), ...) and configures itself automatically and dynamically. | ||||
| Pointing Traefik at your orchestrator should be the _only_ configuration step you need. | ||||
|  | ||||
| --- | ||||
| @@ -57,8 +61,8 @@ _(But if you'd rather configure some of your routes manually, Traefik supports t | ||||
| - Provides HTTPS to your microservices by leveraging [Let's Encrypt](https://letsencrypt.org)  (wildcard certificates support) | ||||
| - Circuit breakers, retry | ||||
| - See the magic through its clean web UI | ||||
| - Websocket, HTTP/2, GRPC ready | ||||
| - Provides metrics (Rest, Prometheus, Datadog, Statsd, InfluxDB) | ||||
| - Websocket, HTTP/2, gRPC ready | ||||
| - Provides metrics (Rest, Prometheus, Datadog, Statsd, InfluxDB 2.X) | ||||
| - Keeps access logs (JSON, CLF) | ||||
| - Fast | ||||
| - Exposes a Rest API | ||||
| @@ -68,8 +72,6 @@ _(But if you'd rather configure some of your routes manually, Traefik supports t | ||||
|  | ||||
| - [Docker](https://doc.traefik.io/traefik/providers/docker/) / [Swarm mode](https://doc.traefik.io/traefik/providers/docker/) | ||||
| - [Kubernetes](https://doc.traefik.io/traefik/providers/kubernetes-crd/) | ||||
| - [Marathon](https://doc.traefik.io/traefik/providers/marathon/) | ||||
| - [Rancher](https://doc.traefik.io/traefik/providers/rancher/) (Metadata) | ||||
| - [File](https://doc.traefik.io/traefik/providers/file/) | ||||
|  | ||||
| ## Quickstart | ||||
|   | ||||
| @@ -4,7 +4,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	ptypes "github.com/traefik/paerser/types" | ||||
| 	"github.com/traefik/traefik/v2/pkg/config/static" | ||||
| 	"github.com/traefik/traefik/v3/pkg/config/static" | ||||
| ) | ||||
|  | ||||
| // TraefikCmdConfiguration wraps the static configuration and extra parameters. | ||||
| @@ -28,6 +28,10 @@ func NewTraefikConfiguration() *TraefikCmdConfiguration { | ||||
| 			ServersTransport: &static.ServersTransport{ | ||||
| 				MaxIdleConnsPerHost: 200, | ||||
| 			}, | ||||
| 			TCPServersTransport: &static.TCPServersTransport{ | ||||
| 				DialTimeout:   ptypes.Duration(30 * time.Second), | ||||
| 				DialKeepAlive: ptypes.Duration(15 * time.Second), | ||||
| 			}, | ||||
| 		}, | ||||
| 		ConfigFile: "", | ||||
| 	} | ||||
|   | ||||
| @@ -8,7 +8,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/traefik/paerser/cli" | ||||
| 	"github.com/traefik/traefik/v2/pkg/config/static" | ||||
| 	"github.com/traefik/traefik/v3/pkg/config/static" | ||||
| ) | ||||
|  | ||||
| // NewCmd builds a new HealthCheck command. | ||||
|   | ||||
| @@ -11,7 +11,7 @@ import ( | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| const rootPkg = "github.com/traefik/traefik/v2/pkg/config/dynamic" | ||||
| const rootPkg = "github.com/traefik/traefik/v3/pkg/config/dynamic" | ||||
|  | ||||
| const ( | ||||
| 	destModuleName = "github.com/traefik/genconf" | ||||
| @@ -57,8 +57,8 @@ func run(dest string) error { | ||||
| 	} | ||||
|  | ||||
| 	centrifuge.IncludedImports = []string{ | ||||
| 		"github.com/traefik/traefik/v2/pkg/tls", | ||||
| 		"github.com/traefik/traefik/v2/pkg/types", | ||||
| 		"github.com/traefik/traefik/v3/pkg/tls", | ||||
| 		"github.com/traefik/traefik/v3/pkg/types", | ||||
| 	} | ||||
|  | ||||
| 	centrifuge.ExcludedTypes = []string{ | ||||
| @@ -71,8 +71,8 @@ func run(dest string) error { | ||||
| 	} | ||||
|  | ||||
| 	centrifuge.ExcludedFiles = []string{ | ||||
| 		"github.com/traefik/traefik/v2/pkg/types/logs.go", | ||||
| 		"github.com/traefik/traefik/v2/pkg/types/metrics.go", | ||||
| 		"github.com/traefik/traefik/v3/pkg/types/logs.go", | ||||
| 		"github.com/traefik/traefik/v3/pkg/types/metrics.go", | ||||
| 	} | ||||
|  | ||||
| 	centrifuge.TypeCleaner = cleanType | ||||
| @@ -87,11 +87,11 @@ func run(dest string) error { | ||||
| } | ||||
|  | ||||
| func cleanType(typ types.Type, base string) string { | ||||
| 	if typ.String() == "github.com/traefik/traefik/v2/pkg/tls.FileOrContent" { | ||||
| 	if typ.String() == "github.com/traefik/traefik/v3/pkg/tls.FileOrContent" { | ||||
| 		return "string" | ||||
| 	} | ||||
|  | ||||
| 	if typ.String() == "[]github.com/traefik/traefik/v2/pkg/tls.FileOrContent" { | ||||
| 	if typ.String() == "[]github.com/traefik/traefik/v3/pkg/tls.FileOrContent" { | ||||
| 		return "[]string" | ||||
| 	} | ||||
|  | ||||
| @@ -103,8 +103,8 @@ func cleanType(typ types.Type, base string) string { | ||||
| 		return strings.ReplaceAll(typ.String(), base+".", "") | ||||
| 	} | ||||
|  | ||||
| 	if strings.Contains(typ.String(), "github.com/traefik/traefik/v2/pkg/") { | ||||
| 		return strings.ReplaceAll(typ.String(), "github.com/traefik/traefik/v2/pkg/", "") | ||||
| 	if strings.Contains(typ.String(), "github.com/traefik/traefik/v3/pkg/") { | ||||
| 		return strings.ReplaceAll(typ.String(), "github.com/traefik/traefik/v3/pkg/", "") | ||||
| 	} | ||||
|  | ||||
| 	return typ.String() | ||||
| @@ -114,9 +114,9 @@ func cleanPackage(src string) string { | ||||
| 	switch src { | ||||
| 	case "github.com/traefik/paerser/types": | ||||
| 		return "" | ||||
| 	case "github.com/traefik/traefik/v2/pkg/tls": | ||||
| 	case "github.com/traefik/traefik/v3/pkg/tls": | ||||
| 		return path.Join(destModuleName, destPkg, "tls") | ||||
| 	case "github.com/traefik/traefik/v2/pkg/types": | ||||
| 	case "github.com/traefik/traefik/v3/pkg/types": | ||||
| 		return path.Join(destModuleName, destPkg, "types") | ||||
| 	default: | ||||
| 		return src | ||||
|   | ||||
							
								
								
									
										89
									
								
								cmd/traefik/logger.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								cmd/traefik/logger.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"io" | ||||
| 	stdlog "log" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/natefinch/lumberjack" | ||||
| 	"github.com/rs/zerolog" | ||||
| 	"github.com/rs/zerolog/log" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/traefik/traefik/v3/pkg/config/static" | ||||
| 	"github.com/traefik/traefik/v3/pkg/logs" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	// hide the first logs before the setup of the logger. | ||||
| 	zerolog.SetGlobalLevel(zerolog.ErrorLevel) | ||||
| } | ||||
|  | ||||
| func setupLogger(staticConfiguration *static.Configuration) { | ||||
| 	// configure log format | ||||
| 	w := getLogWriter(staticConfiguration) | ||||
|  | ||||
| 	// configure log level | ||||
| 	logLevel := getLogLevel(staticConfiguration) | ||||
|  | ||||
| 	// create logger | ||||
| 	logCtx := zerolog.New(w).With().Timestamp() | ||||
| 	if logLevel <= zerolog.DebugLevel { | ||||
| 		logCtx = logCtx.Caller() | ||||
| 	} | ||||
|  | ||||
| 	log.Logger = logCtx.Logger().Level(logLevel) | ||||
| 	zerolog.DefaultContextLogger = &log.Logger | ||||
| 	zerolog.SetGlobalLevel(logLevel) | ||||
|  | ||||
| 	// Global logrus replacement (related to lib like go-rancher-metadata, docker, etc.) | ||||
| 	logrus.StandardLogger().Out = logs.NoLevel(log.Logger, zerolog.DebugLevel) | ||||
|  | ||||
| 	// configure default standard log. | ||||
| 	stdlog.SetFlags(stdlog.Lshortfile | stdlog.LstdFlags) | ||||
| 	stdlog.SetOutput(logs.NoLevel(log.Logger, zerolog.DebugLevel)) | ||||
| } | ||||
|  | ||||
| func getLogWriter(staticConfiguration *static.Configuration) io.Writer { | ||||
| 	var w io.Writer = os.Stderr | ||||
|  | ||||
| 	if staticConfiguration.Log != nil && len(staticConfiguration.Log.FilePath) > 0 { | ||||
| 		_, _ = os.Create(staticConfiguration.Log.FilePath) | ||||
| 		w = &lumberjack.Logger{ | ||||
| 			Filename:   staticConfiguration.Log.FilePath, | ||||
| 			MaxSize:    staticConfiguration.Log.MaxSize, | ||||
| 			MaxBackups: staticConfiguration.Log.MaxBackups, | ||||
| 			MaxAge:     staticConfiguration.Log.MaxAge, | ||||
| 			Compress:   true, | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if staticConfiguration.Log == nil || staticConfiguration.Log.Format != "json" { | ||||
| 		w = zerolog.ConsoleWriter{ | ||||
| 			Out:        w, | ||||
| 			TimeFormat: time.RFC3339, | ||||
| 			NoColor:    staticConfiguration.Log != nil && (staticConfiguration.Log.NoColor || len(staticConfiguration.Log.FilePath) > 0), | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return w | ||||
| } | ||||
|  | ||||
| func getLogLevel(staticConfiguration *static.Configuration) zerolog.Level { | ||||
| 	levelStr := "error" | ||||
| 	if staticConfiguration.Log != nil && staticConfiguration.Log.Level != "" { | ||||
| 		levelStr = strings.ToLower(staticConfiguration.Log.Level) | ||||
| 	} | ||||
|  | ||||
| 	logLevel, err := zerolog.ParseLevel(strings.ToLower(levelStr)) | ||||
| 	if err != nil { | ||||
| 		log.Error().Err(err). | ||||
| 			Str("logLevel", levelStr). | ||||
| 			Msg("Unspecified or invalid log level, setting the level to default (ERROR)...") | ||||
|  | ||||
| 		logLevel = zerolog.ErrorLevel | ||||
| 	} | ||||
|  | ||||
| 	return logLevel | ||||
| } | ||||
| @@ -3,8 +3,8 @@ package main | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/traefik/traefik/v2/pkg/config/static" | ||||
| 	"github.com/traefik/traefik/v2/pkg/plugins" | ||||
| 	"github.com/traefik/traefik/v3/pkg/config/static" | ||||
| 	"github.com/traefik/traefik/v3/pkg/plugins" | ||||
| ) | ||||
|  | ||||
| const outputDir = "./plugins-storage/" | ||||
| @@ -35,12 +35,12 @@ func initPlugins(staticCfg *static.Configuration) (*plugins.Client, map[string]p | ||||
| 		var err error | ||||
| 		client, err = plugins.NewClient(opts) | ||||
| 		if err != nil { | ||||
| 			return nil, nil, nil, err | ||||
| 			return nil, nil, nil, fmt.Errorf("unable to create plugins client: %w", err) | ||||
| 		} | ||||
|  | ||||
| 		err = plugins.SetupRemotePlugins(client, staticCfg.Experimental.Plugins) | ||||
| 		if err != nil { | ||||
| 			return nil, nil, nil, err | ||||
| 			return nil, nil, nil, fmt.Errorf("unable to set up plugins environment: %w", err) | ||||
| 		} | ||||
|  | ||||
| 		plgs = staticCfg.Experimental.Plugins | ||||
|   | ||||
| @@ -9,7 +9,6 @@ import ( | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"os/signal" | ||||
| 	"path/filepath" | ||||
| 	"sort" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
| @@ -18,33 +17,35 @@ import ( | ||||
| 	"github.com/coreos/go-systemd/daemon" | ||||
| 	"github.com/go-acme/lego/v4/challenge" | ||||
| 	gokitmetrics "github.com/go-kit/kit/metrics" | ||||
| 	"github.com/rs/zerolog/log" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/spiffe/go-spiffe/v2/workloadapi" | ||||
| 	"github.com/traefik/paerser/cli" | ||||
| 	"github.com/traefik/traefik/v2/cmd" | ||||
| 	"github.com/traefik/traefik/v2/cmd/healthcheck" | ||||
| 	cmdVersion "github.com/traefik/traefik/v2/cmd/version" | ||||
| 	tcli "github.com/traefik/traefik/v2/pkg/cli" | ||||
| 	"github.com/traefik/traefik/v2/pkg/collector" | ||||
| 	"github.com/traefik/traefik/v2/pkg/config/dynamic" | ||||
| 	"github.com/traefik/traefik/v2/pkg/config/runtime" | ||||
| 	"github.com/traefik/traefik/v2/pkg/config/static" | ||||
| 	"github.com/traefik/traefik/v2/pkg/log" | ||||
| 	"github.com/traefik/traefik/v2/pkg/metrics" | ||||
| 	"github.com/traefik/traefik/v2/pkg/middlewares/accesslog" | ||||
| 	"github.com/traefik/traefik/v2/pkg/provider/acme" | ||||
| 	"github.com/traefik/traefik/v2/pkg/provider/aggregator" | ||||
| 	"github.com/traefik/traefik/v2/pkg/provider/hub" | ||||
| 	"github.com/traefik/traefik/v2/pkg/provider/traefik" | ||||
| 	"github.com/traefik/traefik/v2/pkg/safe" | ||||
| 	"github.com/traefik/traefik/v2/pkg/server" | ||||
| 	"github.com/traefik/traefik/v2/pkg/server/middleware" | ||||
| 	"github.com/traefik/traefik/v2/pkg/server/service" | ||||
| 	traefiktls "github.com/traefik/traefik/v2/pkg/tls" | ||||
| 	"github.com/traefik/traefik/v2/pkg/tracing" | ||||
| 	"github.com/traefik/traefik/v2/pkg/tracing/jaeger" | ||||
| 	"github.com/traefik/traefik/v2/pkg/types" | ||||
| 	"github.com/traefik/traefik/v2/pkg/version" | ||||
| 	"github.com/vulcand/oxy/v2/roundrobin" | ||||
| 	"github.com/traefik/traefik/v3/cmd" | ||||
| 	"github.com/traefik/traefik/v3/cmd/healthcheck" | ||||
| 	cmdVersion "github.com/traefik/traefik/v3/cmd/version" | ||||
| 	tcli "github.com/traefik/traefik/v3/pkg/cli" | ||||
| 	"github.com/traefik/traefik/v3/pkg/collector" | ||||
| 	"github.com/traefik/traefik/v3/pkg/config/dynamic" | ||||
| 	"github.com/traefik/traefik/v3/pkg/config/runtime" | ||||
| 	"github.com/traefik/traefik/v3/pkg/config/static" | ||||
| 	"github.com/traefik/traefik/v3/pkg/logs" | ||||
| 	"github.com/traefik/traefik/v3/pkg/metrics" | ||||
| 	"github.com/traefik/traefik/v3/pkg/middlewares/accesslog" | ||||
| 	"github.com/traefik/traefik/v3/pkg/provider/acme" | ||||
| 	"github.com/traefik/traefik/v3/pkg/provider/aggregator" | ||||
| 	"github.com/traefik/traefik/v3/pkg/provider/tailscale" | ||||
| 	"github.com/traefik/traefik/v3/pkg/provider/traefik" | ||||
| 	"github.com/traefik/traefik/v3/pkg/safe" | ||||
| 	"github.com/traefik/traefik/v3/pkg/server" | ||||
| 	"github.com/traefik/traefik/v3/pkg/server/middleware" | ||||
| 	"github.com/traefik/traefik/v3/pkg/server/service" | ||||
| 	"github.com/traefik/traefik/v3/pkg/tcp" | ||||
| 	traefiktls "github.com/traefik/traefik/v3/pkg/tls" | ||||
| 	"github.com/traefik/traefik/v3/pkg/tracing" | ||||
| 	"github.com/traefik/traefik/v3/pkg/tracing/jaeger" | ||||
| 	"github.com/traefik/traefik/v3/pkg/types" | ||||
| 	"github.com/traefik/traefik/v3/pkg/version" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| @@ -78,7 +79,7 @@ Complete documentation is available at https://traefik.io`, | ||||
|  | ||||
| 	err = cli.Execute(cmdTraefik) | ||||
| 	if err != nil { | ||||
| 		stdlog.Println(err) | ||||
| 		log.Error().Err(err).Msg("Command error") | ||||
| 		logrus.Exit(1) | ||||
| 	} | ||||
|  | ||||
| @@ -86,27 +87,24 @@ Complete documentation is available at https://traefik.io`, | ||||
| } | ||||
|  | ||||
| func runCmd(staticConfiguration *static.Configuration) error { | ||||
| 	configureLogging(staticConfiguration) | ||||
| 	setupLogger(staticConfiguration) | ||||
|  | ||||
| 	http.DefaultTransport.(*http.Transport).Proxy = http.ProxyFromEnvironment | ||||
|  | ||||
| 	if err := roundrobin.SetDefaultWeight(0); err != nil { | ||||
| 		log.WithoutContext().Errorf("Could not set round robin default weight: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	staticConfiguration.SetEffectiveConfiguration() | ||||
| 	if err := staticConfiguration.ValidateConfiguration(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	log.WithoutContext().Infof("Traefik version %s built on %s", version.Version, version.BuildDate) | ||||
| 	log.Info().Str("version", version.Version). | ||||
| 		Msgf("Traefik version %s built on %s", version.Version, version.BuildDate) | ||||
|  | ||||
| 	jsonConf, err := json.Marshal(staticConfiguration) | ||||
| 	if err != nil { | ||||
| 		log.WithoutContext().Errorf("Could not marshal static configuration: %v", err) | ||||
| 		log.WithoutContext().Debugf("Static configuration loaded [struct] %#v", staticConfiguration) | ||||
| 		log.Error().Err(err).Msg("Could not marshal static configuration") | ||||
| 		log.Debug().Interface("staticConfiguration", staticConfiguration).Msg("Static configuration loaded [struct]") | ||||
| 	} else { | ||||
| 		log.WithoutContext().Debugf("Static configuration loaded %s", string(jsonConf)) | ||||
| 		log.Debug().RawJSON("staticConfiguration", jsonConf).Msg("Static configuration loaded [json]") | ||||
| 	} | ||||
|  | ||||
| 	if staticConfiguration.Global.CheckNewVersion { | ||||
| @@ -131,16 +129,16 @@ func runCmd(staticConfiguration *static.Configuration) error { | ||||
|  | ||||
| 	sent, err := daemon.SdNotify(false, "READY=1") | ||||
| 	if !sent && err != nil { | ||||
| 		log.WithoutContext().Errorf("Failed to notify: %v", err) | ||||
| 		log.Error().Err(err).Msg("Failed to notify") | ||||
| 	} | ||||
|  | ||||
| 	t, err := daemon.SdWatchdogEnabled(false) | ||||
| 	if err != nil { | ||||
| 		log.WithoutContext().Errorf("Could not enable Watchdog: %v", err) | ||||
| 		log.Error().Err(err).Msg("Could not enable Watchdog") | ||||
| 	} else if t != 0 { | ||||
| 		// Send a ping each half time given | ||||
| 		t /= 2 | ||||
| 		log.WithoutContext().Infof("Watchdog activated with timer duration %s", t) | ||||
| 		log.Info().Msgf("Watchdog activated with timer duration %s", t) | ||||
| 		safe.Go(func() { | ||||
| 			tick := time.Tick(t) | ||||
| 			for range tick { | ||||
| @@ -151,17 +149,17 @@ func runCmd(staticConfiguration *static.Configuration) error { | ||||
|  | ||||
| 				if staticConfiguration.Ping == nil || errHealthCheck == nil { | ||||
| 					if ok, _ := daemon.SdNotify(false, "WATCHDOG=1"); !ok { | ||||
| 						log.WithoutContext().Error("Fail to tick watchdog") | ||||
| 						log.Error().Msg("Fail to tick watchdog") | ||||
| 					} | ||||
| 				} else { | ||||
| 					log.WithoutContext().Error(errHealthCheck) | ||||
| 					log.Error().Err(errHealthCheck).Send() | ||||
| 				} | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| 	svr.Wait() | ||||
| 	log.WithoutContext().Info("Shutting down") | ||||
| 	log.Info().Msg("Shutting down") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @@ -190,9 +188,18 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err | ||||
|  | ||||
| 	acmeProviders := initACMEProvider(staticConfiguration, &providerAggregator, tlsManager, httpChallengeProvider, tlsChallengeProvider) | ||||
|  | ||||
| 	// Tailscale | ||||
|  | ||||
| 	tsProviders := initTailscaleProviders(staticConfiguration, &providerAggregator) | ||||
|  | ||||
| 	// Metrics | ||||
|  | ||||
| 	metricRegistries := registerMetricClients(staticConfiguration.Metrics) | ||||
| 	metricsRegistry := metrics.NewMultiRegistry(metricRegistries) | ||||
|  | ||||
| 	// Entrypoints | ||||
|  | ||||
| 	serverEntryPointsTCP, err := server.NewTCPEntryPoints(staticConfiguration.EntryPoints, staticConfiguration.HostResolver) | ||||
| 	serverEntryPointsTCP, err := server.NewTCPEntryPoints(staticConfiguration.EntryPoints, staticConfiguration.HostResolver, metricsRegistry) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -202,15 +209,11 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if staticConfiguration.Pilot != nil { | ||||
| 		log.WithoutContext().Warn("Traefik Pilot has been removed.") | ||||
| 	} | ||||
|  | ||||
| 	// Plugins | ||||
|  | ||||
| 	pluginBuilder, err := createPluginBuilder(staticConfiguration) | ||||
| 	if err != nil { | ||||
| 		log.WithoutContext().WithError(err).Error("Plugins are disabled because an error has occurred.") | ||||
| 		log.Error().Err(err).Msg("Plugins are disabled because an error has occurred.") | ||||
| 	} | ||||
|  | ||||
| 	// Providers plugins | ||||
| @@ -231,27 +234,29 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Traefik Hub | ||||
|  | ||||
| 	if staticConfiguration.Hub != nil { | ||||
| 		if err = providerAggregator.AddProvider(staticConfiguration.Hub); err != nil { | ||||
| 			return nil, fmt.Errorf("adding Traefik Hub provider: %w", err) | ||||
| 		} | ||||
|  | ||||
| 		// API is mandatory for Traefik Hub to access the dynamic configuration. | ||||
| 		if staticConfiguration.API == nil { | ||||
| 			staticConfiguration.API = &static.API{} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Metrics | ||||
|  | ||||
| 	metricRegistries := registerMetricClients(staticConfiguration.Metrics) | ||||
| 	metricsRegistry := metrics.NewMultiRegistry(metricRegistries) | ||||
|  | ||||
| 	// Service manager factory | ||||
|  | ||||
| 	roundTripperManager := service.NewRoundTripperManager() | ||||
| 	var spiffeX509Source *workloadapi.X509Source | ||||
| 	if staticConfiguration.Spiffe != nil && staticConfiguration.Spiffe.WorkloadAPIAddr != "" { | ||||
| 		log.Info().Str("workloadAPIAddr", staticConfiguration.Spiffe.WorkloadAPIAddr). | ||||
| 			Msg("Waiting on SPIFFE SVID delivery") | ||||
|  | ||||
| 		spiffeX509Source, err = workloadapi.NewX509Source( | ||||
| 			ctx, | ||||
| 			workloadapi.WithClientOptions( | ||||
| 				workloadapi.WithAddr( | ||||
| 					staticConfiguration.Spiffe.WorkloadAPIAddr, | ||||
| 				), | ||||
| 			), | ||||
| 		) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("unable to create SPIFFE x509 source: %w", err) | ||||
| 		} | ||||
| 		log.Info().Msg("Successfully obtained SPIFFE SVID.") | ||||
| 	} | ||||
|  | ||||
| 	roundTripperManager := service.NewRoundTripperManager(spiffeX509Source) | ||||
| 	dialerManager := tcp.NewDialerManager(spiffeX509Source) | ||||
| 	acmeHTTPHandler := getHTTPChallengeHandler(acmeProviders, httpChallengeProvider) | ||||
| 	managerFactory := service.NewManagerFactory(*staticConfiguration, routinesPool, metricsRegistry, roundTripperManager, acmeHTTPHandler) | ||||
|  | ||||
| @@ -261,7 +266,7 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err | ||||
| 	tracer := setupTracing(staticConfiguration.Tracing) | ||||
|  | ||||
| 	chainBuilder := middleware.NewChainBuilder(metricsRegistry, accessLog, tracer) | ||||
| 	routerFactory := server.NewRouterFactory(*staticConfiguration, managerFactory, tlsManager, chainBuilder, pluginBuilder, metricsRegistry) | ||||
| 	routerFactory := server.NewRouterFactory(*staticConfiguration, managerFactory, tlsManager, chainBuilder, pluginBuilder, metricsRegistry, dialerManager) | ||||
|  | ||||
| 	// Watcher | ||||
|  | ||||
| @@ -292,13 +297,14 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err | ||||
| 	// Server Transports | ||||
| 	watcher.AddListener(func(conf dynamic.Configuration) { | ||||
| 		roundTripperManager.Update(conf.HTTP.ServersTransports) | ||||
| 		dialerManager.Update(conf.TCP.ServersTransports) | ||||
| 	}) | ||||
|  | ||||
| 	// Switch router | ||||
| 	watcher.AddListener(switchRouter(routerFactory, serverEntryPointsTCP, serverEntryPointsUDP)) | ||||
|  | ||||
| 	// Metrics | ||||
| 	if metricsRegistry.IsEpEnabled() || metricsRegistry.IsSvcEnabled() { | ||||
| 	if metricsRegistry.IsEpEnabled() || metricsRegistry.IsRouterEnabled() || metricsRegistry.IsSvcEnabled() { | ||||
| 		var eps []string | ||||
| 		for key := range serverEntryPointsTCP { | ||||
| 			eps = append(eps, key) | ||||
| @@ -311,13 +317,22 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err | ||||
| 	// TLS challenge | ||||
| 	watcher.AddListener(tlsChallengeProvider.ListenConfiguration) | ||||
|  | ||||
| 	// ACME | ||||
| 	// Certificate Resolvers | ||||
|  | ||||
| 	resolverNames := map[string]struct{}{} | ||||
|  | ||||
| 	// ACME | ||||
| 	for _, p := range acmeProviders { | ||||
| 		resolverNames[p.ResolverName] = struct{}{} | ||||
| 		watcher.AddListener(p.ListenConfiguration) | ||||
| 	} | ||||
|  | ||||
| 	// Tailscale | ||||
| 	for _, p := range tsProviders { | ||||
| 		resolverNames[p.ResolverName] = struct{}{} | ||||
| 		watcher.AddListener(p.HandleConfigUpdate) | ||||
| 	} | ||||
|  | ||||
| 	// Certificate resolver logs | ||||
| 	watcher.AddListener(func(config dynamic.Configuration) { | ||||
| 		for rtName, rt := range config.HTTP.Routers { | ||||
| @@ -325,11 +340,9 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			if _, ok := resolverNames[rt.TLS.CertResolver]; !ok && | ||||
| 				// "traefik-hub" is an allowed certificate resolver name in a Traefik Hub Experimental feature context. | ||||
| 				// It is used to activate its own certificate resolution, even though it is not a "classical" traefik certificate resolver. | ||||
| 				(staticConfiguration.Hub == nil || rt.TLS.CertResolver != "traefik-hub") { | ||||
| 				log.WithoutContext().Errorf("the router %s uses a non-existent resolver: %s", rtName, rt.TLS.CertResolver) | ||||
| 			if _, ok := resolverNames[rt.TLS.CertResolver]; !ok { | ||||
| 				log.Error().Err(err).Str(logs.RouterName, rtName).Str("certificateResolver", rt.TLS.CertResolver). | ||||
| 					Msg("Router uses a non-existent certificate resolver") | ||||
| 			} | ||||
| 		} | ||||
| 	}) | ||||
| @@ -350,16 +363,27 @@ func getHTTPChallengeHandler(acmeProviders []*acme.Provider, httpChallengeProvid | ||||
|  | ||||
| func getDefaultsEntrypoints(staticConfiguration *static.Configuration) []string { | ||||
| 	var defaultEntryPoints []string | ||||
|  | ||||
| 	// Determines if at least one EntryPoint is configured to be used by default. | ||||
| 	var hasDefinedDefaults bool | ||||
| 	for _, ep := range staticConfiguration.EntryPoints { | ||||
| 		if ep.AsDefault { | ||||
| 			hasDefinedDefaults = true | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for name, cfg := range staticConfiguration.EntryPoints { | ||||
| 		// Traefik Hub entryPoint should not be part of the set of default entryPoints. | ||||
| 		if hub.APIEntrypoint == name || hub.TunnelEntrypoint == name { | ||||
| 		// By default all entrypoints are considered. | ||||
| 		// If at least one is flagged, then only flagged entrypoints are included. | ||||
| 		if hasDefinedDefaults && !cfg.AsDefault { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		protocol, err := cfg.GetProtocol() | ||||
| 		if err != nil { | ||||
| 			// Should never happen because Traefik should not start if protocol is invalid. | ||||
| 			log.WithoutContext().Errorf("Invalid protocol: %v", err) | ||||
| 			log.Error().Err(err).Msg("Invalid protocol") | ||||
| 		} | ||||
|  | ||||
| 		if protocol != "udp" && name != static.DefaultInternalEntryPointName { | ||||
| @@ -382,7 +406,7 @@ func switchRouter(routerFactory *server.RouterFactory, serverEntryPointsTCP serv | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // initACMEProvider creates an acme provider from the ACME part of globalConfiguration. | ||||
| // initACMEProvider creates and registers acme.Provider instances corresponding to the configured ACME certificate resolvers. | ||||
| func initACMEProvider(c *static.Configuration, providerAggregator *aggregator.ProviderAggregator, tlsManager *traefiktls.Manager, httpChallengeProvider, tlsChallengeProvider challenge.Provider) []*acme.Provider { | ||||
| 	localStores := map[string]*acme.LocalStore{} | ||||
|  | ||||
| @@ -405,7 +429,7 @@ func initACMEProvider(c *static.Configuration, providerAggregator *aggregator.Pr | ||||
| 		} | ||||
|  | ||||
| 		if err := providerAggregator.AddProvider(p); err != nil { | ||||
| 			log.WithoutContext().Errorf("The ACME resolver %q is skipped from the resolvers list because: %v", name, err) | ||||
| 			log.Error().Err(err).Str("resolver", name).Msg("The ACME resolve is skipped from the resolvers list") | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| @@ -419,6 +443,27 @@ func initACMEProvider(c *static.Configuration, providerAggregator *aggregator.Pr | ||||
| 	return resolvers | ||||
| } | ||||
|  | ||||
| // initTailscaleProviders creates and registers tailscale.Provider instances corresponding to the configured Tailscale certificate resolvers. | ||||
| func initTailscaleProviders(cfg *static.Configuration, providerAggregator *aggregator.ProviderAggregator) []*tailscale.Provider { | ||||
| 	var providers []*tailscale.Provider | ||||
| 	for name, resolver := range cfg.CertificatesResolvers { | ||||
| 		if resolver.Tailscale == nil { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		tsProvider := &tailscale.Provider{ResolverName: name} | ||||
|  | ||||
| 		if err := providerAggregator.AddProvider(tsProvider); err != nil { | ||||
| 			log.Error().Err(err).Str(logs.ProviderName, name).Msg("Unable to create Tailscale provider") | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		providers = append(providers, tsProvider) | ||||
| 	} | ||||
|  | ||||
| 	return providers | ||||
| } | ||||
|  | ||||
| func registerMetricClients(metricsConfig *types.Metrics) []metrics.Registry { | ||||
| 	if metricsConfig == nil { | ||||
| 		return nil | ||||
| @@ -427,42 +472,60 @@ func registerMetricClients(metricsConfig *types.Metrics) []metrics.Registry { | ||||
| 	var registries []metrics.Registry | ||||
|  | ||||
| 	if metricsConfig.Prometheus != nil { | ||||
| 		ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "prometheus")) | ||||
| 		prometheusRegister := metrics.RegisterPrometheus(ctx, metricsConfig.Prometheus) | ||||
| 		logger := log.With().Str(logs.MetricsProviderName, "prometheus").Logger() | ||||
|  | ||||
| 		prometheusRegister := metrics.RegisterPrometheus(logger.WithContext(context.Background()), metricsConfig.Prometheus) | ||||
| 		if prometheusRegister != nil { | ||||
| 			registries = append(registries, prometheusRegister) | ||||
| 			log.FromContext(ctx).Debug("Configured Prometheus metrics") | ||||
| 			logger.Debug().Msg("Configured Prometheus metrics") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if metricsConfig.Datadog != nil { | ||||
| 		ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "datadog")) | ||||
| 		registries = append(registries, metrics.RegisterDatadog(ctx, metricsConfig.Datadog)) | ||||
| 		log.FromContext(ctx).Debugf("Configured Datadog metrics: pushing to %s once every %s", | ||||
| 			metricsConfig.Datadog.Address, metricsConfig.Datadog.PushInterval) | ||||
| 		logger := log.With().Str(logs.MetricsProviderName, "datadog").Logger() | ||||
|  | ||||
| 		registries = append(registries, metrics.RegisterDatadog(logger.WithContext(context.Background()), metricsConfig.Datadog)) | ||||
| 		logger.Debug(). | ||||
| 			Str("address", metricsConfig.Datadog.Address). | ||||
| 			Str("pushInterval", metricsConfig.Datadog.PushInterval.String()). | ||||
| 			Msgf("Configured Datadog metrics") | ||||
| 	} | ||||
|  | ||||
| 	if metricsConfig.StatsD != nil { | ||||
| 		ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "statsd")) | ||||
| 		registries = append(registries, metrics.RegisterStatsd(ctx, metricsConfig.StatsD)) | ||||
| 		log.FromContext(ctx).Debugf("Configured StatsD metrics: pushing to %s once every %s", | ||||
| 			metricsConfig.StatsD.Address, metricsConfig.StatsD.PushInterval) | ||||
| 	} | ||||
| 		logger := log.With().Str(logs.MetricsProviderName, "statsd").Logger() | ||||
|  | ||||
| 	if metricsConfig.InfluxDB != nil { | ||||
| 		ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "influxdb")) | ||||
| 		registries = append(registries, metrics.RegisterInfluxDB(ctx, metricsConfig.InfluxDB)) | ||||
| 		log.FromContext(ctx).Debugf("Configured InfluxDB metrics: pushing to %s once every %s", | ||||
| 			metricsConfig.InfluxDB.Address, metricsConfig.InfluxDB.PushInterval) | ||||
| 		registries = append(registries, metrics.RegisterStatsd(logger.WithContext(context.Background()), metricsConfig.StatsD)) | ||||
| 		logger.Debug(). | ||||
| 			Str("address", metricsConfig.StatsD.Address). | ||||
| 			Str("pushInterval", metricsConfig.StatsD.PushInterval.String()). | ||||
| 			Msg("Configured StatsD metrics") | ||||
| 	} | ||||
|  | ||||
| 	if metricsConfig.InfluxDB2 != nil { | ||||
| 		ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "influxdb2")) | ||||
| 		influxDB2Register := metrics.RegisterInfluxDB2(ctx, metricsConfig.InfluxDB2) | ||||
| 		logger := log.With().Str(logs.MetricsProviderName, "influxdb2").Logger() | ||||
|  | ||||
| 		influxDB2Register := metrics.RegisterInfluxDB2(logger.WithContext(context.Background()), metricsConfig.InfluxDB2) | ||||
| 		if influxDB2Register != nil { | ||||
| 			registries = append(registries, influxDB2Register) | ||||
| 			log.FromContext(ctx).Debugf("Configured InfluxDB v2 metrics: pushing to %s (%s org/%s bucket) once every %s", | ||||
| 				metricsConfig.InfluxDB2.Address, metricsConfig.InfluxDB2.Org, metricsConfig.InfluxDB2.Bucket, metricsConfig.InfluxDB2.PushInterval) | ||||
| 			logger.Debug(). | ||||
| 				Str("address", metricsConfig.InfluxDB2.Address). | ||||
| 				Str("bucket", metricsConfig.InfluxDB2.Bucket). | ||||
| 				Str("organization", metricsConfig.InfluxDB2.Org). | ||||
| 				Str("pushInterval", metricsConfig.InfluxDB2.PushInterval.String()). | ||||
| 				Msg("Configured InfluxDB v2 metrics") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if metricsConfig.OpenTelemetry != nil { | ||||
| 		logger := log.With().Str(logs.MetricsProviderName, "openTelemetry").Logger() | ||||
|  | ||||
| 		openTelemetryRegistry := metrics.RegisterOpenTelemetry(logger.WithContext(context.Background()), metricsConfig.OpenTelemetry) | ||||
| 		if openTelemetryRegistry != nil { | ||||
| 			registries = append(registries, openTelemetryRegistry) | ||||
| 			logger.Debug(). | ||||
| 				Str("address", metricsConfig.OpenTelemetry.Address). | ||||
| 				Str("pushInterval", metricsConfig.OpenTelemetry.PushInterval.String()). | ||||
| 				Msg("Configured OpenTelemetry metrics") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -490,7 +553,7 @@ func setupAccessLog(conf *types.AccessLog) *accesslog.Handler { | ||||
|  | ||||
| 	accessLoggerMiddleware, err := accesslog.NewHandler(conf) | ||||
| 	if err != nil { | ||||
| 		log.WithoutContext().Warnf("Unable to create access logger: %v", err) | ||||
| 		log.Warn().Err(err).Msg("Unable to create access logger") | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| @@ -510,7 +573,7 @@ func setupTracing(conf *static.Tracing) *tracing.Tracing { | ||||
|  | ||||
| 	if conf.Zipkin != nil { | ||||
| 		if backend != nil { | ||||
| 			log.WithoutContext().Error("Multiple tracing backend are not supported: cannot create Zipkin backend.") | ||||
| 			log.Error().Msg("Multiple tracing backend are not supported: cannot create Zipkin backend.") | ||||
| 		} else { | ||||
| 			backend = conf.Zipkin | ||||
| 		} | ||||
| @@ -518,7 +581,7 @@ func setupTracing(conf *static.Tracing) *tracing.Tracing { | ||||
|  | ||||
| 	if conf.Datadog != nil { | ||||
| 		if backend != nil { | ||||
| 			log.WithoutContext().Error("Multiple tracing backend are not supported: cannot create Datadog backend.") | ||||
| 			log.Error().Msg("Multiple tracing backend are not supported: cannot create Datadog backend.") | ||||
| 		} else { | ||||
| 			backend = conf.Datadog | ||||
| 		} | ||||
| @@ -526,7 +589,7 @@ func setupTracing(conf *static.Tracing) *tracing.Tracing { | ||||
|  | ||||
| 	if conf.Instana != nil { | ||||
| 		if backend != nil { | ||||
| 			log.WithoutContext().Error("Multiple tracing backend are not supported: cannot create Instana backend.") | ||||
| 			log.Error().Msg("Multiple tracing backend are not supported: cannot create Instana backend.") | ||||
| 		} else { | ||||
| 			backend = conf.Instana | ||||
| 		} | ||||
| @@ -534,7 +597,7 @@ func setupTracing(conf *static.Tracing) *tracing.Tracing { | ||||
|  | ||||
| 	if conf.Haystack != nil { | ||||
| 		if backend != nil { | ||||
| 			log.WithoutContext().Error("Multiple tracing backend are not supported: cannot create Haystack backend.") | ||||
| 			log.Error().Msg("Multiple tracing backend are not supported: cannot create Haystack backend.") | ||||
| 		} else { | ||||
| 			backend = conf.Haystack | ||||
| 		} | ||||
| @@ -542,14 +605,22 @@ func setupTracing(conf *static.Tracing) *tracing.Tracing { | ||||
|  | ||||
| 	if conf.Elastic != nil { | ||||
| 		if backend != nil { | ||||
| 			log.WithoutContext().Error("Multiple tracing backend are not supported: cannot create Elastic backend.") | ||||
| 			log.Error().Msg("Multiple tracing backend are not supported: cannot create Elastic backend.") | ||||
| 		} else { | ||||
| 			backend = conf.Elastic | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if conf.OpenTelemetry != nil { | ||||
| 		if backend != nil { | ||||
| 			log.Error().Msg("Tracing backends are all mutually exclusive: cannot create OpenTelemetry backend.") | ||||
| 		} else { | ||||
| 			backend = conf.OpenTelemetry | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if backend == nil { | ||||
| 		log.WithoutContext().Debug("Could not initialize tracing, using Jaeger by default") | ||||
| 		log.Debug().Msg("Could not initialize tracing, using Jaeger by default") | ||||
| 		defaultBackend := &jaeger.Config{} | ||||
| 		defaultBackend.SetDefaults() | ||||
| 		backend = defaultBackend | ||||
| @@ -557,65 +628,12 @@ func setupTracing(conf *static.Tracing) *tracing.Tracing { | ||||
|  | ||||
| 	tracer, err := tracing.NewTracing(conf.ServiceName, conf.SpanNameLimit, backend) | ||||
| 	if err != nil { | ||||
| 		log.WithoutContext().Warnf("Unable to create tracer: %v", err) | ||||
| 		log.Warn().Err(err).Msg("Unable to create tracer") | ||||
| 		return nil | ||||
| 	} | ||||
| 	return tracer | ||||
| } | ||||
|  | ||||
| func configureLogging(staticConfiguration *static.Configuration) { | ||||
| 	// configure default log flags | ||||
| 	stdlog.SetFlags(stdlog.Lshortfile | stdlog.LstdFlags) | ||||
|  | ||||
| 	// configure log level | ||||
| 	// an explicitly defined log level always has precedence. if none is | ||||
| 	// given and debug mode is disabled, the default is ERROR, and DEBUG | ||||
| 	// otherwise. | ||||
| 	levelStr := "error" | ||||
| 	if staticConfiguration.Log != nil && staticConfiguration.Log.Level != "" { | ||||
| 		levelStr = strings.ToLower(staticConfiguration.Log.Level) | ||||
| 	} | ||||
|  | ||||
| 	level, err := logrus.ParseLevel(levelStr) | ||||
| 	if err != nil { | ||||
| 		log.WithoutContext().Errorf("Error getting level: %v", err) | ||||
| 	} | ||||
| 	log.SetLevel(level) | ||||
|  | ||||
| 	var logFile string | ||||
| 	if staticConfiguration.Log != nil && len(staticConfiguration.Log.FilePath) > 0 { | ||||
| 		logFile = staticConfiguration.Log.FilePath | ||||
| 	} | ||||
|  | ||||
| 	// configure log format | ||||
| 	var formatter logrus.Formatter | ||||
| 	if staticConfiguration.Log != nil && staticConfiguration.Log.Format == "json" { | ||||
| 		formatter = &logrus.JSONFormatter{} | ||||
| 	} else { | ||||
| 		disableColors := len(logFile) > 0 | ||||
| 		formatter = &logrus.TextFormatter{DisableColors: disableColors, FullTimestamp: true, DisableSorting: true} | ||||
| 	} | ||||
| 	log.SetFormatter(formatter) | ||||
|  | ||||
| 	if len(logFile) > 0 { | ||||
| 		dir := filepath.Dir(logFile) | ||||
|  | ||||
| 		if err := os.MkdirAll(dir, 0o755); err != nil { | ||||
| 			log.WithoutContext().Errorf("Failed to create log path %s: %s", dir, err) | ||||
| 		} | ||||
|  | ||||
| 		err = log.OpenFile(logFile) | ||||
| 		logrus.RegisterExitHandler(func() { | ||||
| 			if err := log.CloseFile(); err != nil { | ||||
| 				log.WithoutContext().Errorf("Error while closing log: %v", err) | ||||
| 			} | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			log.WithoutContext().Errorf("Error while opening log file %s: %v", logFile, err) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func checkNewVersion() { | ||||
| 	ticker := time.Tick(24 * time.Hour) | ||||
| 	safe.Go(func() { | ||||
| @@ -626,16 +644,16 @@ func checkNewVersion() { | ||||
| } | ||||
|  | ||||
| func stats(staticConfiguration *static.Configuration) { | ||||
| 	logger := log.WithoutContext() | ||||
| 	logger := log.Info() | ||||
|  | ||||
| 	if staticConfiguration.Global.SendAnonymousUsage { | ||||
| 		logger.Info(`Stats collection is enabled.`) | ||||
| 		logger.Info(`Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration.`) | ||||
| 		logger.Info(`Help us improve Traefik by leaving this feature on :)`) | ||||
| 		logger.Info(`More details on: https://doc.traefik.io/traefik/contributing/data-collection/`) | ||||
| 		logger.Msg(`Stats collection is enabled.`) | ||||
| 		logger.Msg(`Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration.`) | ||||
| 		logger.Msg(`Help us improve Traefik by leaving this feature on :)`) | ||||
| 		logger.Msg(`More details on: https://doc.traefik.io/traefik/contributing/data-collection/`) | ||||
| 		collect(staticConfiguration) | ||||
| 	} else { | ||||
| 		logger.Info(` | ||||
| 		logger.Msg(` | ||||
| Stats collection is disabled. | ||||
| Help us improve Traefik by turning this feature on :) | ||||
| More details on: https://doc.traefik.io/traefik/contributing/data-collection/ | ||||
| @@ -648,7 +666,7 @@ func collect(staticConfiguration *static.Configuration) { | ||||
| 	safe.Go(func() { | ||||
| 		for time.Sleep(10 * time.Minute); ; <-ticker { | ||||
| 			if err := collector.Collect(staticConfiguration); err != nil { | ||||
| 				log.WithoutContext().Debug(err) | ||||
| 				log.Debug().Err(err).Send() | ||||
| 			} | ||||
| 		} | ||||
| 	}) | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import ( | ||||
| 	"github.com/go-kit/kit/metrics" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| 	"github.com/traefik/traefik/v3/pkg/config/static" | ||||
| ) | ||||
|  | ||||
| // FooCert is a PEM-encoded TLS cert. | ||||
| @@ -114,3 +115,79 @@ func TestAppendCertMetric(t *testing.T) { | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestGetDefaultsEntrypoints(t *testing.T) { | ||||
| 	testCases := []struct { | ||||
| 		desc        string | ||||
| 		entrypoints static.EntryPoints | ||||
| 		expected    []string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			desc: "Skips special names", | ||||
| 			entrypoints: map[string]*static.EntryPoint{ | ||||
| 				"web": { | ||||
| 					Address: ":80", | ||||
| 				}, | ||||
| 				"traefik": { | ||||
| 					Address: ":8080", | ||||
| 				}, | ||||
| 				"traefikhub-api": { | ||||
| 					Address: ":9900", | ||||
| 				}, | ||||
| 				"traefikhub-tunl": { | ||||
| 					Address: ":9901", | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: []string{"web"}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc: "Two EntryPoints not attachable", | ||||
| 			entrypoints: map[string]*static.EntryPoint{ | ||||
| 				"web": { | ||||
| 					Address: ":80", | ||||
| 				}, | ||||
| 				"websecure": { | ||||
| 					Address: ":443", | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: []string{"web", "websecure"}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc: "Two EntryPoints only one attachable", | ||||
| 			entrypoints: map[string]*static.EntryPoint{ | ||||
| 				"web": { | ||||
| 					Address: ":80", | ||||
| 				}, | ||||
| 				"websecure": { | ||||
| 					Address:   ":443", | ||||
| 					AsDefault: true, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: []string{"websecure"}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc: "Two attachable EntryPoints", | ||||
| 			entrypoints: map[string]*static.EntryPoint{ | ||||
| 				"web": { | ||||
| 					Address:   ":80", | ||||
| 					AsDefault: true, | ||||
| 				}, | ||||
| 				"websecure": { | ||||
| 					Address:   ":443", | ||||
| 					AsDefault: true, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: []string{"web", "websecure"}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, test := range testCases { | ||||
| 		t.Run(test.desc, func(t *testing.T) { | ||||
| 			actual := getDefaultsEntrypoints(&static.Configuration{ | ||||
| 				EntryPoints: test.entrypoints, | ||||
| 			}) | ||||
|  | ||||
| 			assert.ElementsMatch(t, test.expected, actual) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -8,7 +8,7 @@ import ( | ||||
| 	"text/template" | ||||
|  | ||||
| 	"github.com/traefik/paerser/cli" | ||||
| 	"github.com/traefik/traefik/v2/pkg/version" | ||||
| 	"github.com/traefik/traefik/v3/pkg/version" | ||||
| ) | ||||
|  | ||||
| var versionTemplate = `Version:      {{.Version}} | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 58 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docs/content/assets/img/traefik.logo-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/content/assets/img/traefik.logo-dark.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 38 KiB | 
| @@ -66,7 +66,6 @@ providers: | ||||
|   docker: | ||||
|     endpoint: "tcp://10.10.10.10:2375" | ||||
|     exposedByDefault: true | ||||
|     swarmMode: true | ||||
|  | ||||
|     tls: | ||||
|       ca: dockerCA | ||||
| @@ -86,7 +85,6 @@ providers: | ||||
|   docker: | ||||
|     endpoint: "xxxx" | ||||
|     exposedByDefault: true | ||||
|     swarmMode: true | ||||
|  | ||||
|     tls: | ||||
|       ca: xxxx | ||||
|   | ||||
| @@ -107,7 +107,6 @@ The `status/*` labels represent the desired state in the workflow. | ||||
| * `area/provider/kv`: KV related. | ||||
| * `area/provider/marathon`: Marathon related. | ||||
| * `area/provider/mesos`: Mesos related. | ||||
| * `area/provider/rancher`: Rancher related. | ||||
| * `area/provider/servicefabric`: Azure service fabric related. | ||||
| * `area/provider/zk`: Zoo Keeper related. | ||||
| * `area/rules`: Rules related. | ||||
|   | ||||
| @@ -2,43 +2,22 @@ | ||||
|  | ||||
| This page is maintained and updated periodically to reflect our roadmap and any decisions around feature deprecation. | ||||
|  | ||||
| | Feature                                                                                             | Deprecated | End of Support | Removal | | ||||
| |-----------------------------------------------------------------------------------------------------|------------|----------------|---------| | ||||
| | [Pilot](#pilot)                                                                                     | 2.7        | 2.8            | 2.9     | | ||||
| | [Consul Enterprise Namespace](#consul-enterprise-namespace)                                         | 2.8        | N/A            | 3.0     | | ||||
| | [TLS 1.0 and 1.1 Support](#tls-10-and-11)                                                           | N/A        | 2.8            | N/A     | | ||||
| | [Nomad Namespace](#nomad-namespace)                                                                 | 2.10       | N/A            | 3.0     | | ||||
| | [Kubernetes CRDs API Group `traefik.containo.us`](#kubernetes-crds-api-group-traefikcontainous)     | 2.10       | N/A            | 3.0     | | ||||
| | [Kubernetes CRDs API Version `traefik.io/v1alpha1`](#kubernetes-crds-api-version-traefikiov1alpha1) | N/A        | N/A            | 3.0     | | ||||
| | Feature                                                                                                              | Deprecated | End of Support | Removal | | ||||
| |----------------------------------------------------------------------------------------------------------------------|------------|----------------|---------| | ||||
| | [Kubernetes CRDs API Version `traefik.io/v1alpha1`](#kubernetes-crds-api-version-traefikiov1alpha1)                  | N/A        | N/A            | 3.0     | | ||||
| | [Kubernetes Ingress API Version `networking.k8s.io/v1beta1`](#kubernetes-ingress-api-version-networkingk8siov1beta1) | N/A        | N/A            | 3.0     | | ||||
| | [CRD API Version `apiextensions.k8s.io/v1beta1`](#kubernetes-ingress-api-version-networkingk8siov1beta1)             | N/A        | N/A            | 3.0     | | ||||
|  | ||||
| ## Impact | ||||
|  | ||||
| ### Pilot | ||||
|  | ||||
| Metrics will continue to function normally up to 2.8, when they will be disabled.   | ||||
| In 2.9, the Pilot platform and all Traefik integration code will be permanently removed. | ||||
|  | ||||
| Starting on 2.7 the pilot token will not be a requirement anymore for plugins.   | ||||
| Since 2.8, a [new plugin catalog](https://plugins.traefik.io) is available, decoupled from Pilot. | ||||
|  | ||||
| ### Consul Enterprise Namespace | ||||
|  | ||||
| Starting on 2.8 the `namespace` option of Consul and Consul Catalog providers is deprecated,  | ||||
| please use the `namespaces` options instead.   | ||||
|  | ||||
| ### TLS 1.0 and 1.1 | ||||
|  | ||||
| Starting on 2.8 the default TLS options will use the minimum version of TLS 1.2. Of course, it can still be overridden with custom configuration.   | ||||
|  | ||||
| ### Nomad Namespace | ||||
|  | ||||
| Starting on 2.10 the `namespace` option of the Nomad provider is deprecated, | ||||
| please use the `namespaces` options instead. | ||||
|  | ||||
| ### Kubernetes CRDs API Group `traefik.containo.us` | ||||
|  | ||||
| In v2.10, the Kubernetes CRDs API Group `traefik.containo.us` is deprecated, and its support will end starting with Traefik v3. Please use the API Group `traefik.io` instead. | ||||
|  | ||||
| ### Kubernetes CRDs API Version `traefik.io/v1alpha1` | ||||
|  | ||||
| The newly introduced Kubernetes CRD API Version `traefik.io/v1alpha1` will subsequently be removed in Traefik v3. The following version will be `traefik.io/v1`. | ||||
|  | ||||
| ### Kubernetes Ingress API Version `networking.k8s.io/v1beta1` | ||||
|  | ||||
| The Kubernetes Ingress API Version `networking.k8s.io/v1beta1` is removed in v3. Please use the API Group `networking.k8s.io/v1` instead. | ||||
|  | ||||
| ### Traefik CRD API Version `apiextensions.k8s.io/v1beta1` | ||||
|  | ||||
| The Traefik CRD API Version `apiextensions.k8s.io/v1beta1` is removed in v3. Please use the API Group `apiextensions.k8s.io/v1` instead. | ||||
|   | ||||
| @@ -6,7 +6,8 @@ Below is a non-exhaustive list of versions and their maintenance status: | ||||
|  | ||||
| | Version | Release Date | Active Support     | Security Support |  | ||||
| |---------|--------------|--------------------|------------------| | ||||
| | 2.9     | Oct 03, 2022 | Yes                | Yes              | | ||||
| | 2.10    | Apr 24, 2023 | Yes                | Yes              | | ||||
| | 2.9     | Oct 03, 2022 | Ended Apr 24, 2023 | No               | | ||||
| | 2.8     | Jun 29, 2022 | Ended Oct 03, 2022 | No               | | ||||
| | 2.7     | May 24, 2022 | Ended Jun 29, 2022 | No               | | ||||
| | 2.6     | Jan 24, 2022 | Ended May 24, 2022 | No               | | ||||
|   | ||||
| @@ -11,7 +11,7 @@ This page explains the base concepts of Traefik. | ||||
|  | ||||
| ## Introduction | ||||
|  | ||||
| Traefik is based on the concept of EntryPoints, Routers, Middelwares and Services. | ||||
| Traefik is based on the concept of EntryPoints, Routers, Middlewares and Services. | ||||
|  | ||||
| The main features include dynamic configuration, automatic service discovery, and support for multiple backends and protocols. | ||||
|  | ||||
|   | ||||
| @@ -79,7 +79,7 @@ traefik --help | ||||
| # or | ||||
|  | ||||
| docker run traefik[:version] --help | ||||
| # ex: docker run traefik:v2.10 --help | ||||
| # ex: docker run traefik:v3.0 --help | ||||
| ``` | ||||
|  | ||||
| All available arguments can also be found [here](../reference/static-configuration/cli.md). | ||||
|   | ||||
| @@ -158,6 +158,56 @@ By default, the following headers are automatically added when proxying requests | ||||
| For more details, | ||||
| please check out the [forwarded header](../routing/entrypoints.md#forwarded-headers) documentation. | ||||
|  | ||||
| ## How Traefik is Storing and Serving TLS Certificates? | ||||
|  | ||||
| ### Storing TLS Certificates | ||||
|  | ||||
| [TLS](../https/tls.md "Link to Traefik TLS docs") certificates are either provided directly by the [dynamic configuration](./configuration-overview.md#the-dynamic-configuration "Link to dynamic configuration overview") from [providers](../https/tls.md#user-defined "Link to the TLS configuration"), | ||||
| or by [ACME resolvers](../https/acme.md#providers "Link to ACME resolvers"), which act themselves as providers internally. | ||||
|  | ||||
| For each TLS certificate, Traefik produces an identifier used as a key to store it. | ||||
| This identifier is constructed as the alphabetically ordered concatenation of the SANs `DNSNames` and `IPAddresses` of the TLScertificate. | ||||
|  | ||||
| #### Examples: | ||||
|  | ||||
| | X509v3 Subject Alternative Name         | TLS Certificate Identifier  | | ||||
| |-----------------------------------------|-----------------------------| | ||||
| | `DNS:example.com, IP Address:127.0.0.1` | `127.0.0.1,example.com`     | | ||||
| | `DNS:example.com, DNS:*.example.com`    | `*.example.com,example.com` | | ||||
|  | ||||
| The identifier is used to store TLS certificates in order to be later used to handle TLS connections. | ||||
| This operation happens each time there are configuration changes. | ||||
|  | ||||
| If multiple TLS certificates are provided with the same SANs definition (same identifier), only the one processed first is kept. | ||||
| Because the dynamic configuration is aggregated from all providers, | ||||
| when processing it to gather TLS certificates, | ||||
| there is no guarantee of the order in which they would be processed. | ||||
| This means that along with configurations applied, it is possible that the TLS certificate retained for a given identifier differs. | ||||
|  | ||||
| ### Serving TLS Certificates | ||||
|  | ||||
| For each incoming connection, Traefik is serving the "best" matching TLS certificate for the provided server name. | ||||
|  | ||||
| The TLS certificate selection process narrows down the list of TLS certificates matching the server name, | ||||
| and then selects the last TLS certificate in this list after having ordered it by the identifier alphabetically. | ||||
|  | ||||
| #### Examples: | ||||
|  | ||||
| | Selected TLS Certificates Identifiers               | Sorted TLS Certificates Identifiers                 | Served Certificate Identifier | | ||||
| |-----------------------------------------------------|-----------------------------------------------------|-------------------------------| | ||||
| | `127.0.0.1,example.com`,`*.example.com,example.com` | `*.example.com,example.com`,`127.0.0.1,example.com` | `127.0.0.1,example.com`       | | ||||
| | `*.example.com,example.com`,`example.com`           | `*.example.com,example.com`,`example.com`           | `example.com`                 | | ||||
|  | ||||
| ### Caching TLS Certificates | ||||
|  | ||||
| While Traefik is serving the best matching TLS certificate for each incoming connection, | ||||
| the selection process cost for each incoming connection is avoided thanks to a cache mechanism. | ||||
|  | ||||
| Once a TLS certificate has been selected as the "best" TLS certificate for a server name, | ||||
| it is cached for an hour, avoiding the selection process for further connections. | ||||
|  | ||||
| Nonetheless, when a new configuration is applied, the cache is reset. | ||||
|  | ||||
| ## What does the "field not found" error mean? | ||||
|  | ||||
| ```shell | ||||
|   | ||||
| @@ -16,12 +16,12 @@ You can install Traefik with the following flavors: | ||||
|  | ||||
| Choose one of the [official Docker images](https://hub.docker.com/_/traefik) and run it with one sample configuration file: | ||||
|  | ||||
| * [YAML](https://raw.githubusercontent.com/traefik/traefik/v2.10/traefik.sample.yml) | ||||
| * [TOML](https://raw.githubusercontent.com/traefik/traefik/v2.10/traefik.sample.toml) | ||||
| * [YAML](https://raw.githubusercontent.com/traefik/traefik/v3.0/traefik.sample.yml) | ||||
| * [TOML](https://raw.githubusercontent.com/traefik/traefik/v3.0/traefik.sample.toml) | ||||
|  | ||||
| ```bash | ||||
| docker run -d -p 8080:8080 -p 80:80 \ | ||||
|     -v $PWD/traefik.yml:/etc/traefik/traefik.yml traefik:v2.10 | ||||
|     -v $PWD/traefik.yml:/etc/traefik/traefik.yml traefik:v3.0 | ||||
| ``` | ||||
|  | ||||
| For more details, go to the [Docker provider documentation](../providers/docker.md) | ||||
| @@ -29,7 +29,7 @@ For more details, go to the [Docker provider documentation](../providers/docker. | ||||
| !!! tip | ||||
|  | ||||
|     * Prefer a fixed version than the latest that could be an unexpected version. | ||||
|     ex: `traefik:v2.10` | ||||
|     ex: `traefik:v3.0` | ||||
|     * Docker images are based from the [Alpine Linux Official image](https://hub.docker.com/_/alpine). | ||||
|     * Any orchestrator using docker images can fetch the official Traefik docker image. | ||||
|  | ||||
|   | ||||
| @@ -130,7 +130,7 @@ spec: | ||||
|       serviceAccountName: traefik-account | ||||
|       containers: | ||||
|         - name: traefik | ||||
|           image: traefik:v2.10 | ||||
|           image: traefik:v3.0 | ||||
|           args: | ||||
|             - --api.insecure | ||||
|             - --providers.kubernetesingress | ||||
| @@ -316,3 +316,5 @@ curl -v http://localhost/ | ||||
|     - [Filter the ingresses](../providers/kubernetes-ingress.md#ingressclass) to use with [IngressClass](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class) | ||||
|     - Use [IngressRoute CRD](../providers/kubernetes-crd.md) | ||||
|     - Protect [ingresses with TLS](../routing/providers/kubernetes-ingress.md#enabling-tls-via-annotations) | ||||
|      | ||||
| {!traefik-api-management-kubernetes.md!} | ||||
|   | ||||
| @@ -1,11 +1,11 @@ | ||||
| --- | ||||
| title: "Traefik Getting Started Quickly" | ||||
| description: "Looking to get started with Traefik Proxy quickly? Read the technical documentation to learn a simple use case that leverages Docker." | ||||
| description: "Looking to get started with Traefik Proxy quickly? Read the technical documentation to see a basic use case that leverages Docker." | ||||
| --- | ||||
|  | ||||
| # Quick Start | ||||
|  | ||||
| A Simple Use Case Using Docker | ||||
| A Basic Use Case Using Docker | ||||
| {: .subtitle } | ||||
|  | ||||
|  | ||||
| @@ -19,9 +19,9 @@ version: '3' | ||||
|  | ||||
| services: | ||||
|   reverse-proxy: | ||||
|     # The official v2 Traefik docker image | ||||
|     image: traefik:v2.10 | ||||
|     # Enables the web UI and tells Traefik to listen to docker | ||||
|     # The official v3 Traefik Docker image | ||||
|     image: traefik:v3.0 | ||||
|     # Enables the web UI and tells Traefik to listen to Docker | ||||
|     command: --api.insecure=true --providers.docker | ||||
|     ports: | ||||
|       # The HTTP port | ||||
| @@ -63,7 +63,7 @@ services: | ||||
|       - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)" | ||||
| ``` | ||||
|  | ||||
| The above defines `whoami`: a simple web service that outputs information about the machine it is deployed on (its IP address, host, and so on). | ||||
| The above defines [`whoami`](https://github.com/traefik/whoami "Link to whoami app on GitHub"), a web service that outputs information about the machine it is deployed on (its IP address, host, etc.). | ||||
|  | ||||
| Start the `whoami` service with the following command: | ||||
|  | ||||
| @@ -71,9 +71,9 @@ Start the `whoami` service with the following command: | ||||
| docker-compose up -d whoami | ||||
| ``` | ||||
|  | ||||
| Go back to your browser (`http://localhost:8080/api/rawdata`) and see that Traefik has automatically detected the new container and updated its own configuration. | ||||
| Browse `http://localhost:8080/api/rawdata` and see that Traefik has automatically detected the new container and updated its own configuration. | ||||
|  | ||||
| When Traefik detects new services, it creates the corresponding routes so you can call them ... _let's see!_  (Here, we're using curl) | ||||
| When Traefik detects new services, it creates the corresponding routes, so you can call them ... _let's see!_  (Here, we're using curl) | ||||
|  | ||||
| ```shell | ||||
| curl -H Host:whoami.docker.localhost http://127.0.0.1 | ||||
| @@ -95,7 +95,7 @@ Run more instances of your `whoami` service with the following command: | ||||
| docker-compose up -d --scale whoami=2 | ||||
| ``` | ||||
|  | ||||
| Go back to your browser (`http://localhost:8080/api/rawdata`) and see that Traefik has automatically detected the new instance of the container. | ||||
| Browse to `http://localhost:8080/api/rawdata` and see that Traefik has automatically detected the new instance of the container. | ||||
|  | ||||
| Finally, see that Traefik load-balances between the two instances of your service by running the following command twice: | ||||
|  | ||||
| @@ -119,6 +119,6 @@ IP: 172.27.0.4 | ||||
|  | ||||
| !!! question "Where to Go Next?" | ||||
|  | ||||
|     Now that you have a basic understanding of how Traefik can automatically create the routes to your services and load balance them, it is time to dive into [the documentation](/) and let Traefik work for you! | ||||
|     Now that you have a basic understanding of how Traefik can automatically create the routes to your services and load balance them, it is time to dive into [the documentation](/ "Link to the docs landing page") and let Traefik work for you! | ||||
|  | ||||
| {!traefik-for-business-applications.md!} | ||||
|   | ||||
| @@ -308,121 +308,127 @@ For example, `CF_API_EMAIL_FILE=/run/secrets/traefik_cf-api-email` could be used | ||||
|  | ||||
| For complete details, refer to your provider's _Additional configuration_ link. | ||||
|  | ||||
| | Provider Name                                                            | Provider Code      | Environment Variables                                                                                                                       |                                                                                 | | ||||
| |--------------------------------------------------------------------------|--------------------|---------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------| | ||||
| | [ACME DNS](https://github.com/joohoi/acme-dns)                           | `acme-dns`         | `ACME_DNS_API_BASE`, `ACME_DNS_STORAGE_PATH`                                                                                                | [Additional configuration](https://go-acme.github.io/lego/dns/acme-dns)         | | ||||
| | [Alibaba Cloud](https://www.alibabacloud.com)                            | `alidns`           | `ALICLOUD_ACCESS_KEY`, `ALICLOUD_SECRET_KEY`, `ALICLOUD_REGION_ID`                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/alidns)           | | ||||
| | [all-inkl](https://all-inkl.com)                                         | `allinkl`          | `ALL_INKL_LOGIN`, `ALL_INKL_PASSWORD`                                                                                                       | [Additional configuration](https://go-acme.github.io/lego/dns/allinkl)          | | ||||
| | [ArvanCloud](https://www.arvancloud.com/en)                              | `arvancloud`       | `ARVANCLOUD_API_KEY`                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/arvancloud)       | | ||||
| | [Auroradns](https://www.pcextreme.com/dns-health-checks)                 | `auroradns`        | `AURORA_USER_ID`, `AURORA_KEY`, `AURORA_ENDPOINT`                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/auroradns)        | | ||||
| | [Autodns](https://www.internetx.com/domains/autodns/)                    | `autodns`          | `AUTODNS_API_USER`, `AUTODNS_API_PASSWORD`                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/autodns)          | | ||||
| | [Azure](https://azure.microsoft.com/services/dns/)                       | `azure`            | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRIPTION_ID`, `AZURE_TENANT_ID`, `AZURE_RESOURCE_GROUP`, `[AZURE_METADATA_ENDPOINT]`   | [Additional configuration](https://go-acme.github.io/lego/dns/azure)            | | ||||
| | [Bindman](https://github.com/labbsr0x/bindman-dns-webhook)               | `bindman`          | `BINDMAN_MANAGER_ADDRESS`                                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/bindman)          | | ||||
| | [Blue Cat](https://www.bluecatnetworks.com/)                             | `bluecat`          | `BLUECAT_SERVER_URL`, `BLUECAT_USER_NAME`, `BLUECAT_PASSWORD`, `BLUECAT_CONFIG_NAME`, `BLUECAT_DNS_VIEW`                                    | [Additional configuration](https://go-acme.github.io/lego/dns/bluecat)          | | ||||
| | [Checkdomain](https://www.checkdomain.de/)                               | `checkdomain`      | `CHECKDOMAIN_TOKEN`,                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/checkdomain/)     | | ||||
| | [Civo](https://www.civo.com/)                                            | `civo`             | `CIVO_TOKEN`                                                                                                                                | [Additional configuration](https://go-acme.github.io/lego/dns/civo)             | | ||||
| | [CloudDNS](https://vshosting.eu/)                                        | `clouddns`         | `CLOUDDNS_CLIENT_ID`, `CLOUDDNS_EMAIL`, `CLOUDDNS_PASSWORD`                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/clouddns)         | | ||||
| | [Cloudflare](https://www.cloudflare.com)                                 | `cloudflare`       | `CF_API_EMAIL`, `CF_API_KEY` [^5] or `CF_DNS_API_TOKEN`, `[CF_ZONE_API_TOKEN]`                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/cloudflare)       | | ||||
| | [ClouDNS](https://www.cloudns.net/)                                      | `cloudns`          | `CLOUDNS_AUTH_ID`, `CLOUDNS_AUTH_PASSWORD`                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/cloudns)          | | ||||
| | [CloudXNS](https://www.cloudxns.net)                                     | `cloudxns`         | `CLOUDXNS_API_KEY`, `CLOUDXNS_SECRET_KEY`                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/cloudxns)         | | ||||
| | [ConoHa](https://www.conoha.jp)                                          | `conoha`           | `CONOHA_TENANT_ID`, `CONOHA_API_USERNAME`, `CONOHA_API_PASSWORD`                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/conoha)           | | ||||
| | [Constellix](https://constellix.com)                                     | `constellix`       | `CONSTELLIX_API_KEY`, `CONSTELLIX_SECRET_KEY`                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/constellix)       | | ||||
| | [deSEC](https://desec.io)                                                | `desec`            | `DESEC_TOKEN`                                                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/desec)            | | ||||
| | [DigitalOcean](https://www.digitalocean.com)                             | `digitalocean`     | `DO_AUTH_TOKEN`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/digitalocean)     | | ||||
| | [DNS Made Easy](https://dnsmadeeasy.com)                                 | `dnsmadeeasy`      | `DNSMADEEASY_API_KEY`, `DNSMADEEASY_API_SECRET`, `DNSMADEEASY_SANDBOX`                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/dnsmadeeasy)      | | ||||
| | [dnsHome.de](https://www.dnshome.de)                                     | `dnsHomede`        | `DNSHOMEDE_CREDENTIALS`                                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/dnshomede)        | | ||||
| | [DNSimple](https://dnsimple.com)                                         | `dnsimple`         | `DNSIMPLE_OAUTH_TOKEN`, `DNSIMPLE_BASE_URL`                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/dnsimple)         | | ||||
| | [DNSPod](https://www.dnspod.com/)                                        | `dnspod`           | `DNSPOD_API_KEY`                                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/dnspod)           | | ||||
| | [Domain Offensive (do.de)](https://www.do.de/)                           | `dode`             | `DODE_TOKEN`                                                                                                                                | [Additional configuration](https://go-acme.github.io/lego/dns/dode)             | | ||||
| | [Domeneshop](https://domene.shop)                                        | `domeneshop`       | `DOMENESHOP_API_TOKEN`, `DOMENESHOP_API_SECRET`                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/domeneshop)       | | ||||
| | [DreamHost](https://www.dreamhost.com/)                                  | `dreamhost`        | `DREAMHOST_API_KEY`                                                                                                                         | [Additional configuration](https://go-acme.github.io/lego/dns/dreamhost)        | | ||||
| | [Duck DNS](https://www.duckdns.org/)                                     | `duckdns`          | `DUCKDNS_TOKEN`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/duckdns)          | | ||||
| | [Dyn](https://dyn.com)                                                   | `dyn`              | `DYN_CUSTOMER_NAME`, `DYN_USER_NAME`, `DYN_PASSWORD`                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/dyn)              | | ||||
| | [Dynu](https://www.dynu.com)                                             | `dynu`             | `DYNU_API_KEY`                                                                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/dynu)             | | ||||
| | [EasyDNS](https://easydns.com/)                                          | `easydns`          | `EASYDNS_TOKEN`, `EASYDNS_KEY`                                                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/easydns)          | | ||||
| | [EdgeDNS](https://www.akamai.com/)                                       | `edgedns`          | `AKAMAI_CLIENT_TOKEN`,  `AKAMAI_CLIENT_SECRET`,  `AKAMAI_ACCESS_TOKEN`                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/edgedns)          | | ||||
| | [Epik](https://www.epik.com)                                             | `epik`             | `EPIK_SIGNATURE`                                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/epik)             | | ||||
| | [Exoscale](https://www.exoscale.com)                                     | `exoscale`         | `EXOSCALE_API_KEY`, `EXOSCALE_API_SECRET`, `EXOSCALE_ENDPOINT`                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/exoscale)         | | ||||
| | [Fast DNS](https://www.akamai.com/)                                      | `fastdns`          | `AKAMAI_CLIENT_TOKEN`,  `AKAMAI_CLIENT_SECRET`,  `AKAMAI_ACCESS_TOKEN`                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/edgedns)          | | ||||
| | [Freemyip.com](https://freemyip.com)                                     | `freemyip`         | `FREEMYIP_TOKEN`                                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/freemyip)         | | ||||
| | [G-Core Lab](https://gcorelabs.com/dns/)                                 | `gcore`            | `GCORE_PERMANENT_API_TOKEN`                                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/gcore)            | | ||||
| | [Gandi v5](https://doc.livedns.gandi.net)                                | `gandiv5`          | `GANDIV5_API_KEY`                                                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/gandiv5)          | | ||||
| | [Gandi](https://www.gandi.net)                                           | `gandi`            | `GANDI_API_KEY`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/gandi)            | | ||||
| | [Glesys](https://glesys.com/)                                            | `glesys`           | `GLESYS_API_USER`, `GLESYS_API_KEY`, `GLESYS_DOMAIN`                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/glesys)           | | ||||
| | [GoDaddy](https://www.godaddy.com)                                       | `godaddy`          | `GODADDY_API_KEY`, `GODADDY_API_SECRET`                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/godaddy)          | | ||||
| | [Google Cloud DNS](https://cloud.google.com/dns/docs/)                   | `gcloud`           | `GCE_PROJECT`, Application Default Credentials [^2] [^3], [`GCE_SERVICE_ACCOUNT_FILE`]                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/gcloud)           | | ||||
| | [Hetzner](https://hetzner.com)                                           | `hetzner`          | `HETZNER_API_KEY`                                                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/hetzner)          | | ||||
| | [hosting.de](https://www.hosting.de)                                     | `hostingde`        | `HOSTINGDE_API_KEY`, `HOSTINGDE_ZONE_NAME`                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/hostingde)        | | ||||
| | [Hosttech](https://www.hosttech.eu)                                      | `hosttech`         | `HOSTTECH_API_KEY`                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/hosttech)         | | ||||
| | [Hurricane Electric](https://dns.he.net)                                 | `hurricane`        | `HURRICANE_TOKENS` [^6]                                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/hurricane)        | | ||||
| | [HyperOne](https://www.hyperone.com)                                     | `hyperone`         | `HYPERONE_PASSPORT_LOCATION`, `HYPERONE_LOCATION_ID`                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/hyperone)         | | ||||
| | [IBM Cloud (SoftLayer)](https://www.ibm.com/cloud/)                      | `ibmcloud`         | `SOFTLAYER_USERNAME`, `SOFTLAYER_API_KEY`                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/ibmcloud)         | | ||||
| | [IIJ DNS Platform Service](https://www.iij.ad.jp)                        | `iijdpf`           | `IIJ_DPF_API_TOKEN` , `IIJ_DPF_DPM_SERVICE_CODE`                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/iijdpf)           | | ||||
| | [IIJ](https://www.iij.ad.jp/)                                            | `iij`              | `IIJ_API_ACCESS_KEY`, `IIJ_API_SECRET_KEY`, `IIJ_DO_SERVICE_CODE`                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/iij)              | | ||||
| | [Infoblox](https://www.infoblox.com/)                                    | `infoblox`         | `INFOBLOX_USERNAME`, `INFOBLOX_PASSWORD`, `INFOBLOX_HOST`                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/infoblox)         | | ||||
| | [Infomaniak](https://www.infomaniak.com)                                 | `infomaniak`       | `INFOMANIAK_ACCESS_TOKEN`                                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/infomaniak)       | | ||||
| | [Internet.bs](https://internetbs.net)                                    | `internetbs`       | `INTERNET_BS_API_KEY`, `INTERNET_BS_PASSWORD`                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/internetbs)       | | ||||
| | [INWX](https://www.inwx.de/en)                                           | `inwx`             | `INWX_USERNAME`, `INWX_PASSWORD`                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/inwx)             | | ||||
| | [ionos](https://ionos.com/)                                              | `ionos`            | `IONOS_API_KEY`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/ionos)            | | ||||
| | [iwantmyname](https://iwantmyname.com)                                   | `iwantmyname`      | `IWANTMYNAME_USERNAME` , `IWANTMYNAME_PASSWORD`                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/iwantmyname)      | | ||||
| | [Joker.com](https://joker.com)                                           | `joker`            | `JOKER_API_MODE` with `JOKER_API_KEY` or `JOKER_USERNAME`, `JOKER_PASSWORD`                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/joker)            | | ||||
| | [Liara](https://liara.ir)                                                | `liara`            | `LIARA_API_KEY`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/liara)            | | ||||
| | [Lightsail](https://aws.amazon.com/lightsail/)                           | `lightsail`        | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `DNS_ZONE`                                                                                    | [Additional configuration](https://go-acme.github.io/lego/dns/lightsail)        | | ||||
| | [Linode v4](https://www.linode.com)                                      | `linode`           | `LINODE_TOKEN`                                                                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/linode)           | | ||||
| | [Liquid Web](https://www.liquidweb.com/)                                 | `liquidweb`        | `LIQUID_WEB_PASSWORD`, `LIQUID_WEB_USERNAME`, `LIQUID_WEB_ZONE`                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/liquidweb)        | | ||||
| | [Loopia](https://loopia.com/)                                            | `loopia`           | `LOOPIA_API_PASSWORD`, `LOOPIA_API_USER`                                                                                                    | [Additional configuration](https://go-acme.github.io/lego/dns/loopia)           | | ||||
| | [LuaDNS](https://luadns.com)                                             | `luadns`           | `LUADNS_API_USERNAME`, `LUADNS_API_TOKEN`                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/luadns)           | | ||||
| | [MyDNS.jp](https://www.mydns.jp/)                                        | `mydnsjp`          | `MYDNSJP_MASTER_ID`, `MYDNSJP_PASSWORD`                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/mydnsjp)          | | ||||
| | [Mythic Beasts](https://www.mythic-beasts.com)                           | `mythicbeasts`     | `MYTHICBEASTS_USER_NAME`, `MYTHICBEASTS_PASSWORD`                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/mythicbeasts)     | | ||||
| | [name.com](https://www.name.com/)                                        | `namedotcom`       | `NAMECOM_USERNAME`, `NAMECOM_API_TOKEN`, `NAMECOM_SERVER`                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/namedotcom)       | | ||||
| | [Namecheap](https://www.namecheap.com)                                   | `namecheap`        | `NAMECHEAP_API_USER`, `NAMECHEAP_API_KEY`                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/namecheap)        | | ||||
| | [Namesilo](https://www.namesilo.com/)                                    | `namesilo`         | `NAMESILO_API_KEY`                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/namesilo)         | | ||||
| | [NearlyFreeSpeech.NET](https://www.nearlyfreespeech.net/)                | `nearlyfreespeech` | `NEARLYFREESPEECH_API_KEY`, `NEARLYFREESPEECH_LOGIN`                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/nearlyfreespeech) | | ||||
| | [Netcup](https://www.netcup.eu/)                                         | `netcup`           | `NETCUP_CUSTOMER_NUMBER`, `NETCUP_API_KEY`, `NETCUP_API_PASSWORD`                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/netcup)           | | ||||
| | [Netlify](https://www.netlify.com)                                       | `netlify`          | `NETLIFY_TOKEN`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/netlify)          | | ||||
| | [Nicmanager](https://www.nicmanager.com)                                 | `nicmanager`       | `NICMANAGER_API_EMAIL`, `NICMANAGER_API_PASSWORD`                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/nicmanager)       | | ||||
| | [NIFCloud](https://cloud.nifty.com/service/dns.htm)                      | `nifcloud`         | `NIFCLOUD_ACCESS_KEY_ID`, `NIFCLOUD_SECRET_ACCESS_KEY`                                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/nifcloud)         | | ||||
| | [Njalla](https://njal.la)                                                | `njalla`           | `NJALLA_TOKEN`                                                                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/njalla)           | | ||||
| | [NS1](https://ns1.com/)                                                  | `ns1`              | `NS1_API_KEY`                                                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/ns1)              | | ||||
| | [Open Telekom Cloud](https://cloud.telekom.de)                           | `otc`              | `OTC_DOMAIN_NAME`, `OTC_USER_NAME`, `OTC_PASSWORD`, `OTC_PROJECT_NAME`, `OTC_IDENTITY_ENDPOINT`                                             | [Additional configuration](https://go-acme.github.io/lego/dns/otc)              | | ||||
| | [Openstack Designate](https://docs.openstack.org/designate)              | `designate`        | `OS_AUTH_URL`, `OS_USERNAME`, `OS_PASSWORD`, `OS_TENANT_NAME`, `OS_REGION_NAME`                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/designate)        | | ||||
| | [Oracle Cloud](https://cloud.oracle.com/home)                            | `oraclecloud`      | `OCI_COMPARTMENT_OCID`, `OCI_PRIVKEY_FILE`, `OCI_PRIVKEY_PASS`, `OCI_PUBKEY_FINGERPRINT`, `OCI_REGION`, `OCI_TENANCY_OCID`, `OCI_USER_OCID` | [Additional configuration](https://go-acme.github.io/lego/dns/oraclecloud)      | | ||||
| | [OVH](https://www.ovh.com)                                               | `ovh`              | `OVH_ENDPOINT`, `OVH_APPLICATION_KEY`, `OVH_APPLICATION_SECRET`, `OVH_CONSUMER_KEY`                                                         | [Additional configuration](https://go-acme.github.io/lego/dns/ovh)              | | ||||
| | [Porkbun](https://porkbun.com/)                                          | `porkbun`          | `PORKBUN_SECRET_API_KEY`, `PORKBUN_API_KEY`                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/porkbun)          | | ||||
| | [PowerDNS](https://www.powerdns.com)                                     | `pdns`             | `PDNS_API_KEY`, `PDNS_API_URL`                                                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/pdns)             | | ||||
| | [Rackspace](https://www.rackspace.com/cloud/dns)                         | `rackspace`        | `RACKSPACE_USER`, `RACKSPACE_API_KEY`                                                                                                       | [Additional configuration](https://go-acme.github.io/lego/dns/rackspace)        | | ||||
| | [reg.ru](https://www.reg.ru)                                             | `regru`            | `REGRU_USERNAME`, `REGRU_PASSWORD`                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/regru)            | | ||||
| | [RFC2136](https://tools.ietf.org/html/rfc2136)                           | `rfc2136`          | `RFC2136_TSIG_KEY`, `RFC2136_TSIG_SECRET`, `RFC2136_TSIG_ALGORITHM`, `RFC2136_NAMESERVER`                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/rfc2136)          | | ||||
| | [RimuHosting](https://rimuhosting.com)                                   | `rimuhosting`      | `RIMUHOSTING_API_KEY`                                                                                                                       | [Additional configuration](https://go-acme.github.io/lego/dns/rimuhosting)      | | ||||
| | [Route 53](https://aws.amazon.com/route53/)                              | `route53`          | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `[AWS_REGION]`, `[AWS_HOSTED_ZONE_ID]` or a configured user/instance IAM profile.             | [Additional configuration](https://go-acme.github.io/lego/dns/route53)          | | ||||
| | [Sakura Cloud](https://cloud.sakura.ad.jp/)                              | `sakuracloud`      | `SAKURACLOUD_ACCESS_TOKEN`, `SAKURACLOUD_ACCESS_TOKEN_SECRET`                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/sakuracloud)      | | ||||
| | [Scaleway](https://www.scaleway.com)                                     | `scaleway`         | `SCALEWAY_API_TOKEN`                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/scaleway)         | | ||||
| | [Selectel](https://selectel.ru/en/)                                      | `selectel`         | `SELECTEL_API_TOKEN`                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/selectel)         | | ||||
| | [Servercow](https://servercow.de)                                        | `servercow`        | `SERVERCOW_USERNAME`, `SERVERCOW_PASSWORD`                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/servercow)        | | ||||
| | [Simply.com](https://www.simply.com/en/domains/)                         | `simply`           | `SIMPLY_ACCOUNT_NAME`, `SIMPLY_API_KEY`                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/simply)           | | ||||
| | [Sonic](https://www.sonic.com/)                                          | `sonic`            | `SONIC_USER_ID`, `SONIC_API_KEY`                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/sonic)            | | ||||
| | [Stackpath](https://www.stackpath.com/)                                  | `stackpath`        | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID`                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/stackpath)        | | ||||
| | [Tencent Cloud DNS](https://cloud.tencent.com/product/cns)               | `tencentcloud`     | `TENCENTCLOUD_SECRET_ID`, `TENCENTCLOUD_SECRET_KEY`                                                                                         | [Additional configuration](https://go-acme.github.io/lego/dns/tencentcloud)     | | ||||
| | [TransIP](https://www.transip.nl/)                                       | `transip`          | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH`                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/transip)          | | ||||
| | [UKFast SafeDNS](https://docs.ukfast.co.uk/domains/safedns/index.html)   | `safedns`          | `SAFEDNS_AUTH_TOKEN`                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/safedns)          | | ||||
| | [Ultradns](https://neustarsecurityservices.com/dns-services)             | `ultradns`         | `ULTRADNS_USERNAME`, `ULTRADNS_PASSWORD`                                                                                                    | [Additional configuration](https://go-acme.github.io/lego/dns/ultradns)         | | ||||
| | [Variomedia](https://www.variomedia.de/)                                 | `variomedia`       | `VARIOMEDIA_API_TOKEN`                                                                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/variomedia)       | | ||||
| | [VegaDNS](https://github.com/shupp/VegaDNS-API)                          | `vegadns`          | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL`                                                                                | [Additional configuration](https://go-acme.github.io/lego/dns/vegadns)          | | ||||
| | [Vercel](https://vercel.com)                                             | `vercel`           | `VERCEL_API_TOKEN`                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/vercel)           | | ||||
| | [Versio](https://www.versio.nl/domeinnamen)                              | `versio`           | `VERSIO_USERNAME`, `VERSIO_PASSWORD`                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/versio)           | | ||||
| | [VinylDNS](https://www.vinyldns.io)                                      | `vinyldns`         | `VINYLDNS_ACCESS_KEY`, `VINYLDNS_SECRET_KEY`, `VINYLDNS_HOST`                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/vinyldns)         | | ||||
| | [VK Cloud](https://mcs.mail.ru/)                                         | `vkcloud`          | `VK_CLOUD_PASSWORD`, `VK_CLOUD_PROJECT_ID`, `VK_CLOUD_USERNAME`                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/vkcloud)          | | ||||
| | [Vscale](https://vscale.io/)                                             | `vscale`           | `VSCALE_API_TOKEN`                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/vscale)           | | ||||
| | [VULTR](https://www.vultr.com)                                           | `vultr`            | `VULTR_API_KEY`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/vultr)            | | ||||
| | [Websupport](https://websupport.sk)                                      | `websupport`       | `WEBSUPPORT_API_KEY`, `WEBSUPPORT_SECRET`                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/websupport)       | | ||||
| | [WEDOS](https://www.wedos.com)                                           | `wedos`            | `WEDOS_USERNAME`, `WEDOS_WAPI_PASSWORD`                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/wedos)            | | ||||
| | [Yandex Cloud](https://cloud.yandex.com/en/)                             | `yandexcloud`      | `YANDEX_CLOUD_FOLDER_ID`, `YANDEX_CLOUD_IAM_TOKEN`                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/yandexcloud)      | | ||||
| | [Yandex](https://yandex.com)                                             | `yandex`           | `YANDEX_PDD_TOKEN`                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/yandex)           | | ||||
| | [Zone.ee](https://www.zone.ee)                                           | `zoneee`           | `ZONEEE_API_USER`, `ZONEEE_API_KEY`                                                                                                         | [Additional configuration](https://go-acme.github.io/lego/dns/zoneee)           | | ||||
| | [Zonomi](https://zonomi.com)                                             | `zonomi`           | `ZONOMI_API_KEY`                                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/zonomi)           | | ||||
| | External Program                                                         | `exec`             | `EXEC_PATH`                                                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/exec)             | | ||||
| | HTTP request                                                             | `httpreq`          | `HTTPREQ_ENDPOINT`, `HTTPREQ_MODE`, `HTTPREQ_USERNAME`, `HTTPREQ_PASSWORD` [^1]                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/httpreq)          | | ||||
| | manual                                                                   | `manual`           | none, but you need to run Traefik interactively [^4], turn on debug log to see instructions and press <kbd>Enter</kbd>.                     |                                                                                 | | ||||
| | Provider Name                                                          | Provider Code      | Environment Variables                                                                                                                       |                                                                                 | | ||||
| |------------------------------------------------------------------------|--------------------|---------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------| | ||||
| | [ACME DNS](https://github.com/joohoi/acme-dns)                         | `acme-dns`         | `ACME_DNS_API_BASE`, `ACME_DNS_STORAGE_PATH`                                                                                                | [Additional configuration](https://go-acme.github.io/lego/dns/acme-dns)         | | ||||
| | [Alibaba Cloud](https://www.alibabacloud.com)                          | `alidns`           | `ALICLOUD_ACCESS_KEY`, `ALICLOUD_SECRET_KEY`, `ALICLOUD_REGION_ID`                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/alidns)           | | ||||
| | [all-inkl](https://all-inkl.com)                                       | `allinkl`          | `ALL_INKL_LOGIN`, `ALL_INKL_PASSWORD`                                                                                                       | [Additional configuration](https://go-acme.github.io/lego/dns/allinkl)          | | ||||
| | [ArvanCloud](https://www.arvancloud.com/en)                            | `arvancloud`       | `ARVANCLOUD_API_KEY`                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/arvancloud)       | | ||||
| | [Auroradns](https://www.pcextreme.com/dns-health-checks)               | `auroradns`        | `AURORA_USER_ID`, `AURORA_KEY`, `AURORA_ENDPOINT`                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/auroradns)        | | ||||
| | [Autodns](https://www.internetx.com/domains/autodns/)                  | `autodns`          | `AUTODNS_API_USER`, `AUTODNS_API_PASSWORD`                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/autodns)          | | ||||
| | [Azure](https://azure.microsoft.com/services/dns/)                     | `azure`            | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRIPTION_ID`, `AZURE_TENANT_ID`, `AZURE_RESOURCE_GROUP`, `[AZURE_METADATA_ENDPOINT]`   | [Additional configuration](https://go-acme.github.io/lego/dns/azure)            | | ||||
| | [Bindman](https://github.com/labbsr0x/bindman-dns-webhook)             | `bindman`          | `BINDMAN_MANAGER_ADDRESS`                                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/bindman)          | | ||||
| | [Blue Cat](https://www.bluecatnetworks.com/)                           | `bluecat`          | `BLUECAT_SERVER_URL`, `BLUECAT_USER_NAME`, `BLUECAT_PASSWORD`, `BLUECAT_CONFIG_NAME`, `BLUECAT_DNS_VIEW`                                    | [Additional configuration](https://go-acme.github.io/lego/dns/bluecat)          | | ||||
| | [Brandit](https://www.brandit.com)                                     | `brandit`          | `BRANDIT_API_USERNAME`, `BRANDIT_API_KEY`                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/brandit)          | | ||||
| | [Bunny](https://bunny.net)                                             | `bunny`            | `BUNNY_API_KEY`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/bunny)            | | ||||
| | [Checkdomain](https://www.checkdomain.de/)                             | `checkdomain`      | `CHECKDOMAIN_TOKEN`,                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/checkdomain/)     | | ||||
| | [Civo](https://www.civo.com/)                                          | `civo`             | `CIVO_TOKEN`                                                                                                                                | [Additional configuration](https://go-acme.github.io/lego/dns/civo)             | | ||||
| | [CloudDNS](https://vshosting.eu/)                                      | `clouddns`         | `CLOUDDNS_CLIENT_ID`, `CLOUDDNS_EMAIL`, `CLOUDDNS_PASSWORD`                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/clouddns)         | | ||||
| | [Cloudflare](https://www.cloudflare.com)                               | `cloudflare`       | `CF_API_EMAIL`, `CF_API_KEY` [^5] or `CF_DNS_API_TOKEN`, `[CF_ZONE_API_TOKEN]`                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/cloudflare)       | | ||||
| | [ClouDNS](https://www.cloudns.net/)                                    | `cloudns`          | `CLOUDNS_AUTH_ID`, `CLOUDNS_AUTH_PASSWORD`                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/cloudns)          | | ||||
| | [CloudXNS](https://www.cloudxns.net)                                   | `cloudxns`         | `CLOUDXNS_API_KEY`, `CLOUDXNS_SECRET_KEY`                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/cloudxns)         | | ||||
| | [ConoHa](https://www.conoha.jp)                                        | `conoha`           | `CONOHA_TENANT_ID`, `CONOHA_API_USERNAME`, `CONOHA_API_PASSWORD`                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/conoha)           | | ||||
| | [Constellix](https://constellix.com)                                   | `constellix`       | `CONSTELLIX_API_KEY`, `CONSTELLIX_SECRET_KEY`                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/constellix)       | | ||||
| | [Derak Cloud](https://derak.cloud/)                                    | `derak`            | `DERAK_API_KEY`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/derak)            | | ||||
| | [deSEC](https://desec.io)                                              | `desec`            | `DESEC_TOKEN`                                                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/desec)            | | ||||
| | [DigitalOcean](https://www.digitalocean.com)                           | `digitalocean`     | `DO_AUTH_TOKEN`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/digitalocean)     | | ||||
| | [DNS Made Easy](https://dnsmadeeasy.com)                               | `dnsmadeeasy`      | `DNSMADEEASY_API_KEY`, `DNSMADEEASY_API_SECRET`, `DNSMADEEASY_SANDBOX`                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/dnsmadeeasy)      | | ||||
| | [dnsHome.de](https://www.dnshome.de)                                   | `dnsHomede`        | `DNSHOMEDE_CREDENTIALS`                                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/dnshomede)        | | ||||
| | [DNSimple](https://dnsimple.com)                                       | `dnsimple`         | `DNSIMPLE_OAUTH_TOKEN`, `DNSIMPLE_BASE_URL`                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/dnsimple)         | | ||||
| | [DNSPod](https://www.dnspod.com/)                                      | `dnspod`           | `DNSPOD_API_KEY`                                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/dnspod)           | | ||||
| | [Domain Offensive (do.de)](https://www.do.de/)                         | `dode`             | `DODE_TOKEN`                                                                                                                                | [Additional configuration](https://go-acme.github.io/lego/dns/dode)             | | ||||
| | [Domeneshop](https://domene.shop)                                      | `domeneshop`       | `DOMENESHOP_API_TOKEN`, `DOMENESHOP_API_SECRET`                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/domeneshop)       | | ||||
| | [DreamHost](https://www.dreamhost.com/)                                | `dreamhost`        | `DREAMHOST_API_KEY`                                                                                                                         | [Additional configuration](https://go-acme.github.io/lego/dns/dreamhost)        | | ||||
| | [Duck DNS](https://www.duckdns.org/)                                   | `duckdns`          | `DUCKDNS_TOKEN`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/duckdns)          | | ||||
| | [Dyn](https://dyn.com)                                                 | `dyn`              | `DYN_CUSTOMER_NAME`, `DYN_USER_NAME`, `DYN_PASSWORD`                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/dyn)              | | ||||
| | [Dynu](https://www.dynu.com)                                           | `dynu`             | `DYNU_API_KEY`                                                                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/dynu)             | | ||||
| | [EasyDNS](https://easydns.com/)                                        | `easydns`          | `EASYDNS_TOKEN`, `EASYDNS_KEY`                                                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/easydns)          | | ||||
| | [EdgeDNS](https://www.akamai.com/)                                     | `edgedns`          | `AKAMAI_CLIENT_TOKEN`,  `AKAMAI_CLIENT_SECRET`,  `AKAMAI_ACCESS_TOKEN`                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/edgedns)          | | ||||
| | [Epik](https://www.epik.com)                                           | `epik`             | `EPIK_SIGNATURE`                                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/epik)             | | ||||
| | [Exoscale](https://www.exoscale.com)                                   | `exoscale`         | `EXOSCALE_API_KEY`, `EXOSCALE_API_SECRET`, `EXOSCALE_ENDPOINT`                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/exoscale)         | | ||||
| | [Fast DNS](https://www.akamai.com/)                                    | `fastdns`          | `AKAMAI_CLIENT_TOKEN`,  `AKAMAI_CLIENT_SECRET`,  `AKAMAI_ACCESS_TOKEN`                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/edgedns)          | | ||||
| | [Freemyip.com](https://freemyip.com)                                   | `freemyip`         | `FREEMYIP_TOKEN`                                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/freemyip)         | | ||||
| | [G-Core Lab](https://gcorelabs.com/dns/)                               | `gcore`            | `GCORE_PERMANENT_API_TOKEN`                                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/gcore)            | | ||||
| | [Gandi v5](https://doc.livedns.gandi.net)                              | `gandiv5`          | `GANDIV5_API_KEY`                                                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/gandiv5)          | | ||||
| | [Gandi](https://www.gandi.net)                                         | `gandi`            | `GANDI_API_KEY`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/gandi)            | | ||||
| | [Glesys](https://glesys.com/)                                          | `glesys`           | `GLESYS_API_USER`, `GLESYS_API_KEY`, `GLESYS_DOMAIN`                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/glesys)           | | ||||
| | [GoDaddy](https://www.godaddy.com)                                     | `godaddy`          | `GODADDY_API_KEY`, `GODADDY_API_SECRET`                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/godaddy)          | | ||||
| | [Google Domains](https://domains.google)                               | `googledomains`    | `GOOGLE_DOMAINS_ACCESS_TOKEN`                                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/googledomains)    | | ||||
| | [Google Cloud DNS](https://cloud.google.com/dns/docs/)                 | `gcloud`           | `GCE_PROJECT`, Application Default Credentials [^2] [^3], [`GCE_SERVICE_ACCOUNT_FILE`]                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/gcloud)           | | ||||
| | [Hetzner](https://hetzner.com)                                         | `hetzner`          | `HETZNER_API_KEY`                                                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/hetzner)          | | ||||
| | [hosting.de](https://www.hosting.de)                                   | `hostingde`        | `HOSTINGDE_API_KEY`, `HOSTINGDE_ZONE_NAME`                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/hostingde)        | | ||||
| | [Hosttech](https://www.hosttech.eu)                                    | `hosttech`         | `HOSTTECH_API_KEY`                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/hosttech)         | | ||||
| | [Hurricane Electric](https://dns.he.net)                               | `hurricane`        | `HURRICANE_TOKENS` [^6]                                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/hurricane)        | | ||||
| | [HyperOne](https://www.hyperone.com)                                   | `hyperone`         | `HYPERONE_PASSPORT_LOCATION`, `HYPERONE_LOCATION_ID`                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/hyperone)         | | ||||
| | [IBM Cloud (SoftLayer)](https://www.ibm.com/cloud/)                    | `ibmcloud`         | `SOFTLAYER_USERNAME`, `SOFTLAYER_API_KEY`                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/ibmcloud)         | | ||||
| | [IIJ DNS Platform Service](https://www.iij.ad.jp)                      | `iijdpf`           | `IIJ_DPF_API_TOKEN` , `IIJ_DPF_DPM_SERVICE_CODE`                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/iijdpf)           | | ||||
| | [IIJ](https://www.iij.ad.jp/)                                          | `iij`              | `IIJ_API_ACCESS_KEY`, `IIJ_API_SECRET_KEY`, `IIJ_DO_SERVICE_CODE`                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/iij)              | | ||||
| | [Infoblox](https://www.infoblox.com/)                                  | `infoblox`         | `INFOBLOX_USERNAME`, `INFOBLOX_PASSWORD`, `INFOBLOX_HOST`                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/infoblox)         | | ||||
| | [Infomaniak](https://www.infomaniak.com)                               | `infomaniak`       | `INFOMANIAK_ACCESS_TOKEN`                                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/infomaniak)       | | ||||
| | [Internet.bs](https://internetbs.net)                                  | `internetbs`       | `INTERNET_BS_API_KEY`, `INTERNET_BS_PASSWORD`                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/internetbs)       | | ||||
| | [INWX](https://www.inwx.de/en)                                         | `inwx`             | `INWX_USERNAME`, `INWX_PASSWORD`                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/inwx)             | | ||||
| | [ionos](https://ionos.com/)                                            | `ionos`            | `IONOS_API_KEY`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/ionos)            | | ||||
| | [iwantmyname](https://iwantmyname.com)                                 | `iwantmyname`      | `IWANTMYNAME_USERNAME` , `IWANTMYNAME_PASSWORD`                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/iwantmyname)      | | ||||
| | [Joker.com](https://joker.com)                                         | `joker`            | `JOKER_API_MODE` with `JOKER_API_KEY` or `JOKER_USERNAME`, `JOKER_PASSWORD`                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/joker)            | | ||||
| | [Liara](https://liara.ir)                                              | `liara`            | `LIARA_API_KEY`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/liara)            | | ||||
| | [Lightsail](https://aws.amazon.com/lightsail/)                         | `lightsail`        | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `DNS_ZONE`                                                                                    | [Additional configuration](https://go-acme.github.io/lego/dns/lightsail)        | | ||||
| | [Linode v4](https://www.linode.com)                                    | `linode`           | `LINODE_TOKEN`                                                                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/linode)           | | ||||
| | [Liquid Web](https://www.liquidweb.com/)                               | `liquidweb`        | `LIQUID_WEB_PASSWORD`, `LIQUID_WEB_USERNAME`, `LIQUID_WEB_ZONE`                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/liquidweb)        | | ||||
| | [Loopia](https://loopia.com/)                                          | `loopia`           | `LOOPIA_API_PASSWORD`, `LOOPIA_API_USER`                                                                                                    | [Additional configuration](https://go-acme.github.io/lego/dns/loopia)           | | ||||
| | [LuaDNS](https://luadns.com)                                           | `luadns`           | `LUADNS_API_USERNAME`, `LUADNS_API_TOKEN`                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/luadns)           | | ||||
| | [MyDNS.jp](https://www.mydns.jp/)                                      | `mydnsjp`          | `MYDNSJP_MASTER_ID`, `MYDNSJP_PASSWORD`                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/mydnsjp)          | | ||||
| | [Mythic Beasts](https://www.mythic-beasts.com)                         | `mythicbeasts`     | `MYTHICBEASTS_USER_NAME`, `MYTHICBEASTS_PASSWORD`                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/mythicbeasts)     | | ||||
| | [name.com](https://www.name.com/)                                      | `namedotcom`       | `NAMECOM_USERNAME`, `NAMECOM_API_TOKEN`, `NAMECOM_SERVER`                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/namedotcom)       | | ||||
| | [Namecheap](https://www.namecheap.com)                                 | `namecheap`        | `NAMECHEAP_API_USER`, `NAMECHEAP_API_KEY`                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/namecheap)        | | ||||
| | [Namesilo](https://www.namesilo.com/)                                  | `namesilo`         | `NAMESILO_API_KEY`                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/namesilo)         | | ||||
| | [NearlyFreeSpeech.NET](https://www.nearlyfreespeech.net/)              | `nearlyfreespeech` | `NEARLYFREESPEECH_API_KEY`, `NEARLYFREESPEECH_LOGIN`                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/nearlyfreespeech) | | ||||
| | [Netcup](https://www.netcup.eu/)                                       | `netcup`           | `NETCUP_CUSTOMER_NUMBER`, `NETCUP_API_KEY`, `NETCUP_API_PASSWORD`                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/netcup)           | | ||||
| | [Netlify](https://www.netlify.com)                                     | `netlify`          | `NETLIFY_TOKEN`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/netlify)          | | ||||
| | [Nicmanager](https://www.nicmanager.com)                               | `nicmanager`       | `NICMANAGER_API_EMAIL`, `NICMANAGER_API_PASSWORD`                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/nicmanager)       | | ||||
| | [NIFCloud](https://cloud.nifty.com/service/dns.htm)                    | `nifcloud`         | `NIFCLOUD_ACCESS_KEY_ID`, `NIFCLOUD_SECRET_ACCESS_KEY`                                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/nifcloud)         | | ||||
| | [Njalla](https://njal.la)                                              | `njalla`           | `NJALLA_TOKEN`                                                                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/njalla)           | | ||||
| | [Nodion](https://www.nodion.com)                                       | `nodion`           | `NODION_API_TOKEN`                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/nodion)           | | ||||
| | [NS1](https://ns1.com/)                                                | `ns1`              | `NS1_API_KEY`                                                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/ns1)              | | ||||
| | [Open Telekom Cloud](https://cloud.telekom.de)                         | `otc`              | `OTC_DOMAIN_NAME`, `OTC_USER_NAME`, `OTC_PASSWORD`, `OTC_PROJECT_NAME`, `OTC_IDENTITY_ENDPOINT`                                             | [Additional configuration](https://go-acme.github.io/lego/dns/otc)              | | ||||
| | [Openstack Designate](https://docs.openstack.org/designate)            | `designate`        | `OS_AUTH_URL`, `OS_USERNAME`, `OS_PASSWORD`, `OS_TENANT_NAME`, `OS_REGION_NAME`                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/designate)        | | ||||
| | [Oracle Cloud](https://cloud.oracle.com/home)                          | `oraclecloud`      | `OCI_COMPARTMENT_OCID`, `OCI_PRIVKEY_FILE`, `OCI_PRIVKEY_PASS`, `OCI_PUBKEY_FINGERPRINT`, `OCI_REGION`, `OCI_TENANCY_OCID`, `OCI_USER_OCID` | [Additional configuration](https://go-acme.github.io/lego/dns/oraclecloud)      | | ||||
| | [OVH](https://www.ovh.com)                                             | `ovh`              | `OVH_ENDPOINT`, `OVH_APPLICATION_KEY`, `OVH_APPLICATION_SECRET`, `OVH_CONSUMER_KEY`                                                         | [Additional configuration](https://go-acme.github.io/lego/dns/ovh)              | | ||||
| | [Plesk](https://www.plesk.com)                                         | `plesk`            | `PLESK_SERVER_BASE_URL`, `PLESK_USERNAME`, `PLESK_PASSWORD`                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/plesk)            | | ||||
| | [Porkbun](https://porkbun.com/)                                        | `porkbun`          | `PORKBUN_SECRET_API_KEY`, `PORKBUN_API_KEY`                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/porkbun)          | | ||||
| | [PowerDNS](https://www.powerdns.com)                                   | `pdns`             | `PDNS_API_KEY`, `PDNS_API_URL`                                                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/pdns)             | | ||||
| | [Rackspace](https://www.rackspace.com/cloud/dns)                       | `rackspace`        | `RACKSPACE_USER`, `RACKSPACE_API_KEY`                                                                                                       | [Additional configuration](https://go-acme.github.io/lego/dns/rackspace)        | | ||||
| | [reg.ru](https://www.reg.ru)                                           | `regru`            | `REGRU_USERNAME`, `REGRU_PASSWORD`                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/regru)            | | ||||
| | [RFC2136](https://tools.ietf.org/html/rfc2136)                         | `rfc2136`          | `RFC2136_TSIG_KEY`, `RFC2136_TSIG_SECRET`, `RFC2136_TSIG_ALGORITHM`, `RFC2136_NAMESERVER`                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/rfc2136)          | | ||||
| | [RimuHosting](https://rimuhosting.com)                                 | `rimuhosting`      | `RIMUHOSTING_API_KEY`                                                                                                                       | [Additional configuration](https://go-acme.github.io/lego/dns/rimuhosting)      | | ||||
| | [Route 53](https://aws.amazon.com/route53/)                            | `route53`          | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `[AWS_REGION]`, `[AWS_HOSTED_ZONE_ID]` or a configured user/instance IAM profile.             | [Additional configuration](https://go-acme.github.io/lego/dns/route53)          | | ||||
| | [Sakura Cloud](https://cloud.sakura.ad.jp/)                            | `sakuracloud`      | `SAKURACLOUD_ACCESS_TOKEN`, `SAKURACLOUD_ACCESS_TOKEN_SECRET`                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/sakuracloud)      | | ||||
| | [Scaleway](https://www.scaleway.com)                                   | `scaleway`         | `SCALEWAY_API_TOKEN`                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/scaleway)         | | ||||
| | [Selectel](https://selectel.ru/en/)                                    | `selectel`         | `SELECTEL_API_TOKEN`                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/selectel)         | | ||||
| | [Servercow](https://servercow.de)                                      | `servercow`        | `SERVERCOW_USERNAME`, `SERVERCOW_PASSWORD`                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/servercow)        | | ||||
| | [Simply.com](https://www.simply.com/en/domains/)                       | `simply`           | `SIMPLY_ACCOUNT_NAME`, `SIMPLY_API_KEY`                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/simply)           | | ||||
| | [Sonic](https://www.sonic.com/)                                        | `sonic`            | `SONIC_USER_ID`, `SONIC_API_KEY`                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/sonic)            | | ||||
| | [Stackpath](https://www.stackpath.com/)                                | `stackpath`        | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID`                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/stackpath)        | | ||||
| | [Tencent Cloud DNS](https://cloud.tencent.com/product/cns)             | `tencentcloud`     | `TENCENTCLOUD_SECRET_ID`, `TENCENTCLOUD_SECRET_KEY`                                                                                         | [Additional configuration](https://go-acme.github.io/lego/dns/tencentcloud)     | | ||||
| | [TransIP](https://www.transip.nl/)                                     | `transip`          | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH`                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/transip)          | | ||||
| | [UKFast SafeDNS](https://docs.ukfast.co.uk/domains/safedns/index.html) | `safedns`          | `SAFEDNS_AUTH_TOKEN`                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/safedns)          | | ||||
| | [Ultradns](https://neustarsecurityservices.com/dns-services)           | `ultradns`         | `ULTRADNS_USERNAME`, `ULTRADNS_PASSWORD`                                                                                                    | [Additional configuration](https://go-acme.github.io/lego/dns/ultradns)         | | ||||
| | [Variomedia](https://www.variomedia.de/)                               | `variomedia`       | `VARIOMEDIA_API_TOKEN`                                                                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/variomedia)       | | ||||
| | [VegaDNS](https://github.com/shupp/VegaDNS-API)                        | `vegadns`          | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL`                                                                                | [Additional configuration](https://go-acme.github.io/lego/dns/vegadns)          | | ||||
| | [Vercel](https://vercel.com)                                           | `vercel`           | `VERCEL_API_TOKEN`                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/vercel)           | | ||||
| | [Versio](https://www.versio.nl/domeinnamen)                            | `versio`           | `VERSIO_USERNAME`, `VERSIO_PASSWORD`                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/versio)           | | ||||
| | [VinylDNS](https://www.vinyldns.io)                                    | `vinyldns`         | `VINYLDNS_ACCESS_KEY`, `VINYLDNS_SECRET_KEY`, `VINYLDNS_HOST`                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/vinyldns)         | | ||||
| | [VK Cloud](https://mcs.mail.ru/)                                       | `vkcloud`          | `VK_CLOUD_PASSWORD`, `VK_CLOUD_PROJECT_ID`, `VK_CLOUD_USERNAME`                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/vkcloud)          | | ||||
| | [Vscale](https://vscale.io/)                                           | `vscale`           | `VSCALE_API_TOKEN`                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/vscale)           | | ||||
| | [VULTR](https://www.vultr.com)                                         | `vultr`            | `VULTR_API_KEY`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/vultr)            | | ||||
| | [Websupport](https://websupport.sk)                                    | `websupport`       | `WEBSUPPORT_API_KEY`, `WEBSUPPORT_SECRET`                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/websupport)       | | ||||
| | [WEDOS](https://www.wedos.com)                                         | `wedos`            | `WEDOS_USERNAME`, `WEDOS_WAPI_PASSWORD`                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/wedos)            | | ||||
| | [Yandex Cloud](https://cloud.yandex.com/en/)                           | `yandexcloud`      | `YANDEX_CLOUD_FOLDER_ID`, `YANDEX_CLOUD_IAM_TOKEN`                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/yandexcloud)      | | ||||
| | [Yandex](https://yandex.com)                                           | `yandex`           | `YANDEX_PDD_TOKEN`                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/yandex)           | | ||||
| | [Zone.ee](https://www.zone.ee)                                         | `zoneee`           | `ZONEEE_API_USER`, `ZONEEE_API_KEY`                                                                                                         | [Additional configuration](https://go-acme.github.io/lego/dns/zoneee)           | | ||||
| | [Zonomi](https://zonomi.com)                                           | `zonomi`           | `ZONOMI_API_KEY`                                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/zonomi)           | | ||||
| | External Program                                                       | `exec`             | `EXEC_PATH`                                                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/exec)             | | ||||
| | HTTP request                                                           | `httpreq`          | `HTTPREQ_ENDPOINT`, `HTTPREQ_MODE`, `HTTPREQ_USERNAME`, `HTTPREQ_PASSWORD` [^1]                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/httpreq)          | | ||||
| | manual                                                                 | `manual`           | none, but you need to run Traefik interactively [^4], turn on debug log to see instructions and press <kbd>Enter</kbd>.                     |                                                                                 | | ||||
|  | ||||
| [^1]: More information about the HTTP message format can be found [here](https://go-acme.github.io/lego/dns/httpreq/). | ||||
| [^2]: [Providing credentials to your application](https://cloud.google.com/docs/authentication/production). | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| ## Dynamic configuration | ||||
| labels: | ||||
|   - traefik.http.routers.blog.rule=Host(`example.com`) && Path(`/blog`) | ||||
| @@ -43,27 +43,6 @@ spec: | ||||
|       - '*.example.org' | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| labels: { | ||||
|   "traefik.http.routers.blog.rule": "Host(`example.com`) && Path(`/blog`)", | ||||
|   "traefik.http.routers.blog.tls": "true", | ||||
|   "traefik.http.routers.blog.tls.certresolver": "myresolver", | ||||
|   "traefik.http.routers.blog.tls.domains[0].main": "example.com", | ||||
|   "traefik.http.routers.blog.tls.domains[0].sans": "*.example.com", | ||||
|   "traefik.http.services.blog-svc.loadbalancer.server.port": "8080" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| ## Dynamic configuration | ||||
| labels: | ||||
|   - traefik.http.routers.blog.rule=Host(`example.com`) && Path(`/blog`) | ||||
|   - traefik.http.routers.blog.tls=true | ||||
|   - traefik.http.routers.blog.tls.certresolver=myresolver | ||||
|   - traefik.http.routers.blog.tls.domains[0].main=example.org | ||||
|   - traefik.http.routers.blog.tls.domains[0].sans=*.example.org | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| ## Dynamic configuration | ||||
| http: | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| ## Dynamic configuration | ||||
| labels: | ||||
|   - traefik.http.routers.blog.rule=(Host(`example.com`) && Path(`/blog`)) || Host(`blog.example.org`) | ||||
| @@ -35,23 +35,6 @@ spec: | ||||
|     certResolver: myresolver | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| labels: { | ||||
|   "traefik.http.routers.blog.rule": "(Host(`example.com`) && Path(`/blog`)) || Host(`blog.example.org`)", | ||||
|   "traefik.http.routers.blog.tls": "true", | ||||
|   "traefik.http.routers.blog.tls.certresolver": "myresolver", | ||||
|   "traefik.http.services.blog-svc.loadbalancer.server.port": "8080" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| ## Dynamic configuration | ||||
| labels: | ||||
|   - traefik.http.routers.blog.rule=(Host(`example.com`) && Path(`/blog`)) || Host(`blog.example.org`) | ||||
|   - traefik.http.routers.blog.tls=true | ||||
|   - traefik.http.routers.blog.tls.certresolver=myresolver | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| ## Dynamic configuration | ||||
| http: | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| ## Dynamic configuration | ||||
| labels: | ||||
|   - traefik.http.routers.blog.rule=Host(`example.com`) && Path(`/blog`) | ||||
| @@ -35,23 +35,6 @@ spec: | ||||
|     certResolver: myresolver | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| labels: { | ||||
|   "traefik.http.routers.blog.rule": "Host(`example.com`) && Path(`/blog`)", | ||||
|   "traefik.http.routers.blog.tls": "true", | ||||
|   "traefik.http.routers.blog.tls.certresolver": "myresolver", | ||||
|   "traefik.http.services.blog-svc.loadbalancer.server.port": "8080" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| ## Dynamic configuration | ||||
| labels: | ||||
|   - traefik.http.routers.blog.rule=Host(`example.com`) && Path(`/blog`) | ||||
|   - traefik.http.routers.blog.tls=true | ||||
|   - traefik.http.routers.blog.tls.certresolver=myresolver | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| ## Dynamic configuration | ||||
| http: | ||||
|   | ||||
							
								
								
									
										56
									
								
								docs/content/https/spiffe.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								docs/content/https/spiffe.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| --- | ||||
| title: "Traefik SPIFFE Documentation" | ||||
| description: "Learn how to configure Traefik to use SPIFFE. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # SPIFFE | ||||
|  | ||||
| Secure the backend connection with SPIFFE. | ||||
| {: .subtitle } | ||||
|  | ||||
| [SPIFFE](https://spiffe.io/docs/latest/spiffe-about/overview/) (Secure Production Identity Framework For Everyone),  | ||||
| provides a secure identity in the form of a specially crafted X.509 certificate,  | ||||
| to every workload in an environment. | ||||
|  | ||||
| Traefik is able to connect to the Workload API to obtain an x509-SVID used to secure the connection with SPIFFE enabled backends. | ||||
|  | ||||
| ## Configuration | ||||
|  | ||||
| ### General | ||||
|  | ||||
| Enabling SPIFFE is part of the [static configuration](../getting-started/configuration-overview.md#the-static-configuration). | ||||
| It can be defined by using a file (YAML or TOML) or CLI arguments. | ||||
|  | ||||
| ### Workload API | ||||
|  | ||||
| The `workloadAPIAddr` configuration defines the address of the SPIFFE [Workload API](https://spiffe.io/docs/latest/spiffe-about/spiffe-concepts/#spiffe-workload-api). | ||||
|  | ||||
| !!! info "Enabling SPIFFE in ServersTransports" | ||||
|  | ||||
|     Enabling SPIFFE does not imply that backend connections are going to use it automatically. | ||||
|     Each [ServersTransport](../routing/services/index.md#serverstransport_1) or [TCPServersTransport](../routing/services/index.md#serverstransport_2), | ||||
| 	that is meant to be secured with SPIFFE, | ||||
| 	must explicitly enable it (see [SPIFFE with ServersTransport](../routing/services/index.md#spiffe) or [SPIFFE with TCPServersTransport](../routing/services/index.md#spiffe_1)). | ||||
|  | ||||
| !!! warning "SPIFFE can cause Traefik to stall" | ||||
| 	When using SPIFFE, | ||||
| 	Traefik will wait for the first SVID to be delivered before starting. | ||||
| 	If Traefik is hanging when waiting on SPIFFE SVID delivery, | ||||
| 	please double check that it is correctly registered as workload in your SPIFFE infrastructure. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| ## Static configuration | ||||
| spiffe: | ||||
|     workloadAPIAddr: localhost | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| ## Static configuration | ||||
| [spiffe] | ||||
|     workloadAPIAddr: localhost | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| ## Static configuration | ||||
| --spiffe.workloadAPIAddr=localhost | ||||
| ``` | ||||
							
								
								
									
										207
									
								
								docs/content/https/tailscale.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								docs/content/https/tailscale.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,207 @@ | ||||
| --- | ||||
| title: "Traefik Tailscale Documentation" | ||||
| description: "Learn how to configure Traefik Proxy to resolve TLS certificates for your Tailscale services. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # Tailscale | ||||
|  | ||||
| Provision TLS certificates for your internal Tailscale services. | ||||
| {: .subtitle } | ||||
|  | ||||
| To protect a service with TLS, a certificate from a public Certificate Authority is needed. | ||||
| In addition to its vpn role, Tailscale can also [provide certificates](https://tailscale.com/kb/1153/enabling-https/) for the machines in your Tailscale network. | ||||
|  | ||||
| ## Certificate resolvers | ||||
|  | ||||
| To obtain a TLS certificate from the Tailscale daemon, | ||||
| a Tailscale certificate resolver needs to be configured as below. | ||||
|  | ||||
| !!! info "Referencing a certificate resolver" | ||||
|  | ||||
|     Defining a certificate resolver does not imply that routers are going to use it automatically. | ||||
|     Each router or entrypoint that is meant to use the resolver must explicitly [reference](../routing/routers/index.md#certresolver) it. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| certificatesResolvers: | ||||
|     myresolver: | ||||
|         tailscale: {} | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [certificatesResolvers.myresolver.tailscale] | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --certificatesresolvers.myresolver.tailscale=true | ||||
| ``` | ||||
|  | ||||
| ## Domain Definition | ||||
|  | ||||
| A certificate resolver requests certificates for a set of domain names inferred from routers, according to the following: | ||||
|  | ||||
| - If the router has a [`tls.domains`](../routing/routers/index.md#domains) option set, | ||||
|   then the certificate resolver derives this router domain name from the `main` option of `tls.domains`. | ||||
|  | ||||
| - Otherwise, the certificate resolver derives the domain name from any `Host()` or `HostSNI()` matchers | ||||
|   in the [router's rule](../routing/routers/index.md#rule). | ||||
|  | ||||
| !!! info "Tailscale Domain Format" | ||||
|  | ||||
|     The domain is only taken into account if it is a Tailscale-specific one, | ||||
|     i.e. of the form `machine-name.domains-alias.ts.net`. | ||||
|  | ||||
| ## Configuration Example | ||||
|  | ||||
| !!! example "Enabling Tailscale certificate resolution" | ||||
|  | ||||
|     ```yaml tab="File (YAML)" | ||||
|     entryPoints: | ||||
|       web: | ||||
|         address: ":80" | ||||
|  | ||||
|       websecure: | ||||
|         address: ":443" | ||||
|  | ||||
|     certificatesResolvers: | ||||
|       myresolver: | ||||
|         tailscale: {} | ||||
|     ``` | ||||
|  | ||||
|     ```toml tab="File (TOML)" | ||||
|     [entryPoints] | ||||
|       [entryPoints.web] | ||||
|         address = ":80" | ||||
|  | ||||
|       [entryPoints.websecure] | ||||
|         address = ":443" | ||||
|  | ||||
|     [certificatesResolvers.myresolver.tailscale] | ||||
|     ``` | ||||
|  | ||||
|     ```bash tab="CLI" | ||||
|     --entrypoints.web.address=:80 | ||||
|     --entrypoints.websecure.address=:443 | ||||
|     # ... | ||||
|     --certificatesresolvers.myresolver.tailscale=true | ||||
|     ``` | ||||
|  | ||||
| !!! example "Domain from Router's Rule Example" | ||||
|  | ||||
|     ```yaml tab="Docker & Swarm" | ||||
|     ## Dynamic configuration | ||||
|     labels: | ||||
|       - traefik.http.routers.blog.rule=Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`) | ||||
|       - traefik.http.routers.blog.tls.certresolver=myresolver | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="Docker (Swarm)" | ||||
|     ## Dynamic configuration | ||||
|     deploy: | ||||
|       labels: | ||||
|         - traefik.http.routers.blog.rule=Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`) | ||||
|         - traefik.http.routers.blog.tls.certresolver=myresolver | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="Kubernetes" | ||||
|     apiVersion: traefik.io/v1alpha1 | ||||
|     kind: IngressRoute | ||||
|     metadata: | ||||
|       name: blogtls | ||||
|     spec: | ||||
|       entryPoints: | ||||
|         - websecure | ||||
|       routes: | ||||
|         - match: Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`) | ||||
|           kind: Rule | ||||
|           services: | ||||
|             - name: blog | ||||
|               port: 8080 | ||||
|       tls: | ||||
|         certResolver: myresolver | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="File (YAML)" | ||||
|     ## Dynamic configuration | ||||
|     http: | ||||
|       routers: | ||||
|         blog: | ||||
|           rule: "Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`)" | ||||
|           tls: | ||||
|             certResolver: myresolver | ||||
|     ``` | ||||
|  | ||||
|     ```toml tab="File (TOML)" | ||||
|     ## Dynamic configuration | ||||
|     [http.routers] | ||||
|       [http.routers.blog] | ||||
|       rule = "Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`)" | ||||
|       [http.routers.blog.tls] | ||||
|         certResolver = "myresolver" | ||||
|     ``` | ||||
|  | ||||
| !!! example "Domain from Router's tls.domain Example" | ||||
|  | ||||
|     ```yaml tab="Docker & Swarm" | ||||
|     ## Dynamic configuration | ||||
|     labels: | ||||
|       - traefik.http.routers.blog.rule=Path(`/metrics`) | ||||
|       - traefik.http.routers.blog.tls.certresolver=myresolver | ||||
|       - traefik.http.routers.blog.tls.domains[0].main=monitoring.yak-bebop.ts.net | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="Docker (Swarm)" | ||||
|     ## Dynamic configuration | ||||
|     deploy: | ||||
|       labels: | ||||
|         - traefik.http.routers.blog.rule=Path(`/metrics`) | ||||
|         - traefik.http.routers.blog.tls.certresolver=myresolver | ||||
|         - traefik.http.routers.blog.tls.domains[0].main=monitoring.yak-bebop.ts.net | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="Kubernetes" | ||||
|     apiVersion: traefik.io/v1alpha1 | ||||
|     kind: IngressRoute | ||||
|     metadata: | ||||
|       name: blogtls | ||||
|     spec: | ||||
|       entryPoints: | ||||
|         - websecure | ||||
|       routes: | ||||
|         - match: Path(`/metrics`) | ||||
|           kind: Rule | ||||
|           services: | ||||
|             - name: blog | ||||
|               port: 8080 | ||||
|       tls: | ||||
|         certResolver: myresolver | ||||
|         domains: | ||||
|           - main: monitoring.yak-bebop.ts.net | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="File (YAML)" | ||||
|     ## Dynamic configuration | ||||
|     http: | ||||
|       routers: | ||||
|         blog: | ||||
|           rule: "Path(`/metrics`)" | ||||
|           tls: | ||||
|             certResolver: myresolver | ||||
|             domains: | ||||
|               - main: "monitoring.yak-bebop.ts.net" | ||||
|     ``` | ||||
|  | ||||
|     ```toml tab="File (TOML)" | ||||
|     ## Dynamic configuration | ||||
|     [http.routers] | ||||
|       [http.routers.blog] | ||||
|         rule = "Path(`/metrics`)" | ||||
|         [http.routers.blog.tls] | ||||
|           certResolver = "myresolver" | ||||
|           [[http.routers.blog.tls.domains]] | ||||
|             main = "monitoring.yak-bebop.ts.net" | ||||
|     ``` | ||||
|  | ||||
| ## Automatic Renewals | ||||
|  | ||||
| Traefik automatically tracks the expiry date of each Tailscale certificate it fetches, | ||||
| and starts to renew a certificate 14 days before its expiry to match Tailscale daemon renew policy. | ||||
| @@ -211,7 +211,7 @@ spec: | ||||
|         - bar.example.org | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| ## Dynamic configuration | ||||
| labels: | ||||
|   - "traefik.tls.stores.default.defaultgeneratedcert.resolver=myresolver" | ||||
| @@ -219,14 +219,6 @@ labels: | ||||
|   - "traefik.tls.stores.default.defaultgeneratedcert.domain.sans=foo.example.org, bar.example.org" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| labels: { | ||||
|   "traefik.tls.stores.default.defaultgeneratedcert.resolver": "myresolver", | ||||
|   "traefik.tls.stores.default.defaultgeneratedcert.domain.main": "example.org", | ||||
|   "traefik.tls.stores.default.defaultgeneratedcert.domain.sans": "foo.example.org, bar.example.org", | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## TLS Options | ||||
|  | ||||
| The TLS options allow one to configure some parameters of the TLS connection. | ||||
|   | ||||
							
								
								
									
										3
									
								
								docs/content/includes/kubernetes-requirements.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								docs/content/includes/kubernetes-requirements.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| Traefik follows the [Kubernetes support policy](https://kubernetes.io/releases/version-skew-policy/#supported-versions), | ||||
| and supports at least the latest three minor versions of Kubernetes. | ||||
| General functionality cannot be guaranteed for versions older than that. | ||||
							
								
								
									
										11
									
								
								docs/content/includes/traefik-api-management-kubernetes.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								docs/content/includes/traefik-api-management-kubernetes.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| --- | ||||
|  | ||||
| !!! question "Managing APIs in Kubernetes?" | ||||
|  | ||||
|     If your organization is publishing, securing, and managing APIs, consider [Traefik Hub](https://traefik.io/traefik-hub/) for your API management solution. | ||||
|      | ||||
|     - K8s services auto-discovery, 100% CRDs configuration, & full GitOps compliance | ||||
|     - Centralized control plane for all APIs, users, & infrastructure components | ||||
|     - Self-serve API portal with API discovery, documentation, testing, & access control | ||||
|  | ||||
|     Traefik Hub makes managing APIs easier than ever before. See for yourself in this [short video walkthrough](https://info.traefik.io/watch-traefik-hub-demo). | ||||
| @@ -13,7 +13,7 @@ It receives requests on behalf of your system and finds out which components are | ||||
| What sets Traefik apart, besides its many features, is that it automatically discovers the right configuration for your services.  | ||||
| The magic happens when Traefik inspects your infrastructure, where it finds relevant information and discovers which service serves which request.  | ||||
|  | ||||
| Traefik is natively compliant with every major cluster technology, such as Kubernetes, Docker, Docker Swarm, AWS, Mesos, Marathon, and [the list goes on](providers/overview.md); and can handle many at the same time. (It even works for legacy software running on bare metal.) | ||||
| Traefik is natively compliant with every major cluster technology, such as Kubernetes, Docker, Docker Swarm, AWS, and [the list goes on](providers/overview.md); and can handle many at the same time. (It even works for legacy software running on bare metal.) | ||||
|   | ||||
| With Traefik, there is no need to maintain and synchronize a separate configuration file: everything happens automatically, in real time (no restarts, no connection interruptions). | ||||
| With Traefik, you spend time developing and deploying new features to your system, not on configuring and maintaining its working state.    | ||||
| @@ -24,7 +24,7 @@ Developing Traefik, our main goal is to make it simple to use, and we're sure yo | ||||
|  | ||||
| !!! info | ||||
|  | ||||
|     Join our user friendly and active [Community Forum]((https://community.traefik.io "Link to Traefik Community Forum") to discuss, learn, and connect with the traefik community. | ||||
|     Join our user friendly and active [Community Forum](https://community.traefik.io "Link to Traefik Community Forum") to discuss, learn, and connect with the traefik community. | ||||
|  | ||||
|     Using Traefik in your organization? Consider [Traefik Enterprise](https://traefik.io/traefik-enterprise/ "Lino to Traefik Enterprise"), our unified API Gateway and Ingress that simplifies the discovery, security, and deployment of APIs and microservices across any environment. | ||||
|  | ||||
|   | ||||
| @@ -14,7 +14,7 @@ The AddPrefix middleware updates the path of a request before forwarding it. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Prefixing with /foo | ||||
| labels: | ||||
|   - "traefik.http.middlewares.add-foo.addprefix.prefix=/foo" | ||||
| @@ -36,18 +36,6 @@ spec: | ||||
| - "traefik.http.middlewares.add-foo.addprefix.prefix=/foo" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.add-foo.addprefix.prefix": "/foo" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Prefixing with /foo | ||||
| labels: | ||||
|   - "traefik.http.middlewares.add-foo.addprefix.prefix=/foo" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Prefixing with /foo | ||||
| http: | ||||
|   | ||||
| @@ -14,7 +14,7 @@ The BasicAuth middleware restricts access to your services to known users. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Declaring the user list | ||||
| # | ||||
| # Note: when used in docker-compose.yml all dollar signs in the hash need to be doubled for escaping. | ||||
| @@ -41,18 +41,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.basicauth.users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Declaring the user list | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Declaring the user list | ||||
| http: | ||||
| @@ -100,7 +88,7 @@ The `users` option is an array of authorized users. Each user must be declared u | ||||
|     Please note that these keys are not hashed or encrypted in any way, and therefore is less secure than other methods. | ||||
|     You can find more information on the [Kubernetes Basic Authentication Secret Documentation](https://kubernetes.io/docs/concepts/configuration/secret/#basic-authentication-secret) | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Declaring the user list | ||||
| # | ||||
| # Note: when used in docker-compose.yml all dollar signs in the hash need to be doubled for escaping. | ||||
| @@ -157,18 +145,6 @@ data: | ||||
| - "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.basicauth.users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Declaring the user list | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Declaring the user list | ||||
| http: | ||||
| @@ -201,7 +177,7 @@ The file content is a list of `name:hashed-password`. | ||||
|     - If both `users` and `usersFile` are provided, the two are merged. The contents of `usersFile` have precedence over the values in `users`. | ||||
|     - Because it does not make much sense to refer to a file path on Kubernetes, the `usersFile` field doesn't exist for Kubernetes IngressRoute, and one should use the `secret` field instead. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.basicauth.usersfile=/path/to/my/usersfile" | ||||
| ``` | ||||
| @@ -232,17 +208,6 @@ data: | ||||
| - "traefik.http.middlewares.test-auth.basicauth.usersfile=/path/to/my/usersfile" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.basicauth.usersfile": "/path/to/my/usersfile" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.basicauth.usersfile=/path/to/my/usersfile" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -268,7 +233,7 @@ http: | ||||
|  | ||||
| You can customize the realm for the authentication with the `realm` option. The default value is `traefik`. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.basicauth.realm=MyRealm" | ||||
| ``` | ||||
| @@ -287,17 +252,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.basicauth.realm=MyRealm" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.basicauth.realm": "MyRealm" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.basicauth.realm=MyRealm" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -316,7 +270,7 @@ http: | ||||
|  | ||||
| You can define a header field to store the authenticated user using the `headerField`option. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.my-auth.basicauth.headerField=X-WebAuth-User" | ||||
| ``` | ||||
| @@ -336,12 +290,6 @@ spec: | ||||
| - "traefik.http.middlewares.my-auth.basicauth.headerField=X-WebAuth-User" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.my-auth.basicauth.headerField": "X-WebAuth-User" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -361,7 +309,7 @@ http: | ||||
|  | ||||
| Set the `removeHeader` option to `true` to remove the authorization header before forwarding the request to your service. (Default value is `false`.) | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.basicauth.removeheader=true" | ||||
| ``` | ||||
| @@ -380,17 +328,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.basicauth.removeheader=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.basicauth.removeheader": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.basicauth.removeheader=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|   | ||||
| @@ -18,7 +18,7 @@ This can help services avoid large amounts of data (`multipart/form-data` for ex | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Sets the maximum request body to 2MB | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" | ||||
| @@ -40,18 +40,6 @@ spec: | ||||
| - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes": "2000000" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Sets the maximum request body to 2MB | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Sets the maximum request body to 2MB | ||||
| http: | ||||
| @@ -78,7 +66,7 @@ The `maxRequestBodyBytes` option configures the maximum allowed body size for th | ||||
|  | ||||
| If the request exceeds the allowed size, it is not forwarded to the service, and the client gets a `413` (Request Entity Too Large) response. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" | ||||
| ``` | ||||
| @@ -97,17 +85,6 @@ spec: | ||||
| - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes": "2000000" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -128,7 +105,7 @@ _Optional, Default=1048576_ | ||||
|  | ||||
| You can configure a threshold (in bytes) from which the request will be buffered on disk instead of in memory with the `memRequestBodyBytes` option. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.memRequestBodyBytes=2000000" | ||||
| ``` | ||||
| @@ -147,17 +124,6 @@ spec: | ||||
| - "traefik.http.middlewares.limit.buffering.memRequestBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.limit.buffering.memRequestBodyBytes": "2000000" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.memRequestBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -180,7 +146,7 @@ The `maxResponseBodyBytes` option configures the maximum allowed response size f | ||||
|  | ||||
| If the response exceeds the allowed size, it is not forwarded to the client. The client gets a `500` (Internal Server Error) response instead. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.maxResponseBodyBytes=2000000" | ||||
| ``` | ||||
| @@ -199,17 +165,6 @@ spec: | ||||
| - "traefik.http.middlewares.limit.buffering.maxResponseBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.limit.buffering.maxResponseBodyBytes": "2000000" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.maxResponseBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -230,7 +185,7 @@ _Optional, Default=1048576_ | ||||
|  | ||||
| You can configure a threshold (in bytes) from which the response will be buffered on disk instead of in memory with the `memResponseBodyBytes` option. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.memResponseBodyBytes=2000000" | ||||
| ``` | ||||
| @@ -249,17 +204,6 @@ spec: | ||||
| - "traefik.http.middlewares.limit.buffering.memResponseBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.limit.buffering.memResponseBodyBytes": "2000000" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.memResponseBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -282,7 +226,7 @@ You can have the Buffering middleware replay the request using `retryExpression` | ||||
|  | ||||
| ??? example "Retries once in the case of a network error" | ||||
|  | ||||
|     ```yaml tab="Docker" | ||||
|     ```yaml tab="Docker & Swarm" | ||||
|     labels: | ||||
|       - "traefik.http.middlewares.limit.buffering.retryExpression=IsNetworkError() && Attempts() < 2" | ||||
|     ``` | ||||
| @@ -301,17 +245,6 @@ You can have the Buffering middleware replay the request using `retryExpression` | ||||
|     - "traefik.http.middlewares.limit.buffering.retryExpression=IsNetworkError() && Attempts() < 2" | ||||
|     ``` | ||||
|  | ||||
|     ```json tab="Marathon" | ||||
|     "labels": { | ||||
|       "traefik.http.middlewares.limit.buffering.retryExpression": "IsNetworkError() && Attempts() < 2" | ||||
|     } | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="Rancher" | ||||
|     labels: | ||||
|       - "traefik.http.middlewares.limit.buffering.retryExpression=IsNetworkError() && Attempts() < 2" | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="File (YAML)" | ||||
|     http: | ||||
|       middlewares: | ||||
|   | ||||
| @@ -15,9 +15,9 @@ It makes reusing the same groups easier. | ||||
|  | ||||
| ## Configuration Example | ||||
|  | ||||
| Below is an example of a Chain containing `WhiteList`, `BasicAuth`, and `RedirectScheme`. | ||||
| Below is an example of a Chain containing `AllowList`, `BasicAuth`, and `RedirectScheme`. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.routers.router1.service=service1" | ||||
|   - "traefik.http.routers.router1.middlewares=secured" | ||||
| @@ -25,7 +25,7 @@ labels: | ||||
|   - "traefik.http.middlewares.secured.chain.middlewares=https-only,known-ips,auth-users" | ||||
|   - "traefik.http.middlewares.auth-users.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" | ||||
|   - "traefik.http.middlewares.https-only.redirectscheme.scheme=https" | ||||
|   - "traefik.http.middlewares.known-ips.ipwhitelist.sourceRange=192.168.1.7,127.0.0.1/32" | ||||
|   - "traefik.http.middlewares.known-ips.ipallowlist.sourceRange=192.168.1.7,127.0.0.1/32" | ||||
|   - "traefik.http.services.service1.loadbalancer.server.port=80" | ||||
| ``` | ||||
|  | ||||
| @@ -80,7 +80,7 @@ kind: Middleware | ||||
| metadata: | ||||
|   name: known-ips | ||||
| spec: | ||||
|   ipWhiteList: | ||||
|   ipAllowList: | ||||
|     sourceRange: | ||||
|     - 192.168.1.7 | ||||
|     - 127.0.0.1/32 | ||||
| @@ -93,35 +93,10 @@ spec: | ||||
| - "traefik.http.middlewares.secured.chain.middlewares=https-only,known-ips,auth-users" | ||||
| - "traefik.http.middlewares.auth-users.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" | ||||
| - "traefik.http.middlewares.https-only.redirectscheme.scheme=https" | ||||
| - "traefik.http.middlewares.known-ips.ipwhitelist.sourceRange=192.168.1.7,127.0.0.1/32" | ||||
| - "traefik.http.middlewares.known-ips.ipallowlist.sourceRange=192.168.1.7,127.0.0.1/32" | ||||
| - "traefik.http.services.service1.loadbalancer.server.port=80" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.routers.router1.service": "service1", | ||||
|   "traefik.http.routers.router1.middlewares": "secured", | ||||
|   "traefik.http.routers.router1.rule": "Host(`mydomain`)", | ||||
|   "traefik.http.middlewares.secured.chain.middlewares": "https-only,known-ips,auth-users", | ||||
|   "traefik.http.middlewares.auth-users.basicauth.users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", | ||||
|   "traefik.http.middlewares.https-only.redirectscheme.scheme": "https", | ||||
|   "traefik.http.middlewares.known-ips.ipwhitelist.sourceRange": "192.168.1.7,127.0.0.1/32", | ||||
|   "traefik.http.services.service1.loadbalancer.server.port": "80" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.routers.router1.service=service1" | ||||
|   - "traefik.http.routers.router1.middlewares=secured" | ||||
|   - "traefik.http.routers.router1.rule=Host(`mydomain`)" | ||||
|   - "traefik.http.middlewares.secured.chain.middlewares=https-only,known-ips,auth-users" | ||||
|   - "traefik.http.middlewares.auth-users.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" | ||||
|   - "traefik.http.middlewares.https-only.redirectscheme.scheme=https" | ||||
|   - "traefik.http.middlewares.known-ips.ipwhitelist.sourceRange=192.168.1.7,127.0.0.1/32" | ||||
|   - "traefik.http.services.service1.loadbalancer.server.port=80" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # ... | ||||
| http: | ||||
| @@ -150,7 +125,7 @@ http: | ||||
|         scheme: https | ||||
|  | ||||
|     known-ips: | ||||
|       ipWhiteList: | ||||
|       ipAllowList: | ||||
|         sourceRange: | ||||
|           - "192.168.1.7" | ||||
|           - "127.0.0.1/32" | ||||
| @@ -180,7 +155,7 @@ http: | ||||
|   [http.middlewares.https-only.redirectScheme] | ||||
|     scheme = "https" | ||||
|  | ||||
|   [http.middlewares.known-ips.ipWhiteList] | ||||
|   [http.middlewares.known-ips.ipAllowList] | ||||
|     sourceRange = ["192.168.1.7", "127.0.0.1/32"] | ||||
|  | ||||
| [http.services] | ||||
|   | ||||
| @@ -30,7 +30,7 @@ To assess if your system is healthy, the circuit breaker constantly monitors the | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Latency Check | ||||
| labels: | ||||
|   - "traefik.http.middlewares.latency-check.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 100" | ||||
| @@ -52,18 +52,6 @@ spec: | ||||
| - "traefik.http.middlewares.latency-check.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 100" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.latency-check.circuitbreaker.expression": "LatencyAtQuantileMS(50.0) > 100" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Latency Check | ||||
| labels: | ||||
|   - "traefik.http.middlewares.latency-check.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 100" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Latency Check | ||||
| http: | ||||
|   | ||||
| @@ -5,23 +5,24 @@ description: "Traefik Proxy's HTTP middleware lets you compress responses before | ||||
|  | ||||
| # Compress | ||||
|  | ||||
| Compress Responses before Sending them to the Client | ||||
| Compress Allows Compressing Responses before Sending them to the Client | ||||
| {: .subtitle } | ||||
|  | ||||
|  | ||||
|  | ||||
| The Compress middleware uses gzip compression. | ||||
| The Compress middleware supports gzip and Brotli compression. | ||||
| The activation of compression, and the compression method choice rely (among other things) on the request's `Accept-Encoding` header. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| # Enable gzip compression | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Enable compression | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-compress.compress=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Enable gzip compression | ||||
| # Enable compression | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
| @@ -31,24 +32,12 @@ spec: | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Consul Catalog" | ||||
| # Enable gzip compression | ||||
| # Enable compression | ||||
| - "traefik.http.middlewares.test-compress.compress=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-compress.compress": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Enable gzip compression | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-compress.compress=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Enable gzip compression | ||||
| # Enable compression | ||||
| http: | ||||
|   middlewares: | ||||
|     test-compress: | ||||
| @@ -56,7 +45,7 @@ http: | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| # Enable gzip compression | ||||
| # Enable compression | ||||
| [http.middlewares] | ||||
|   [http.middlewares.test-compress.compress] | ||||
| ``` | ||||
| @@ -65,24 +54,35 @@ http: | ||||
|  | ||||
|     Responses are compressed when the following criteria are all met: | ||||
|  | ||||
|     * The response body is larger than the configured minimum amount of bytes (default is `1024`). | ||||
|     * The `Accept-Encoding` request header contains `gzip`. | ||||
|     * The `Accept-Encoding` request header contains `gzip`, `*`, and/or `br` with or without [quality values](https://developer.mozilla.org/en-US/docs/Glossary/Quality_values). | ||||
|     If the `Accept-Encoding` request header is absent, it is meant as br compression is requested. | ||||
|     If it is present, but its value is the empty string, then compression is disabled. | ||||
|     * The response is not already compressed, i.e. the `Content-Encoding` response header is not already set. | ||||
|  | ||||
|     If the `Content-Type` header is not defined, or empty, the compress middleware will automatically [detect](https://mimesniff.spec.whatwg.org/) a content type. | ||||
|     It will also set the `Content-Type` header according to the detected MIME type. | ||||
|     * The response`Content-Type` header is not one among the [excludedContentTypes options](#excludedcontenttypes). | ||||
|     * The response body is larger than the [configured minimum amount of bytes](#minresponsebodybytes) (default is `1024`). | ||||
|  | ||||
| ## Configuration Options | ||||
|  | ||||
| ### `excludedContentTypes` | ||||
|  | ||||
| _Optional, Default=""_  | ||||
|  | ||||
| `excludedContentTypes` specifies a list of content types to compare the `Content-Type` header of the incoming requests and responses before compressing. | ||||
|  | ||||
| The responses with content types defined in `excludedContentTypes` are not compressed. | ||||
|  | ||||
| Content types are compared in a case-insensitive, whitespace-ignored manner. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| !!! info "In the case of gzip" | ||||
|  | ||||
|     If the `Content-Type` header is not defined, or empty, the compress middleware will automatically [detect](https://mimesniff.spec.whatwg.org/) a content type. | ||||
|     It will also set the `Content-Type` header according to the detected MIME type. | ||||
|  | ||||
| !!! info "gRPC" | ||||
|  | ||||
|     Note that `application/grpc` is never compressed. | ||||
|  | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-compress.compress.excludedcontenttypes=text/event-stream" | ||||
| ``` | ||||
| @@ -102,17 +102,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-compress.compress.excludedcontenttypes=text/event-stream" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-compress.compress.excludedcontenttypes": "text/event-stream" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-compress.compress.excludedcontenttypes=text/event-stream" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -130,13 +119,13 @@ http: | ||||
|  | ||||
| ### `minResponseBodyBytes` | ||||
|  | ||||
| `minResponseBodyBytes` specifies the minimum amount of bytes a response body must have to be compressed. | ||||
| _Optional, Default=1024_ | ||||
|  | ||||
| The default value is `1024`, which should be a reasonable value for most cases. | ||||
| `minResponseBodyBytes` specifies the minimum amount of bytes a response body must have to be compressed. | ||||
|  | ||||
| Responses smaller than the specified values will not be compressed. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-compress.compress.minresponsebodybytes=1200" | ||||
| ``` | ||||
| @@ -155,17 +144,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-compress.compress.minresponsebodybytes=1200" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-compress.compress.minresponsebodybytes": 1200 | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-compress.compress.minresponsebodybytes=1200" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| --- | ||||
| title: "Traefik ContentType Documentation" | ||||
| description: "Traefik Proxy's HTTP middleware can automatically specify the content-type header if it has not been defined by the backend. Read the technical documentation." | ||||
| description: "Traefik Proxy's HTTP middleware automatically sets the `Content-Type` header value when it is not set by the backend. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # ContentType | ||||
| @@ -8,84 +8,47 @@ description: "Traefik Proxy's HTTP middleware can automatically specify the cont | ||||
| Handling Content-Type auto-detection | ||||
| {: .subtitle } | ||||
|  | ||||
| The Content-Type middleware - or rather its `autoDetect` option - | ||||
| specifies whether to let the `Content-Type` header, | ||||
| if it has not been defined by the backend, | ||||
| be automatically set to a value derived from the contents of the response. | ||||
|  | ||||
| As a proxy, the default behavior should be to leave the header alone, | ||||
| regardless of what the backend did with it. | ||||
| However, the historic default was to always auto-detect and set the header if it was not already defined, | ||||
| and altering this behavior would be a breaking change which would impact many users. | ||||
|  | ||||
| This middleware exists to enable the correct behavior until at least the default one can be changed in a future version. | ||||
| The Content-Type middleware sets the `Content-Type` header value to the media type detected from the response content, | ||||
| when it is not set by the backend. | ||||
|  | ||||
| !!! info | ||||
|  | ||||
|     As explained above, for compatibility reasons the default behavior on a router (without this middleware), | ||||
|     is still to automatically set the `Content-Type` header. | ||||
|     Therefore, given the default value of the `autoDetect` option (false), | ||||
|     simply enabling this middleware for a router switches the router's behavior. | ||||
|  | ||||
|     The scope of the Content-Type middleware is the MIME type detection done by the core of Traefik (the server part). | ||||
|     Therefore, it has no effect against any other `Content-Type` header modifications (e.g.: in another middleware such as compress). | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| # Disable auto-detection | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Enable auto-detection | ||||
| labels: | ||||
|   - "traefik.http.middlewares.autodetect.contenttype.autodetect=false" | ||||
|   - "traefik.http.middlewares.autodetect.contenttype=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Disable auto-detection | ||||
| # Enable auto-detection | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: autodetect | ||||
| spec: | ||||
|   contentType: | ||||
|     autoDetect: false | ||||
|   contentType: {} | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Consul Catalog" | ||||
| # Disable auto-detection | ||||
| - "traefik.http.middlewares.autodetect.contenttype.autodetect=false" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.autodetect.contenttype.autodetect": "false" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Disable auto-detection | ||||
| labels: | ||||
|   - "traefik.http.middlewares.autodetect.contenttype.autodetect=false" | ||||
| # Enable auto-detection | ||||
| - "traefik.http.middlewares.autodetect.contenttype=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Disable auto-detection | ||||
| # Enable auto-detection | ||||
| http: | ||||
|   middlewares: | ||||
|     autodetect: | ||||
|       contentType: | ||||
|         autoDetect: false | ||||
|       contentType: {} | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| # Disable auto-detection | ||||
| # Enable auto-detection | ||||
| [http.middlewares] | ||||
|   [http.middlewares.autodetect.contentType] | ||||
|      autoDetect=false | ||||
| ``` | ||||
|  | ||||
| ## Configuration Options | ||||
|  | ||||
| ### `autoDetect` | ||||
|  | ||||
| `autoDetect` specifies whether to let the `Content-Type` header, | ||||
| if it has not been set by the backend, | ||||
| be automatically set to a value derived from the contents of the response. | ||||
|   | ||||
| @@ -14,7 +14,7 @@ The DigestAuth middleware restricts access to your services to known users. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Declaring the user list | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" | ||||
| @@ -36,18 +36,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.digestauth.users": "test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Declaring the user list | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Declaring the user list | ||||
| http: | ||||
| @@ -84,7 +72,7 @@ The `users` option is an array of authorized users. Each user will be declared u | ||||
|     - If both `users` and `usersFile` are provided, the two are merged. The contents of `usersFile` have precedence over the values in `users`. | ||||
|     - For security reasons, the field `users` doesn't exist for Kubernetes IngressRoute, and one should use the `secret` field instead. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" | ||||
| ``` | ||||
| @@ -114,17 +102,6 @@ data: | ||||
| - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.digestauth.users": "test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -155,7 +132,7 @@ The file content is a list of `name:realm:encoded-password`. | ||||
|     - If both `users` and `usersFile` are provided, the two are merged. The contents of `usersFile` have precedence over the values in `users`. | ||||
|     - Because it does not make much sense to refer to a file path on Kubernetes, the `usersFile` field doesn't exist for Kubernetes IngressRoute, and one should use the `secret` field instead. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.usersfile=/path/to/my/usersfile" | ||||
| ``` | ||||
| @@ -186,17 +163,6 @@ data: | ||||
| - "traefik.http.middlewares.test-auth.digestauth.usersfile=/path/to/my/usersfile" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.digestauth.usersfile": "/path/to/my/usersfile" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.usersfile=/path/to/my/usersfile" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -222,7 +188,7 @@ http: | ||||
|  | ||||
| You can customize the realm for the authentication with the `realm` option. The default value is `traefik`. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.realm=MyRealm" | ||||
| ``` | ||||
| @@ -241,17 +207,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.digestauth.realm=MyRealm" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.digestauth.realm": "MyRealm" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.realm=MyRealm" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -270,7 +225,7 @@ http: | ||||
|  | ||||
| You can customize the header field for the authenticated user using the `headerField`option. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.my-auth.digestauth.headerField=X-WebAuth-User" | ||||
| ``` | ||||
| @@ -290,17 +245,6 @@ spec: | ||||
| - "traefik.http.middlewares.my-auth.digestauth.headerField=X-WebAuth-User" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.my-auth.digestauth.headerField": "X-WebAuth-User" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.my-auth.digestauth.headerField=X-WebAuth-User" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -320,7 +264,7 @@ http: | ||||
|  | ||||
| Set the `removeHeader` option to `true` to remove the authorization header before forwarding the request to your service. (Default value is `false`.) | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.removeheader=true" | ||||
| ``` | ||||
| @@ -339,17 +283,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.digestauth.removeheader=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.digestauth.removeheader": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.removeheader=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|   | ||||
| @@ -18,7 +18,7 @@ The Errors middleware returns a custom page in lieu of the default, according to | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Dynamic Custom Error Page for 5XX Status Code | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-errors.errors.status=500-599" | ||||
| @@ -48,22 +48,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-errors.errors.query=/{status}.html" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-errors.errors.status": "500-599", | ||||
|   "traefik.http.middlewares.test-errors.errors.service": "serviceError", | ||||
|   "traefik.http.middlewares.test-errors.errors.query": "/{status}.html" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Dynamic Custom Error Page for 5XX Status Code | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-errors.errors.status=500-599" | ||||
|   - "traefik.http.middlewares.test-errors.errors.service=serviceError" | ||||
|   - "traefik.http.middlewares.test-errors.errors.query=/{status}.html" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Custom Error Page for 5XX | ||||
| http: | ||||
|   | ||||
| @@ -16,7 +16,7 @@ Otherwise, the response from the authentication server is returned. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Forward authentication to example.com | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" | ||||
| @@ -38,18 +38,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.address": "https://example.com/auth" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Forward authentication to example.com | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Forward authentication to example.com | ||||
| http: | ||||
| @@ -84,7 +72,7 @@ The following request properties are provided to the forward-auth target endpoin | ||||
|  | ||||
| The `address` option defines the authentication server address. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" | ||||
| ``` | ||||
| @@ -103,17 +91,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.address": "https://example.com/auth" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -132,7 +109,7 @@ http: | ||||
|  | ||||
| Set the `trustForwardHeader` option to `true` to trust all `X-Forwarded-*` headers. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true" | ||||
| ``` | ||||
| @@ -152,17 +129,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -184,7 +150,7 @@ http: | ||||
| The `authResponseHeaders` option is the list of headers to copy from the authentication server response and set on | ||||
| forwarded request, replacing any existing conflicting headers. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret" | ||||
| ``` | ||||
| @@ -206,17 +172,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders": "X-Auth-User,X-Secret" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -242,7 +197,7 @@ set on forwarded request, after stripping all headers that match the regex. | ||||
| It allows partial matching of the regular expression against the header key. | ||||
| The start of string (`^`) and end of string (`$`) anchors should be used to ensure a full match against the header key. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeadersRegex=^X-" | ||||
| ``` | ||||
| @@ -262,17 +217,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeadersRegex=^X-" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.authResponseHeadersRegex": "^X-" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeadersRegex=^X-" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -301,7 +245,7 @@ The `authRequestHeaders` option is the list of the headers to copy from the requ | ||||
| It allows filtering headers that should not be passed to the authentication server. | ||||
| If not set or empty then all request headers are passed. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.authRequestHeaders=Accept,X-CustomHeader" | ||||
| ``` | ||||
| @@ -323,17 +267,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.authRequestHeaders=Accept,X-CustomHeader" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.authRequestHeaders": "Accept,X-CustomHeader" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.authRequestHeaders=Accept,X-CustomHeader" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -365,7 +298,7 @@ _Optional_ | ||||
| `ca` is the path to the certificate authority used for the secured connection to the authentication server, | ||||
| it defaults to the system bundle. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt" | ||||
| ``` | ||||
| @@ -397,17 +330,6 @@ data: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.tls.ca": "path/to/local.crt" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -433,7 +355,7 @@ _Optional_ | ||||
| `cert` is the path to the public certificate used for the secure connection to the authentication server. | ||||
| When using this option, setting the `key` option is required. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert" | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" | ||||
| @@ -467,19 +389,6 @@ data: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.tls.cert": "path/to/foo.cert", | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.tls.key": "path/to/foo.key" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert" | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -511,7 +420,7 @@ _Optional_ | ||||
| `key` is the path to the private key used for the secure connection to the authentication server. | ||||
| When using this option, setting the `cert` option is required. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert" | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" | ||||
| @@ -545,19 +454,6 @@ data: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.tls.cert": "path/to/foo.cert", | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.tls.key": "path/to/foo.key" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert" | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -588,7 +484,7 @@ _Optional, Default=false_ | ||||
|  | ||||
| If `insecureSkipVerify` is `true`, the TLS connection to the authentication server accepts any certificate presented by the server regardless of the hostnames it covers. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.insecureSkipVerify=true" | ||||
| ``` | ||||
| @@ -609,17 +505,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.tls.InsecureSkipVerify=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.tls.insecureSkipVerify": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.InsecureSkipVerify=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|   | ||||
							
								
								
									
										66
									
								
								docs/content/middlewares/http/grpcweb.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								docs/content/middlewares/http/grpcweb.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| --- | ||||
| title: "Traefik GrpcWeb Documentation" | ||||
| description: "In Traefik Proxy's HTTP middleware, GrpcWeb converts a gRPC Web requests to HTTP/2 gRPC requests. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # GrpcWeb | ||||
|  | ||||
| Converting gRPC Web requests to HTTP/2 gRPC requests. | ||||
| {: .subtitle } | ||||
|  | ||||
| The GrpcWeb middleware converts gRPC Web requests to HTTP/2 gRPC requests before forwarding them to the backends. | ||||
|  | ||||
| !!! tip | ||||
|  | ||||
|     Please note, that Traefik needs to communicate using gRPC with the backends (h2c or HTTP/2 over TLS). | ||||
|     Check out the [gRPC](../../user-guides/grpc.md) user guide for more details. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-grpcweb.grpcweb.allowOrigins=*" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-grpcweb | ||||
| spec: | ||||
|   grpcWeb: | ||||
|     allowOrigins: | ||||
|       - "*" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Consul Catalog" | ||||
| - "traefik.http.middlewares.test-grpcweb.grpcWeb.allowOrigins=*" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|     test-grpcweb: | ||||
|       grpcWeb: | ||||
|         allowOrigins: | ||||
|           - "*" | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [http.middlewares] | ||||
|   [http.middlewares.test-grpcweb.grpcWeb] | ||||
|     allowOrigins = ["*"] | ||||
| ``` | ||||
|  | ||||
| ## Configuration Options | ||||
|  | ||||
| ### `allowOrigins` | ||||
|  | ||||
| The `allowOrigins` contains the list of allowed origins. | ||||
| A wildcard origin `*` can also be configured to match all requests. | ||||
|  | ||||
| More information including how to use the settings can be found at: | ||||
|  | ||||
| - [Mozilla.org](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin) | ||||
| - [w3](https://fetch.spec.whatwg.org/#http-access-control-allow-origin) | ||||
| - [IETF](https://tools.ietf.org/html/rfc6454#section-7.1) | ||||
| @@ -20,7 +20,7 @@ A set of forwarded headers are automatically added by default. See the [FAQ](../ | ||||
|  | ||||
| The following example adds the `X-Script-Name` header to the proxied request and the `X-Custom-Response-Header` header to the response | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.testHeader.headers.customrequestheaders.X-Script-Name=test" | ||||
|   - "traefik.http.middlewares.testHeader.headers.customresponseheaders.X-Custom-Response-Header=value" | ||||
| @@ -44,19 +44,6 @@ spec: | ||||
| - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header=value" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name": "test", | ||||
|   "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header": "value" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name=test" | ||||
|   - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header=value" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -82,7 +69,7 @@ http: | ||||
| In the following example, requests are proxied with an extra `X-Script-Name` header while their `X-Custom-Request-Header` header gets stripped, | ||||
| and responses are stripped of their `X-Custom-Response-Header` header. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name=test" | ||||
|   - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Custom-Request-Header=" | ||||
| @@ -109,21 +96,6 @@ spec: | ||||
| - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header=" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name": "test", | ||||
|   "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Custom-Request-Header": "", | ||||
|   "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header": "", | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name=test" | ||||
|   - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Custom-Request-Header=" | ||||
|   - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header=" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -151,7 +123,7 @@ http: | ||||
| Security-related headers (HSTS headers, Browser XSS filter, etc) can be managed similarly to custom headers as shown above. | ||||
| This functionality makes it possible to easily use security features by adding headers. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.testHeader.headers.framedeny=true" | ||||
|   - "traefik.http.middlewares.testHeader.headers.browserxssfilter=true" | ||||
| @@ -173,19 +145,6 @@ spec: | ||||
| - "traefik.http.middlewares.testheader.headers.browserxssfilter=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.testheader.headers.framedeny": "true", | ||||
|   "traefik.http.middlewares.testheader.headers.browserxssfilter": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.testheader.headers.framedeny=true" | ||||
|   - "traefik.http.middlewares.testheader.headers.browserxssfilter=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -211,7 +170,7 @@ instead the response will be generated and sent back to the client directly. | ||||
| Please note that the example below is by no means authoritative or exhaustive, | ||||
| and should not be used as is for production. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods=GET,OPTIONS,PUT" | ||||
|   - "traefik.http.middlewares.testheader.headers.accesscontrolallowheaders=*" | ||||
| @@ -247,25 +206,6 @@ spec: | ||||
| - "traefik.http.middlewares.testheader.headers.addvaryheader=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods": "GET,OPTIONS,PUT", | ||||
|   "traefik.http.middlewares.testheader.headers.accesscontrolallowheaders=*", | ||||
|   "traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist": "https://foo.bar.org,https://example.org", | ||||
|   "traefik.http.middlewares.testheader.headers.accesscontrolmaxage": "100", | ||||
|   "traefik.http.middlewares.testheader.headers.addvaryheader": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods=GET,OPTIONS,PUT" | ||||
|   - "traefik.http.middlewares.testheader.headers.accesscontrolallowheaders=*" | ||||
|   - "traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist=https://foo.bar.org,https://example.org" | ||||
|   - "traefik.http.middlewares.testheader.headers.accesscontrolmaxage=100" | ||||
|   - "traefik.http.middlewares.testheader.headers.addvaryheader=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -373,43 +313,11 @@ The `allowedHosts` option lists fully qualified domain names that are allowed. | ||||
|  | ||||
| The `hostsProxyHeaders` option is a set of header keys that may hold a proxied hostname value for the request. | ||||
|  | ||||
| ### `sslRedirect` | ||||
|  | ||||
| !!! warning | ||||
|  | ||||
|     Deprecated in favor of [EntryPoint redirection](../../routing/entrypoints.md#redirection) or the [RedirectScheme middleware](./redirectscheme.md). | ||||
|  | ||||
| The `sslRedirect` only allow HTTPS requests when set to `true`. | ||||
|  | ||||
| ### `sslTemporaryRedirect` | ||||
|  | ||||
| !!! warning | ||||
|  | ||||
|     Deprecated in favor of [EntryPoint redirection](../../routing/entrypoints.md#redirection) or the [RedirectScheme middleware](./redirectscheme.md). | ||||
|  | ||||
| Set `sslTemporaryRedirect` to `true` to force an SSL redirection using a 302 (instead of a 301). | ||||
|  | ||||
| ### `sslHost` | ||||
|  | ||||
| !!! warning | ||||
|  | ||||
|     Deprecated in favor of the [RedirectRegex middleware](./redirectregex.md). | ||||
|  | ||||
| The `sslHost` option is the host name that is used to redirect HTTP requests to HTTPS. | ||||
|  | ||||
| ### `sslProxyHeaders` | ||||
|  | ||||
| The `sslProxyHeaders` option is set of header keys with associated values that would indicate a valid HTTPS request. | ||||
| It can be useful when using other proxies (example: `"X-Forwarded-Proto": "https"`). | ||||
|  | ||||
| ### `sslForceHost` | ||||
|  | ||||
| !!! warning | ||||
|  | ||||
|     Deprecated in favor of the [RedirectRegex middleware](./redirectregex.md). | ||||
|  | ||||
| Set `sslForceHost` to `true` and set `sslHost` to force requests to use `SSLHost` regardless of whether they already use SSL. | ||||
|  | ||||
| ### `stsSeconds` | ||||
|  | ||||
| The `stsSeconds` is the max-age of the `Strict-Transport-Security` header. | ||||
| @@ -461,14 +369,6 @@ The `publicKey` implements HPKP to prevent MITM attacks with forged certificates | ||||
|  | ||||
| The `referrerPolicy` allows sites to control whether browsers forward the `Referer` header to other sites. | ||||
|  | ||||
| ### `featurePolicy` | ||||
|  | ||||
| !!! warning | ||||
|  | ||||
|     Deprecated in favor of `permissionsPolicy` | ||||
|  | ||||
| The `featurePolicy` allows sites to control browser features. | ||||
|  | ||||
| ### `permissionsPolicy` | ||||
|  | ||||
| The `permissionsPolicy` allows sites to control browser features. | ||||
|   | ||||
| @@ -14,7 +14,7 @@ To proactively prevent services from being overwhelmed with high load, the numbe | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" | ||||
| ``` | ||||
| @@ -34,18 +34,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-inflightreq.inflightreq.amount": "10" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Limiting to 10 simultaneous connections | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Limiting to 10 simultaneous connections | ||||
| http: | ||||
| @@ -69,7 +57,7 @@ http: | ||||
| The `amount` option defines the maximum amount of allowed simultaneous in-flight request. | ||||
| The middleware responds with `HTTP 429 Too Many Requests` if there are already `amount` requests in progress (based on the same `sourceCriterion` strategy). | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" | ||||
| ``` | ||||
| @@ -89,18 +77,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-inflightreq.inflightreq.amount": "10" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Limiting to 10 simultaneous connections | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Limiting to 10 simultaneous connections | ||||
| http: | ||||
| @@ -146,7 +122,7 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and select | ||||
|     | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `3`     | `"11.0.0.1"` | | ||||
|     | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `5`     | `""`         | | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.depth=2" | ||||
| ``` | ||||
| @@ -167,17 +143,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.depth=2" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.depth": "2" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.depth=2" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -211,7 +176,7 @@ http: | ||||
|     | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `"15.0.0.1,16.0.0.1"` | `"13.0.0.1"` | | ||||
|     | `"10.0.0.1,11.0.0.1"`                   | `"10.0.0.1,11.0.0.1"` | `""`         | | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
| @@ -234,17 +199,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.excludedips": "127.0.0.1/32, 192.168.1.7" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -268,7 +222,7 @@ http: | ||||
|  | ||||
| Name of the header used to group incoming requests. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requestheadername=username" | ||||
| ``` | ||||
| @@ -288,17 +242,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requestheadername=username" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requestheadername": "username" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requestheadername=username" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -319,7 +262,7 @@ http: | ||||
|  | ||||
| Whether to consider the request host as the source. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requesthost=true" | ||||
| ``` | ||||
| @@ -339,17 +282,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requesthost=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requesthost": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requesthost=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|   | ||||
| @@ -1,32 +1,30 @@ | ||||
| --- | ||||
| title: "Traefik HTTP Middlewares IPWhiteList" | ||||
| description: "Learn how to use IPWhiteList in HTTP middleware for limiting clients to specific IPs in Traefik Proxy. Read the technical documentation." | ||||
| title: "Traefik HTTP Middlewares IPAllowList" | ||||
| description: "Learn how to use IPAllowList in HTTP middleware for limiting clients to specific IPs in Traefik Proxy. Read the technical documentation." | ||||
| --- | ||||
| 
 | ||||
| # IPWhiteList | ||||
| # IPAllowList | ||||
| 
 | ||||
| Limiting Clients to Specific IPs | ||||
| {: .subtitle } | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| IPWhitelist accepts / refuses requests based on the client IP. | ||||
| IPAllowList accepts / refuses requests based on the client IP. | ||||
| 
 | ||||
| ## Configuration Examples | ||||
| 
 | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Accepts request from defined IP | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
|   - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-ipwhitelist | ||||
|   name: test-ipallowlist | ||||
| spec: | ||||
|   ipWhiteList: | ||||
|   ipAllowList: | ||||
|     sourceRange: | ||||
|       - 127.0.0.1/32 | ||||
|       - 192.168.1.7 | ||||
| @@ -34,27 +32,15 @@ spec: | ||||
| 
 | ||||
| ```yaml tab="Consul Catalog" | ||||
| # Accepts request from defined IP | ||||
| - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
| 
 | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourcerange": "127.0.0.1/32,192.168.1.7" | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="Rancher" | ||||
| # Accepts request from defined IP | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
| - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="File (YAML)" | ||||
| # Accepts request from defined IP | ||||
| http: | ||||
|   middlewares: | ||||
|     test-ipwhitelist: | ||||
|       ipWhiteList: | ||||
|     test-ipallowlist: | ||||
|       ipAllowList: | ||||
|         sourceRange: | ||||
|           - "127.0.0.1/32" | ||||
|           - "192.168.1.7" | ||||
| @@ -63,7 +49,7 @@ http: | ||||
| ```toml tab="File (TOML)" | ||||
| # Accepts request from defined IP | ||||
| [http.middlewares] | ||||
|   [http.middlewares.test-ipwhitelist.ipWhiteList] | ||||
|   [http.middlewares.test-ipallowlist.ipAllowList] | ||||
|     sourceRange = ["127.0.0.1/32", "192.168.1.7"] | ||||
| ``` | ||||
| 
 | ||||
| @@ -89,7 +75,7 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and take th | ||||
| 
 | ||||
| !!! example "Examples of Depth & X-Forwarded-For" | ||||
| 
 | ||||
|     If `depth` is set to 2, and the request `X-Forwarded-For` header is `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` then the "real" client IP is `"10.0.0.1"` (at depth 4) but the IP used for the whitelisting is `"12.0.0.1"` (`depth=2`). | ||||
|     If `depth` is set to 2, and the request `X-Forwarded-For` header is `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` then the "real" client IP is `"10.0.0.1"` (at depth 4) but the IP used is `"12.0.0.1"` (`depth=2`). | ||||
| 
 | ||||
|     | `X-Forwarded-For`                       | `depth` | clientIP     | | ||||
|     |-----------------------------------------|---------|--------------| | ||||
| @@ -97,21 +83,21 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and take th | ||||
|     | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `3`     | `"11.0.0.1"` | | ||||
|     | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `5`     | `""`         | | ||||
| 
 | ||||
| ```yaml tab="Docker" | ||||
| # Whitelisting Based on `X-Forwarded-For` with `depth=2` | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Allowlisting Based on `X-Forwarded-For` with `depth=2` | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
|   - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.ipstrategy.depth=2" | ||||
|   - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
|   - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth=2" | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="Kubernetes" | ||||
| # Whitelisting Based on `X-Forwarded-For` with `depth=2` | ||||
| # Allowlisting Based on `X-Forwarded-For` with `depth=2` | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-ipwhitelist | ||||
|   name: test-ipallowlist | ||||
| spec: | ||||
|   ipWhiteList: | ||||
|   ipAllowList: | ||||
|     sourceRange: | ||||
|       - 127.0.0.1/32 | ||||
|       - 192.168.1.7 | ||||
| @@ -120,31 +106,17 @@ spec: | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="Consul Catalog" | ||||
| # Whitelisting Based on `X-Forwarded-For` with `depth=2` | ||||
| - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
| - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.ipstrategy.depth=2" | ||||
| ``` | ||||
| 
 | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourcerange": "127.0.0.1/32, 192.168.1.7", | ||||
|   "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.ipstrategy.depth": "2" | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="Rancher" | ||||
| # Whitelisting Based on `X-Forwarded-For` with `depth=2` | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
|   - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.ipstrategy.depth=2" | ||||
| # Allowlisting Based on `X-Forwarded-For` with `depth=2` | ||||
| - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
| - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth=2" | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="File (YAML)" | ||||
| # Whitelisting Based on `X-Forwarded-For` with `depth=2` | ||||
| # Allowlisting Based on `X-Forwarded-For` with `depth=2` | ||||
| http: | ||||
|   middlewares: | ||||
|     test-ipwhitelist: | ||||
|       ipWhiteList: | ||||
|     test-ipallowlist: | ||||
|       ipAllowList: | ||||
|         sourceRange: | ||||
|           - "127.0.0.1/32" | ||||
|           - "192.168.1.7" | ||||
| @@ -153,11 +125,11 @@ http: | ||||
| ``` | ||||
| 
 | ||||
| ```toml tab="File (TOML)" | ||||
| # Whitelisting Based on `X-Forwarded-For` with `depth=2` | ||||
| # Allowlisting Based on `X-Forwarded-For` with `depth=2` | ||||
| [http.middlewares] | ||||
|   [http.middlewares.test-ipwhitelist.ipWhiteList] | ||||
|   [http.middlewares.test-ipallowlist.ipAllowList] | ||||
|     sourceRange = ["127.0.0.1/32", "192.168.1.7"] | ||||
|     [http.middlewares.test-ipwhitelist.ipWhiteList.ipStrategy] | ||||
|     [http.middlewares.test-ipallowlist.ipAllowList.ipStrategy] | ||||
|       depth = 2 | ||||
| ``` | ||||
| 
 | ||||
| @@ -177,10 +149,10 @@ http: | ||||
|     | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `"15.0.0.1,16.0.0.1"` | `"13.0.0.1"` | | ||||
|     | `"10.0.0.1,11.0.0.1"`                   | `"10.0.0.1,11.0.0.1"` | `""`         | | ||||
| 
 | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Exclude from `X-Forwarded-For` | ||||
| labels: | ||||
|     - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
|     - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="Kubernetes" | ||||
| @@ -188,9 +160,9 @@ labels: | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-ipwhitelist | ||||
|   name: test-ipallowlist | ||||
| spec: | ||||
|   ipWhiteList: | ||||
|   ipAllowList: | ||||
|     ipStrategy: | ||||
|       excludedIPs: | ||||
|         - 127.0.0.1/32 | ||||
| @@ -199,27 +171,15 @@ spec: | ||||
| 
 | ||||
| ```yaml tab="Consul Catalog" | ||||
| # Exclude from `X-Forwarded-For` | ||||
| - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
| 
 | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.ipstrategy.excludedips": "127.0.0.1/32, 192.168.1.7" | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="Rancher" | ||||
| # Exclude from `X-Forwarded-For` | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="File (YAML)" | ||||
| # Exclude from `X-Forwarded-For` | ||||
| http: | ||||
|   middlewares: | ||||
|     test-ipwhitelist: | ||||
|       ipWhiteList: | ||||
|     test-ipallowlist: | ||||
|       ipAllowList: | ||||
|         ipStrategy: | ||||
|           excludedIPs: | ||||
|             - "127.0.0.1/32" | ||||
| @@ -229,7 +189,7 @@ http: | ||||
| ```toml tab="File (TOML)" | ||||
| # Exclude from `X-Forwarded-For` | ||||
| [http.middlewares] | ||||
|   [http.middlewares.test-ipwhitelist.ipWhiteList] | ||||
|     [http.middlewares.test-ipwhitelist.ipWhiteList.ipStrategy] | ||||
|   [http.middlewares.test-ipallowlist.ipAllowList] | ||||
|     [http.middlewares.test-ipallowlist.ipAllowList.ipStrategy] | ||||
|       excludedIPs = ["127.0.0.1/32", "192.168.1.7"] | ||||
| ``` | ||||
| @@ -12,7 +12,7 @@ Controlling connections | ||||
|  | ||||
| ## Configuration Example | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # As a Docker Label | ||||
| whoami: | ||||
|   #  A container that exposes an API to show its IP address | ||||
| @@ -26,19 +26,6 @@ whoami: | ||||
|  | ||||
| ```yaml tab="Kubernetes IngressRoute" | ||||
| # As a Kubernetes Traefik IngressRoute | ||||
| apiVersion: apiextensions.k8s.io/v1beta1 | ||||
| kind: CustomResourceDefinition | ||||
| metadata: | ||||
|   name: middlewares.traefik.io | ||||
| spec: | ||||
|   group: traefik.io | ||||
|   version: v1alpha1 | ||||
|   names: | ||||
|     kind: Middleware | ||||
|     plural: middlewares | ||||
|     singular: middleware | ||||
|   scope: Namespaced | ||||
|  | ||||
| --- | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| @@ -69,22 +56,6 @@ spec: | ||||
| - "traefik.http.routers.router1.middlewares=foo-add-prefix@consulcatalog" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.foo-add-prefix.addprefix.prefix": "/foo", | ||||
|   "traefik.http.routers.router1.middlewares": "foo-add-prefix@marathon" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # As a Rancher Label | ||||
| labels: | ||||
|   # Create a middleware named `foo-add-prefix` | ||||
|   - "traefik.http.middlewares.foo-add-prefix.addprefix.prefix=/foo" | ||||
|   # Apply the middleware named `foo-add-prefix` to the router named `router1` | ||||
|   - "traefik.http.routers.router1.middlewares=foo-add-prefix@rancher" | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| # As TOML Configuration File | ||||
| [http.routers] | ||||
| @@ -142,7 +113,7 @@ http: | ||||
| | [Errors](errorpages.md)                   | Defines custom error pages                        | Request Lifecycle           | | ||||
| | [ForwardAuth](forwardauth.md)             | Delegates Authentication                          | Security, Authentication    | | ||||
| | [Headers](headers.md)                     | Adds / Updates headers                            | Security                    | | ||||
| | [IPWhiteList](ipwhitelist.md)             | Limits the allowed client IPs                     | Security, Request lifecycle | | ||||
| | [IPAllowList](ipallowlist.md)             | Limits the allowed client IPs                     | Security, Request lifecycle | | ||||
| | [InFlightReq](inflightreq.md)             | Limits the number of simultaneous connections     | Security, Request lifecycle | | ||||
| | [PassTLSClientCert](passtlsclientcert.md) | Adds Client Certificates in a Header              | Security                    | | ||||
| | [RateLimit](ratelimit.md)                 | Limits the call frequency                         | Security, Request lifecycle | | ||||
|   | ||||
| @@ -18,7 +18,7 @@ PassTLSClientCert adds the selected data from the passed client TLS certificate | ||||
|  | ||||
| Pass the pem in the `X-Forwarded-Tls-Client-Cert` header. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Pass the pem in the `X-Forwarded-Tls-Client-Cert` header. | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem=true" | ||||
| @@ -39,18 +39,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Pass the pem in the `X-Forwarded-Tls-Client-Cert` header. | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Pass the pem in the `X-Forwarded-Tls-Client-Cert` header. | ||||
| http: | ||||
| @@ -69,7 +57,7 @@ http: | ||||
|  | ||||
| ??? example "Pass the pem in the `X-Forwarded-Tls-Client-Cert` header" | ||||
|  | ||||
|     ```yaml tab="Docker" | ||||
|     ```yaml tab="Docker & Swarm" | ||||
|     # Pass all the available info in the `X-Forwarded-Tls-Client-Cert-Info` header | ||||
|     labels: | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notafter=true" | ||||
| @@ -146,52 +134,6 @@ http: | ||||
|     - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.serialnumber=true" | ||||
|     ``` | ||||
|  | ||||
|     ```json tab="Marathon" | ||||
|     "labels": { | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notafter": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notbefore": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.sans": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.commonname": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.country": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.locality": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organization": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organizationalunit": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.province": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.serialnumber": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.commonname": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.country": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.domaincomponent": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.locality": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.organization": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.province": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.serialnumber": "true" | ||||
|     } | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="Rancher" | ||||
|     # Pass all the available info in the `X-Forwarded-Tls-Client-Cert-Info` header | ||||
|     labels: | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notafter=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notbefore=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.sans=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.commonname=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.country=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.locality=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organization=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organizationalunit=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.province=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.serialnumber=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.commonname=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.country=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.domaincomponent=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.locality=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.organization=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.province=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.serialnumber=true" | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="File (YAML)" | ||||
|     # Pass all the available info in the `X-Forwarded-Tls-Client-Cert-Info` header | ||||
|     http: | ||||
|   | ||||
| @@ -14,7 +14,7 @@ It is based on a [token bucket](https://en.wikipedia.org/wiki/Token_bucket) impl | ||||
|  | ||||
| ## Configuration Example | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Here, an average of 100 requests per second is allowed. | ||||
| # In addition, a burst of 50 requests is allowed. | ||||
| labels: | ||||
| @@ -42,21 +42,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=50" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.average": "100", | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.burst": "50" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Here, an average of 100 requests per second is allowed. | ||||
| # In addition, a burst of 50 requests is allowed. | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.average=100" | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=50" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Here, an average of 100 requests per second is allowed. | ||||
| # In addition, a burst of 50 requests is allowed. | ||||
| @@ -88,7 +73,7 @@ It defaults to `0`, which means no rate limiting. | ||||
| The rate is actually defined by dividing `average` by `period`. | ||||
| So for a rate below 1 req/s, one needs to define a `period` larger than a second. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # 100 reqs/s | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.average=100" | ||||
| @@ -110,17 +95,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-ratelimit.ratelimit.average=100" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.average": "100", | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.average=100" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # 100 reqs/s | ||||
| http: | ||||
| @@ -147,7 +121,7 @@ r = average / period | ||||
|  | ||||
| It defaults to `1` second. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # 6 reqs/minute | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.average=6" | ||||
| @@ -172,20 +146,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-ratelimit.ratelimit.period=1m" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.average": "6", | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.period": "1m", | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # 6 reqs/minute | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.average=6" | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.period=1m" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # 6 reqs/minute | ||||
| http: | ||||
| @@ -210,7 +170,7 @@ http: | ||||
|  | ||||
| It defaults to `1`. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=100" | ||||
| ``` | ||||
| @@ -229,17 +189,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=100" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.burst": "100", | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=100" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -283,7 +232,7 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and select | ||||
|     | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `3`     | `"11.0.0.1"` | | ||||
|     | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `5`     | `""`         | | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.depth=2" | ||||
| ``` | ||||
| @@ -304,17 +253,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.depth=2" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.depth": "2" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.depth=2" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -375,7 +313,7 @@ and the first IP that is _not_ in the pool (if any) is returned. | ||||
|     | `"10.0.0.1,11.0.0.1,13.0.0.1"` | `"15.0.0.1,16.0.0.1"` | `"13.0.0.1"` | | ||||
|     | `"10.0.0.1,11.0.0.1"`          | `"10.0.0.1,11.0.0.1"` | `""`         | | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
| @@ -398,17 +336,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.excludedips": "127.0.0.1/32, 192.168.1.7" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -432,7 +359,7 @@ http: | ||||
|  | ||||
| Name of the header used to group incoming requests. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requestheadername=username" | ||||
| ``` | ||||
| @@ -452,17 +379,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requestheadername=username" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requestheadername": "username" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requestheadername=username" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -483,7 +399,7 @@ http: | ||||
|  | ||||
| Whether to consider the request host as the source. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requesthost=true" | ||||
| ``` | ||||
| @@ -503,17 +419,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requesthost=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requesthost": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requesthost=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|   | ||||
| @@ -16,7 +16,7 @@ The RedirectRegex redirects a request using regex matching and replacement. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Redirect with domain replacement | ||||
| # Note: all dollar signs need to be doubled for escaping. | ||||
| labels: | ||||
| @@ -43,21 +43,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-redirectregex.redirectregex.replacement=http://mydomain/$${1}" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-redirectregex.redirectregex.regex": "^http://localhost/(.*)", | ||||
|   "traefik.http.middlewares.test-redirectregex.redirectregex.replacement": "http://mydomain/${1}" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Redirect with domain replacement | ||||
| # Note: all dollar signs need to be doubled for escaping. | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-redirectregex.redirectregex.regex=^http://localhost/(.*)" | ||||
|   - "traefik.http.middlewares.test-redirectregex.redirectregex.replacement=http://mydomain/$${1}" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Redirect with domain replacement | ||||
| http: | ||||
|   | ||||
| @@ -25,7 +25,7 @@ The RedirectScheme middleware redirects the request if the request scheme is dif | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Redirect to https | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https" | ||||
| @@ -51,20 +51,6 @@ labels: | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme": "https" | ||||
|   "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Redirect to https | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https" | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Redirect to https | ||||
| http: | ||||
| @@ -89,7 +75,7 @@ http: | ||||
|  | ||||
| Set the `permanent` option to `true` to apply a permanent redirection. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Redirect to https | ||||
| labels: | ||||
|   # ... | ||||
| @@ -115,20 +101,6 @@ labels: | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|  | ||||
|   "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Redirect to https | ||||
| labels: | ||||
|   # ... | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Redirect to https | ||||
| http: | ||||
| @@ -151,7 +123,7 @@ http: | ||||
|  | ||||
| The `scheme` option defines the scheme of the new URL. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Redirect to https | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https" | ||||
| @@ -174,18 +146,6 @@ labels: | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme": "https" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Redirect to https | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Redirect to https | ||||
| http: | ||||
| @@ -206,7 +166,7 @@ http: | ||||
|  | ||||
| The `port` option defines the port of the new URL. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Redirect to https | ||||
| labels: | ||||
|   # ... | ||||
| @@ -232,20 +192,6 @@ labels: | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.port=443" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|  | ||||
|   "traefik.http.middlewares.test-redirectscheme.redirectscheme.port": "443" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Redirect to https | ||||
| labels: | ||||
|   # ... | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.port=443" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Redirect to https | ||||
| http: | ||||
|   | ||||
| @@ -16,7 +16,7 @@ Replace the path of the request URL. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Replace the path with /foo | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-replacepath.replacepath.path=/foo" | ||||
| @@ -38,18 +38,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-replacepath.replacepath.path=/foo" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-replacepath.replacepath.path": "/foo" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Replace the path with /foo | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-replacepath.replacepath.path=/foo" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Replace the path with /foo | ||||
| http: | ||||
|   | ||||
| @@ -16,7 +16,7 @@ The ReplaceRegex replaces the path of a URL using regex matching and replacement | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Replace path with regex | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-replacepathregex.replacepathregex.regex=^/foo/(.*)" | ||||
| @@ -41,20 +41,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-replacepathregex.replacepathregex.replacement=/bar/$1" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-replacepathregex.replacepathregex.regex": "^/foo/(.*)", | ||||
|   "traefik.http.middlewares.test-replacepathregex.replacepathregex.replacement": "/bar/$1" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Replace path with regex | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-replacepathregex.replacepathregex.regex=^/foo/(.*)" | ||||
|   - "traefik.http.middlewares.test-replacepathregex.replacepathregex.replacement=/bar/$1" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Replace path with regex | ||||
| http: | ||||
|   | ||||
| @@ -18,7 +18,7 @@ The Retry middleware has an optional configuration to enable an exponential back | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Retry 4 times with exponential backoff | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-retry.retry.attempts=4" | ||||
| @@ -43,20 +43,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-retry.retry.initialinterval=100ms" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-retry.retry.attempts": "4", | ||||
|   "traefik.http.middlewares.test-retry.retry.initialinterval": "100ms", | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Retry 4 times with exponential backoff | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-retry.retry.attempts=4" | ||||
|   - "traefik.http.middlewares.test-retry.retry.initialinterval=100ms" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Retry 4 times with exponential backoff | ||||
| http: | ||||
|   | ||||
| @@ -16,7 +16,7 @@ Remove the specified prefixes from the URL path. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Strip prefix /foobar and /fiibar | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes=/foobar,/fiibar" | ||||
| @@ -40,18 +40,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes=/foobar,/fiibar" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes": "/foobar,/fiibar" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Strip prefix /foobar and /fiibar | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes=/foobar,/fiibar" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Strip prefix /foobar and /fiibar | ||||
| http: | ||||
| @@ -88,85 +76,3 @@ For instance, `/products` also matches `/products/shoes` and `/products/shirts`. | ||||
|  | ||||
| If your backend is serving assets (e.g., images or JavaScript files), it can use the `X-Forwarded-Prefix` header to properly construct relative URLs. | ||||
| Using the previous example, the backend should return `/products/shoes/image.png` (and not `/image.png`, which Traefik would likely not be able to associate with the same backend). | ||||
|  | ||||
| ### `forceSlash` | ||||
|  | ||||
| _Optional, Default=true_ | ||||
|  | ||||
| The `forceSlash` option ensures the resulting stripped path is not the empty string, by replacing it with `/` when necessary. | ||||
|  | ||||
| This option was added to keep the initial (non-intuitive) behavior of this middleware, in order to avoid introducing a breaking change. | ||||
|  | ||||
| It is recommended to explicitly set `forceSlash` to `false`. | ||||
|  | ||||
| ??? info "Behavior examples" | ||||
|  | ||||
|     - `forceSlash=true` | ||||
|  | ||||
|     | Path       | Prefix to strip | Result | | ||||
|     |------------|-----------------|--------| | ||||
|     | `/`        | `/`             | `/`    | | ||||
|     | `/foo`     | `/foo`          | `/`    | | ||||
|     | `/foo/`    | `/foo`          | `/`    | | ||||
|     | `/foo/`    | `/foo/`         | `/`    | | ||||
|     | `/bar`     | `/foo`          | `/bar` | | ||||
|     | `/foo/bar` | `/foo`          | `/bar` | | ||||
|  | ||||
|     - `forceSlash=false` | ||||
|  | ||||
|     | Path       | Prefix to strip | Result | | ||||
|     |------------|-----------------|--------| | ||||
|     | `/`        | `/`             | empty  | | ||||
|     | `/foo`     | `/foo`          | empty  | | ||||
|     | `/foo/`    | `/foo`          | `/`    | | ||||
|     | `/foo/`    | `/foo/`         | empty  | | ||||
|     | `/bar`     | `/foo`          | `/bar` | | ||||
|     | `/foo/bar` | `/foo`          | `/bar` | | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.example.stripprefix.prefixes=/foobar" | ||||
|   - "traefik.http.middlewares.example.stripprefix.forceSlash=false" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: example | ||||
| spec: | ||||
|   stripPrefix: | ||||
|     prefixes: | ||||
|       - "/foobar" | ||||
|     forceSlash: false | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.example.stripprefix.prefixes": "/foobar", | ||||
|   "traefik.http.middlewares.example.stripprefix.forceSlash": "false" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.example.stripprefix.prefixes=/foobar" | ||||
|   - "traefik.http.middlewares.example.stripprefix.forceSlash=false" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|     example: | ||||
|       stripPrefix: | ||||
|         prefixes: | ||||
|           - "/foobar" | ||||
|         forceSlash: false | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [http.middlewares] | ||||
|   [http.middlewares.example.stripPrefix] | ||||
|     prefixes = ["/foobar"] | ||||
|     forceSlash = false | ||||
| ``` | ||||
|   | ||||
| @@ -12,7 +12,7 @@ Remove the matching prefixes from the URL path. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/" | ||||
| ``` | ||||
| @@ -32,17 +32,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex": "/foo/[a-z0-9]+/[0-9]+/" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|   | ||||
| @@ -23,7 +23,7 @@ Middlewares that use the same protocol can be combined into chains to fit every | ||||
|  | ||||
| ## Configuration Example | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # As a Docker Label | ||||
| whoami: | ||||
|   #  A container that exposes an API to show its IP address | ||||
| @@ -66,22 +66,6 @@ spec: | ||||
| - "traefik.http.routers.router1.middlewares=foo-add-prefix@consulcatalog" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.foo-add-prefix.addprefix.prefix": "/foo", | ||||
|   "traefik.http.routers.router1.middlewares": "foo-add-prefix@marathon" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # As a Rancher Label | ||||
| labels: | ||||
|   # Create a middleware named `foo-add-prefix` | ||||
|   - "traefik.http.middlewares.foo-add-prefix.addprefix.prefix=/foo" | ||||
|   # Apply the middleware named `foo-add-prefix` to the router named `router1` | ||||
|   - "traefik.http.routers.router1.middlewares=foo-add-prefix@rancher" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # As YAML Configuration File | ||||
| http: | ||||
|   | ||||
| @@ -7,7 +7,7 @@ To proactively prevent services from being overwhelmed with high load, the numbe | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.tcp.middlewares.test-inflightconn.inflightconn.amount=10" | ||||
| ``` | ||||
| @@ -27,18 +27,6 @@ spec: | ||||
| - "traefik.tcp.middlewares.test-inflightconn.inflightconn.amount=10" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.tcp.middlewares.test-inflightconn.inflightconn.amount": "10" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Limiting to 10 simultaneous connections. | ||||
| labels: | ||||
|   - "traefik.tcp.middlewares.test-inflightconn.inflightconn.amount=10" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Limiting to 10 simultaneous connections. | ||||
| tcp: | ||||
|   | ||||
| @@ -1,30 +1,30 @@ | ||||
| --- | ||||
| title: "Traefik TCP Middlewares IPWhiteList" | ||||
| description: "Learn how to use IPWhiteList in TCP middleware for limiting clients to specific IPs in Traefik Proxy. Read the technical documentation." | ||||
| title: "Traefik TCP Middlewares IPAllowList" | ||||
| description: "Learn how to use IPAllowList in TCP middleware for limiting clients to specific IPs in Traefik Proxy. Read the technical documentation." | ||||
| --- | ||||
| 
 | ||||
| # IPWhiteList | ||||
| # IPAllowList | ||||
| 
 | ||||
| Limiting Clients to Specific IPs | ||||
| {: .subtitle } | ||||
| 
 | ||||
| IPWhitelist accepts / refuses connections based on the client IP. | ||||
| IPAllowList accepts / refuses connections based on the client IP. | ||||
| 
 | ||||
| ## Configuration Examples | ||||
| 
 | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Accepts connections from defined IP | ||||
| labels: | ||||
|   - "traefik.tcp.middlewares.test-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
|   - "traefik.tcp.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: MiddlewareTCP | ||||
| metadata: | ||||
|   name: test-ipwhitelist | ||||
|   name: test-ipallowlist | ||||
| spec: | ||||
|   ipWhiteList: | ||||
|   ipAllowList: | ||||
|     sourceRange: | ||||
|       - 127.0.0.1/32 | ||||
|       - 192.168.1.7 | ||||
| @@ -32,25 +32,13 @@ spec: | ||||
| 
 | ||||
| ```yaml tab="Consul Catalog" | ||||
| # Accepts request from defined IP | ||||
| - "traefik.tcp.middlewares.test-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
| 
 | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.tcp.middlewares.test-ipwhitelist.ipwhitelist.sourcerange": "127.0.0.1/32,192.168.1.7" | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="Rancher" | ||||
| # Accepts request from defined IP | ||||
| labels: | ||||
|   - "traefik.tcp.middlewares.test-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
| - "traefik.tcp.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
| 
 | ||||
| ```toml tab="File (TOML)" | ||||
| # Accepts request from defined IP | ||||
| [tcp.middlewares] | ||||
|   [tcp.middlewares.test-ipwhitelist.ipWhiteList] | ||||
|   [tcp.middlewares.test-ipallowlist.ipAllowList] | ||||
|     sourceRange = ["127.0.0.1/32", "192.168.1.7"] | ||||
| ``` | ||||
| 
 | ||||
| @@ -58,8 +46,8 @@ labels: | ||||
| # Accepts request from defined IP | ||||
| tcp: | ||||
|   middlewares: | ||||
|     test-ipwhitelist: | ||||
|       ipWhiteList: | ||||
|     test-ipallowlist: | ||||
|       ipAllowList: | ||||
|         sourceRange: | ||||
|           - "127.0.0.1/32" | ||||
|           - "192.168.1.7" | ||||
| @@ -12,40 +12,27 @@ Controlling connections | ||||
|  | ||||
| ## Configuration Example | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # As a Docker Label | ||||
| whoami: | ||||
|   #  A container that exposes an API to show its IP address | ||||
|   image: traefik/whoami | ||||
|   labels: | ||||
|     # Create a middleware named `foo-ip-whitelist` | ||||
|     - "traefik.tcp.middlewares.foo-ip-whitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
|     # Apply the middleware named `foo-ip-whitelist` to the router named `router1` | ||||
|     - "traefik.tcp.routers.router1.middlewares=foo-ip-whitelist@docker" | ||||
|     # Create a middleware named `foo-ip-allowlist` | ||||
|     - "traefik.tcp.middlewares.foo-ip-allowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
|     # Apply the middleware named `foo-ip-allowlist` to the router named `router1` | ||||
|     - "traefik.tcp.routers.router1.middlewares=foo-ip-allowlist@docker" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes IngressRoute" | ||||
| # As a Kubernetes Traefik IngressRoute | ||||
| apiVersion: apiextensions.k8s.io/v1beta1 | ||||
| kind: CustomResourceDefinition | ||||
| metadata: | ||||
|   name: middlewaretcps.traefik.io | ||||
| spec: | ||||
|   group: traefik.io | ||||
|   version: v1alpha1 | ||||
|   names: | ||||
|     kind: MiddlewareTCP | ||||
|     plural: middlewaretcps | ||||
|     singular: middlewaretcp | ||||
|   scope: Namespaced | ||||
|  | ||||
| --- | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: MiddlewareTCP | ||||
| metadata: | ||||
|   name: foo-ip-whitelist | ||||
|   name: foo-ip-allowlist | ||||
| spec: | ||||
|   ipWhiteList: | ||||
|   ipAllowList: | ||||
|     sourcerange: | ||||
|       - 127.0.0.1/32 | ||||
|       - 192.168.1.7 | ||||
| @@ -60,30 +47,14 @@ spec: | ||||
|   routes: | ||||
|     # more fields... | ||||
|     middlewares: | ||||
|       - name: foo-ip-whitelist | ||||
|       - name: foo-ip-allowlist | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Consul Catalog" | ||||
| # Create a middleware named `foo-ip-whitelist` | ||||
| - "traefik.tcp.middlewares.foo-ip-whitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
| # Apply the middleware named `foo-ip-whitelist` to the router named `router1` | ||||
| - "traefik.tcp.routers.router1.middlewares=foo-ip-whitelist@consulcatalog" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.tcp.middlewares.foo-ip-whitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7", | ||||
|   "traefik.tcp.routers.router1.middlewares=foo-ip-whitelist@marathon" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # As a Rancher Label | ||||
| labels: | ||||
|   # Create a middleware named `foo-ip-whitelist` | ||||
|   - "traefik.tcp.middlewares.foo-ip-whitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
|   # Apply the middleware named `foo-ip-whitelist` to the router named `router1` | ||||
|   - "traefik.tcp.routers.router1.middlewares=foo-ip-whitelist@rancher" | ||||
| # Create a middleware named `foo-ip-allowlist` | ||||
| - "traefik.tcp.middlewares.foo-ip-allowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
| # Apply the middleware named `foo-ip-allowlist` to the router named `router1` | ||||
| - "traefik.tcp.routers.router1.middlewares=foo-ip-allowlist@consulcatalog" | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| @@ -91,11 +62,11 @@ labels: | ||||
| [tcp.routers] | ||||
|   [tcp.routers.router1] | ||||
|     service = "myService" | ||||
|     middlewares = ["foo-ip-whitelist"] | ||||
|     middlewares = ["foo-ip-allowlist"] | ||||
|     rule = "Host(`example.com`)" | ||||
|  | ||||
| [tcp.middlewares] | ||||
|   [tcp.middlewares.foo-ip-whitelist.ipWhiteList] | ||||
|   [tcp.middlewares.foo-ip-allowlist.ipAllowList] | ||||
|     sourceRange = ["127.0.0.1/32", "192.168.1.7"] | ||||
|  | ||||
| [tcp.services] | ||||
| @@ -114,12 +85,12 @@ tcp: | ||||
|     router1: | ||||
|       service: myService | ||||
|       middlewares: | ||||
|         - "foo-ip-whitelist" | ||||
|         - "foo-ip-allowlist" | ||||
|       rule: "Host(`example.com`)" | ||||
|  | ||||
|   middlewares: | ||||
|     foo-ip-whitelist: | ||||
|       ipWhiteList: | ||||
|     foo-ip-allowlist: | ||||
|       ipAllowList: | ||||
|         sourceRange: | ||||
|           - "127.0.0.1/32" | ||||
|           - "192.168.1.7" | ||||
| @@ -137,4 +108,4 @@ tcp: | ||||
| | Middleware                                | Purpose                                           | Area                        | | ||||
| |-------------------------------------------|---------------------------------------------------|-----------------------------| | ||||
| | [InFlightConn](inflightconn.md)           | Limits the number of simultaneous connections.    | Security, Request lifecycle | | ||||
| | [IPWhiteList](ipwhitelist.md)             | Limit the allowed client IPs.                     | Security, Request lifecycle | | ||||
| | [IPAllowList](ipallowlist.md)             | Limit the allowed client IPs.                     | Security, Request lifecycle | | ||||
|   | ||||
| @@ -38,7 +38,7 @@ Then any router can refer to an instance of the wanted middleware. | ||||
|  | ||||
|     !!! info "v1" | ||||
|  | ||||
|     ```yaml tab="Docker" | ||||
|     ```yaml tab="Docker & Swarm" | ||||
|     labels: | ||||
|       - "traefik.frontend.rule=Host:test.localhost;PathPrefix:/test" | ||||
|       - "traefik.frontend.auth.basic.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" | ||||
| @@ -100,7 +100,7 @@ Then any router can refer to an instance of the wanted middleware. | ||||
|  | ||||
|     !!! info "v2" | ||||
|  | ||||
|     ```yaml tab="Docker" | ||||
|     ```yaml tab="Docker & Swarm" | ||||
|     labels: | ||||
|       - "traefik.http.routers.router0.rule=Host(`test.localhost`) && PathPrefix(`/test`)" | ||||
|       - "traefik.http.routers.router0.middlewares=auth" | ||||
| @@ -317,7 +317,7 @@ Then, a [router's TLS field](../routing/routers/index.md#tls) can refer to one o | ||||
|           namespace: default | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="Docker" | ||||
|     ```yaml tab="Docker & Swarm" | ||||
|     labels: | ||||
|       # myTLSOptions must be defined by another provider, in this instance in the File Provider. | ||||
|       # see the cross provider section | ||||
| @@ -428,7 +428,7 @@ To apply a redirection: | ||||
|  | ||||
|     !!! info "v2" | ||||
|  | ||||
|     ```yaml tab="Docker" | ||||
|     ```yaml tab="Docker & Swarm" | ||||
|     labels: | ||||
|       traefik.http.routers.app.rule: Host(`example.net`) | ||||
|       traefik.http.routers.app.entrypoints: web | ||||
| @@ -556,7 +556,7 @@ with the path `/admin` stripped, e.g. to `http://<IP>:<port>/`. In this case, yo | ||||
|  | ||||
|     !!! info "v1" | ||||
|  | ||||
|     ```yaml tab="Docker" | ||||
|     ```yaml tab="Docker & Swarm" | ||||
|     labels: | ||||
|       - "traefik.frontend.rule=Host:example.org;PathPrefixStrip:/admin" | ||||
|     ``` | ||||
| @@ -588,7 +588,7 @@ with the path `/admin` stripped, e.g. to `http://<IP>:<port>/`. In this case, yo | ||||
|  | ||||
|     !!! info "v2" | ||||
|  | ||||
|     ```yaml tab="Docker" | ||||
|     ```yaml tab="Docker & Swarm" | ||||
|     labels: | ||||
|       - "traefik.http.routers.admin.rule=Host(`example.org`) && PathPrefix(`/admin`)" | ||||
|       - "traefik.http.routers.admin.middlewares=admin-stripprefix" | ||||
| @@ -1044,7 +1044,7 @@ To activate the dashboard, you can either: | ||||
|  | ||||
|     !!! info "v2" | ||||
|  | ||||
|     ```yaml tab="Docker" | ||||
|     ```yaml tab="Docker & Swarm" | ||||
|     # dynamic configuration | ||||
|     labels: | ||||
|       - "traefik.http.routers.api.rule=Host(`traefik.docker.localhost`)" | ||||
|   | ||||
							
								
								
									
										108
									
								
								docs/content/migration/v2-to-v3.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								docs/content/migration/v2-to-v3.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| --- | ||||
| title: "Traefik V3 Migration Documentation" | ||||
| description: "Migrate from Traefik Proxy v2 to v3 and update all the necessary configurations to take advantage of all the improvements. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # Migration Guide: From v2 to v3 | ||||
|  | ||||
| How to Migrate from Traefik v2 to Traefik v3. | ||||
| {: .subtitle } | ||||
|  | ||||
| The version 3 of Traefik introduces a number of breaking changes, | ||||
| which require one to update their configuration when they migrate from v2 to v3. | ||||
| 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 v2, and how it now looks like in v3. | ||||
|  | ||||
| ## IPWhiteList | ||||
|  | ||||
| In v3, we renamed the `IPWhiteList` middleware to `IPAllowList` without changing anything to the configuration.  | ||||
|  | ||||
| ## gRPC Metrics | ||||
|  | ||||
| In v3, the reported status code for gRPC requests is now the value of the `Grpc-Status` header.   | ||||
|  | ||||
| ## Deprecated Options Removal | ||||
|  | ||||
| - The `pilot` option has been removed from the static configuration. | ||||
| - The `tracing.datadog.globaltag` option has been removed. | ||||
| - The `namespace` option of Consul, Consul Catalog and Nomad providers has been removed. | ||||
| - The `tls.caOptional` option has been removed from the ForwardAuth middleware, as well as from the HTTP, Consul, Etcd, Redis, ZooKeeper, Consul Catalog, and Docker providers. | ||||
| - `sslRedirect`, `sslTemporaryRedirect`, `sslHost`, `sslForceHost` and `featurePolicy` options of the Headers middleware have been removed. | ||||
| - The `forceSlash` option of the StripPrefix middleware has been removed. | ||||
| - The `preferServerCipherSuites` option has been removed. | ||||
|  | ||||
| ## Matchers | ||||
|  | ||||
| In v3, the `Headers` and `HeadersRegexp` matchers have been renamed to `Header` and `HeaderRegexp` respectively. | ||||
|  | ||||
| `PathPrefix` no longer uses regular expressions to match path prefixes. | ||||
|  | ||||
| `QueryRegexp` has been introduced to match query values using a regular expression. | ||||
|  | ||||
| `HeaderRegexp`, `HostRegexp`, `PathRegexp`, `QueryRegexp`, and `HostSNIRegexp` matchers now uses the [Go regexp syntax](https://golang.org/pkg/regexp/syntax/). | ||||
|  | ||||
| All matchers now take a single value (except `Header`, `HeaderRegexp`, `Query`, and `QueryRegexp` which take two) | ||||
| and should be explicitly combined using logical operators to mimic previous behavior. | ||||
|  | ||||
| `Query` can take a single value to match is the query value that has no value (e.g. `/search?mobile`). | ||||
|  | ||||
| `HostHeader` has been removed, use `Host` instead. | ||||
|  | ||||
| ## Content-Type Auto-Detection | ||||
|  | ||||
| In v3, the `Content-Type` header is not auto-detected anymore when it is not set by the backend. | ||||
| One should use the `ContentType` middleware to enable the `Content-Type` header value auto-detection. | ||||
|  | ||||
| ## HTTP/3 | ||||
|  | ||||
| In v3, HTTP/3 is no longer an experimental feature. | ||||
| The `experimental.http3` option has been removed from the static configuration. | ||||
|  | ||||
| ## TCP ServersTransport | ||||
|  | ||||
| In v3, the support of `TCPServersTransport` has been introduced. | ||||
| When using the KubernetesCRD provider, it is therefore necessary to update [RBAC](../reference/dynamic-configuration/kubernetes-crd.md#rbac) and [CRD](../reference/dynamic-configuration/kubernetes-crd.md) manifests. | ||||
|  | ||||
| ### TCP LoadBalancer `terminationDelay` option | ||||
|  | ||||
| The TCP LoadBalancer `terminationDelay` option has been removed. | ||||
| This option can now be configured directly on the `TCPServersTransport` level, please take a look at this [documentation](../routing/services/index.md#terminationdelay) | ||||
|  | ||||
| ## Rancher v1 | ||||
|  | ||||
| In v3, the rancher v1 provider has been removed because Rancher v1 is [no longer actively maintaned](https://rancher.com/docs/os/v1.x/en/support/) and v2 is supported as a standard Kubernetes provider. | ||||
|  | ||||
| Rancher 2.x requires Kubernetes and does not have a metadata endpoint of its own for Traefik to query. | ||||
| As such, Rancher 2.x users should utilize the [Kubernetes CRD provider](../providers/kubernetes-crd.md) directly. | ||||
|  | ||||
| ## Marathon provider | ||||
|  | ||||
| In v3, the Marathon provider has been removed. | ||||
|  | ||||
| ## InfluxDB v1 | ||||
|  | ||||
| In v3, the InfluxDB v1 metrics provider has been removed because InfluxDB v1.x maintenance [ended in 2021](https://www.influxdata.com/blog/influxdb-oss-and-enterprise-roadmap-update-from-influxdays-emea/). | ||||
|  | ||||
| ### Kubernetes CRDs API Group `traefik.containo.us` | ||||
|  | ||||
| In v3, the Kubernetes CRDs API Group `traefik.containo.us` has been removed.  | ||||
| Please use the API Group `traefik.io` instead. | ||||
|  | ||||
| ## Docker & Docker Swarm | ||||
|  | ||||
| In v3, the provider Docker has been split into 2 providers: | ||||
|  | ||||
| - Docker provider (without Swarm support) | ||||
| - Swarm provider  (Swarm support only) | ||||
|  | ||||
| ### Kubernetes Ingress API Group `networking.k8s.io/v1beta1` | ||||
|  | ||||
| In v3, the Kubernetes Ingress API Group `networking.k8s.io/v1beta1` ([removed since Kubernetes v1.22](https://kubernetes.io/docs/reference/using-api/deprecation-guide/#ingress-v122)) support has been removed. | ||||
|  | ||||
| Please use the API Group `networking.k8s.io/v1` instead. | ||||
|  | ||||
| ### Traefik CRD API Version `apiextensions.k8s.io/v1beta1` | ||||
|  | ||||
| In v3, the Traefik CRD API Version `apiextensions.k8s.io/v1beta1` ([removed since Kubernetes v1.22](https://kubernetes.io/docs/reference/using-api/deprecation-guide/#customresourcedefinition-v122)) support has been removed. | ||||
|  | ||||
| Please use the CRD definition with the API Version `apiextensions.k8s.io/v1` instead. | ||||
| @@ -77,6 +77,7 @@ rules: | ||||
|       - tlsoptions | ||||
|       - tlsstores | ||||
|       - serverstransports | ||||
|       - serverstransporttcps | ||||
|     verbs: | ||||
|       - get | ||||
|       - list | ||||
| @@ -169,6 +170,7 @@ rules: | ||||
|     verbs: | ||||
|       - update | ||||
|   - apiGroups: | ||||
|       - traefik.io | ||||
|       - traefik.containo.us | ||||
|     resources: | ||||
|       - middlewares | ||||
| @@ -180,6 +182,7 @@ rules: | ||||
|       - tlsoptions | ||||
|       - tlsstores | ||||
|       - serverstransports | ||||
|       - serverstransporttcps | ||||
|     verbs: | ||||
|       - get | ||||
|       - list | ||||
| @@ -503,8 +506,6 @@ In `v2.9`, Traefik Pilot support has been removed. | ||||
|  | ||||
| In `v2.10`, the `namespace` option of the Nomad provider is deprecated, please use the `namespaces` options instead. | ||||
|  | ||||
| ## v2.10 | ||||
|  | ||||
| ### Kubernetes CRDs | ||||
|  | ||||
| In `v2.10`, the Kubernetes CRDs API Group `traefik.containo.us` is deprecated, and its support will end starting with Traefik v3. Please use the API Group `traefik.io` instead. | ||||
| @@ -514,6 +515,14 @@ it means that for the same kind, namespace and name, the provider will only keep | ||||
|  | ||||
| In addition, the Kubernetes CRDs API Version `traefik.io/v1alpha1` will not be supported in Traefik v3 itself. | ||||
|  | ||||
| Please note that it is a requirement to update the CRDs and the RBAC in the cluster before upgrading Traefik. | ||||
| To do so, please apply the required [CRDs](https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml) and [RBAC](https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml) manifests for v2.10: | ||||
|  | ||||
| ```bash | ||||
| kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml | ||||
| kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml | ||||
| ``` | ||||
|  | ||||
| ### Traefik Hub | ||||
|  | ||||
| In `v2.10`, Traefik Hub is GA and the `experimental.hub` flag is deprecated. | ||||
| In `v2.10`, Traefik Hub configuration has been removed because Traefik Hub v2 doesn't require this configuration. | ||||
|   | ||||
| @@ -154,9 +154,9 @@ accessLog: | ||||
|     headers: | ||||
|       defaultMode: keep | ||||
|       names: | ||||
|           User-Agent: redact | ||||
|           Authorization: drop | ||||
|           Content-Type: keep | ||||
|         User-Agent: redact | ||||
|         Authorization: drop | ||||
|         Content-Type: keep | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| @@ -229,6 +229,7 @@ accessLog: | ||||
|     | `RetryAttempts`         | The amount of attempts the request was retried.                                                                                                                     | | ||||
|     | `TLSVersion`            | The TLS version used by the connection (e.g. `1.2`) (if connection is TLS).                                                                                         | | ||||
|     | `TLSCipher`             | The TLS cipher used by the connection (e.g. `TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA`) (if connection is TLS)                                                           | | ||||
|     | `TLSClientSubject`      | The string representation of the TLS client certificate's Subject (e.g. `CN=username,O=organization`)                                                               | | ||||
|  | ||||
| ## Log Rotation | ||||
|  | ||||
| @@ -254,7 +255,7 @@ version: "3.7" | ||||
|  | ||||
| services: | ||||
|   traefik: | ||||
|     image: traefik:v2.10 | ||||
|     image: traefik:v3.0 | ||||
|     environment: | ||||
|       - TZ=US/Alaska | ||||
|     command: | ||||
|   | ||||
| @@ -66,7 +66,7 @@ log: | ||||
|  | ||||
| By default, the `level` is set to `ERROR`. | ||||
|  | ||||
| Alternative logging levels are `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL`, and `PANIC`. | ||||
| Alternative logging levels are `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL`, and `PANIC`. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| log: | ||||
| @@ -82,10 +82,101 @@ log: | ||||
| --log.level=DEBUG | ||||
| ``` | ||||
|  | ||||
| #### `noColor` | ||||
|  | ||||
| When using the 'common' format, disables the colorized output. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| log: | ||||
|   noColor: true | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [log] | ||||
|   noColor = true | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --log.nocolor=true | ||||
| ``` | ||||
|  | ||||
| ## Log Rotation | ||||
|  | ||||
| Traefik will close and reopen its log files, assuming they're configured, on receipt of a USR1 signal. | ||||
| This allows the logs to be rotated and processed by an external program, such as `logrotate`. | ||||
| The rotation of the log files can be configured with the following options. | ||||
|  | ||||
| !!! warning | ||||
|     This does not work on Windows due to the lack of USR signals. | ||||
| ### `maxSize` | ||||
|  | ||||
| `maxSize` is the maximum size in megabytes of the log file before it gets rotated. | ||||
| It defaults to 100 megabytes. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| log: | ||||
|   maxSize: 1 | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [log] | ||||
|   maxSize = 1 | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --log.maxsize=1 | ||||
| ``` | ||||
|  | ||||
| ### `maxBackups` | ||||
|  | ||||
| `maxBackups` is the maximum number of old log files to retain. | ||||
| The default is to retain all old log files (though `maxAge` may still cause them to get deleted). | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| log: | ||||
|   maxBackups: 3 | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [log] | ||||
|   maxBackups = 3 | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --log.maxbackups=3 | ||||
| ``` | ||||
|  | ||||
| ### `maxAge` | ||||
|  | ||||
| `maxAge` is the maximum number of days to retain old log files based on the timestamp encoded in their filename. | ||||
| Note that a day is defined as 24 hours and may not exactly correspond to calendar days due to daylight savings, leap seconds, etc. | ||||
| The default is not to remove old log files based on age. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| log: | ||||
|   maxAge: 3 | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [log] | ||||
|   maxAge = 3 | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --log.maxage=3 | ||||
| ``` | ||||
|  | ||||
| ### `compress` | ||||
|  | ||||
| `compress` determines if the rotated log files should be compressed using gzip. | ||||
| The default is not to perform compression. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| log: | ||||
|   compress: 3 | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [log] | ||||
|   compress = 3 | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --log.compress=3 | ||||
| ``` | ||||
|   | ||||
| @@ -1,268 +0,0 @@ | ||||
| --- | ||||
| title: "Traefik InfluxDB Documentation" | ||||
| description: "Traefik supports several metrics backends, including InfluxDB. Learn how to implement it for observability in Traefik Proxy. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # InfluxDB | ||||
|  | ||||
| To enable the InfluxDB: | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   influxDB: {} | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.influxDB] | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.influxdb=true | ||||
| ``` | ||||
|  | ||||
| #### `address` | ||||
|  | ||||
| _Required, Default="localhost:8089"_ | ||||
|  | ||||
| Address instructs exporter to send metrics to influxdb at this address. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   influxDB: | ||||
|     address: localhost:8089 | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.influxDB] | ||||
|     address = "localhost:8089" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.influxdb.address=localhost:8089 | ||||
| ``` | ||||
|  | ||||
| #### `protocol` | ||||
|  | ||||
| _Required, Default="udp"_ | ||||
|  | ||||
| InfluxDB's address protocol (udp or http). | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   influxDB: | ||||
|     protocol: udp | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.influxDB] | ||||
|     protocol = "udp" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.influxdb.protocol=udp | ||||
| ``` | ||||
|  | ||||
| #### `database` | ||||
|  | ||||
| _Optional, Default=""_ | ||||
|  | ||||
| InfluxDB database used when protocol is http. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   influxDB: | ||||
|     database: db | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.influxDB] | ||||
|     database = "db" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.influxdb.database=db | ||||
| ``` | ||||
|  | ||||
| #### `retentionPolicy` | ||||
|  | ||||
| _Optional, Default=""_ | ||||
|  | ||||
| InfluxDB retention policy used when protocol is http. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   influxDB: | ||||
|     retentionPolicy: two_hours | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.influxDB] | ||||
|     retentionPolicy = "two_hours" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.influxdb.retentionPolicy=two_hours | ||||
| ``` | ||||
|  | ||||
| #### `username` | ||||
|  | ||||
| _Optional, Default=""_ | ||||
|  | ||||
| InfluxDB username (only with http). | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   influxDB: | ||||
|     username: john | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.influxDB] | ||||
|     username = "john" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.influxdb.username=john | ||||
| ``` | ||||
|  | ||||
| #### `password` | ||||
|  | ||||
| _Optional, Default=""_ | ||||
|  | ||||
| InfluxDB password (only with http). | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   influxDB: | ||||
|     password: secret | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.influxDB] | ||||
|     password = "secret" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.influxdb.password=secret | ||||
| ``` | ||||
|  | ||||
| #### `addEntryPointsLabels` | ||||
|  | ||||
| _Optional, Default=true_ | ||||
|  | ||||
| Enable metrics on entry points. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   influxDB: | ||||
|     addEntryPointsLabels: true | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.influxDB] | ||||
|     addEntryPointsLabels = true | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.influxdb.addEntryPointsLabels=true | ||||
| ``` | ||||
|  | ||||
| #### `addRoutersLabels` | ||||
|  | ||||
| _Optional, Default=false_ | ||||
|  | ||||
| Enable metrics on routers. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   influxDB: | ||||
|     addRoutersLabels: true | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.influxDB] | ||||
|     addRoutersLabels = true | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.influxdb.addrouterslabels=true | ||||
| ``` | ||||
|  | ||||
| #### `addServicesLabels` | ||||
|  | ||||
| _Optional, Default=true_ | ||||
|  | ||||
| Enable metrics on services. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   influxDB: | ||||
|     addServicesLabels: true | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.influxDB] | ||||
|     addServicesLabels = true | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.influxdb.addServicesLabels=true | ||||
| ``` | ||||
|  | ||||
| #### `pushInterval` | ||||
|  | ||||
| _Optional, Default=10s_ | ||||
|  | ||||
| The interval used by the exporter to push metrics to influxdb. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   influxDB: | ||||
|     pushInterval: 10s | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.influxDB] | ||||
|     pushInterval = "10s" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.influxdb.pushInterval=10s | ||||
| ``` | ||||
|  | ||||
| #### `additionalLabels` | ||||
|  | ||||
| _Optional, Default={}_ | ||||
|  | ||||
| Additional labels (influxdb tags) on all metrics. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   influxDB: | ||||
|     additionalLabels: | ||||
|       host: example.com | ||||
|       environment: production | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.influxDB] | ||||
|     [metrics.influxDB.additionalLabels] | ||||
|       host = "example.com" | ||||
|       environment = "production" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.influxdb.additionallabels.host=example.com --metrics.influxdb.additionallabels.environment=production | ||||
| ``` | ||||
							
								
								
									
										353
									
								
								docs/content/observability/metrics/opentelemetry.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										353
									
								
								docs/content/observability/metrics/opentelemetry.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,353 @@ | ||||
| --- | ||||
| title: "Traefik OpenTelemetry Documentation" | ||||
| description: "Traefik supports several metrics backends, including OpenTelemetry. Learn how to implement it for observability in Traefik Proxy. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # OpenTelemetry | ||||
|  | ||||
| To enable the OpenTelemetry: | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   openTelemetry: {} | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.openTelemetry] | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.openTelemetry=true | ||||
| ``` | ||||
|  | ||||
| !!! info "The OpenTelemetry exporter will export metrics to the collector by using HTTP by default, see the [gRPC Section](#grpc-configuration) to use gRPC." | ||||
|  | ||||
| #### `address` | ||||
|  | ||||
| _Required, Default="localhost:4318", Format="`<host>:<port>`"_ | ||||
|  | ||||
| Address of the OpenTelemetry Collector to send metrics to. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   openTelemetry: | ||||
|     address: localhost:4318 | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.openTelemetry] | ||||
|     address = "localhost:4318" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.openTelemetry.address=localhost:4318 | ||||
| ``` | ||||
|  | ||||
| #### `addEntryPointsLabels` | ||||
|  | ||||
| _Optional, Default=true_ | ||||
|  | ||||
| Enable metrics on entry points. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   openTelemetry: | ||||
|     addEntryPointsLabels: true | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.openTelemetry] | ||||
|     addEntryPointsLabels = true | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.openTelemetry.addEntryPointsLabels=true | ||||
| ``` | ||||
|  | ||||
| #### `addRoutersLabels` | ||||
|  | ||||
| _Optional, Default=false_ | ||||
|  | ||||
| Enable metrics on routers. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   openTelemetry: | ||||
|     addRoutersLabels: true | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.openTelemetry] | ||||
|     addRoutersLabels = true | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.openTelemetry.addRoutersLabels=true | ||||
| ``` | ||||
|  | ||||
| #### `addServicesLabels` | ||||
|  | ||||
| _Optional, Default=true_ | ||||
|  | ||||
| Enable metrics on services. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   openTelemetry: | ||||
|     addServicesLabels: true | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.openTelemetry] | ||||
|     addServicesLabels = true | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.openTelemetry.addServicesLabels=true | ||||
| ``` | ||||
|  | ||||
| #### `explicitBoundaries` | ||||
|  | ||||
| _Optional, Default=".005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10"_ | ||||
|  | ||||
| Explicit boundaries for Histogram data points. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   openTelemetry: | ||||
|     explicitBoundaries: | ||||
|       - 0.1 | ||||
|       - 0.3 | ||||
|       - 1.2 | ||||
|       - 5.0 | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.openTelemetry] | ||||
|     explicitBoundaries = [0.1,0.3,1.2,5.0] | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.openTelemetry.explicitBoundaries=0.1,0.3,1.2,5.0 | ||||
| ``` | ||||
|  | ||||
| #### `headers` | ||||
|  | ||||
| _Optional, Default={}_ | ||||
|  | ||||
| Additional headers sent with metrics by the reporter to the OpenTelemetry Collector. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   openTelemetry: | ||||
|     headers: | ||||
|       foo: bar | ||||
|       baz: buz | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.openTelemetry.headers] | ||||
|     foo = "bar" | ||||
|     baz = "buz" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.openTelemetry.headers.foo=bar --metrics.openTelemetry.headers.baz=buz | ||||
| ``` | ||||
|  | ||||
| #### `insecure` | ||||
|  | ||||
| _Optional, Default=false_ | ||||
|  | ||||
| Allows reporter to send metrics to the OpenTelemetry Collector without using a secured protocol. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   openTelemetry: | ||||
|     insecure: true | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.openTelemetry] | ||||
|     insecure = true | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.openTelemetry.insecure=true | ||||
| ``` | ||||
|  | ||||
| #### `pushInterval` | ||||
|  | ||||
| _Optional, Default=10s_ | ||||
|  | ||||
| Interval at which metrics are sent to the OpenTelemetry Collector. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   openTelemetry: | ||||
|     pushInterval: 10s | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.openTelemetry] | ||||
|     pushInterval = "10s" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.openTelemetry.pushInterval=10s | ||||
| ``` | ||||
|  | ||||
| #### `path` | ||||
|  | ||||
| _Required, Default="/v1/metrics"_ | ||||
|  | ||||
| Allows to override the default URL path used for sending metrics. | ||||
| This option has no effect when using gRPC transport. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   openTelemetry: | ||||
|     path: /foo/v1/metrics | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.openTelemetry] | ||||
|     path = "/foo/v1/metrics" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.openTelemetry.path=/foo/v1/metrics | ||||
| ``` | ||||
|  | ||||
| #### `tls` | ||||
|  | ||||
| _Optional_ | ||||
|  | ||||
| Defines the TLS configuration used by the reporter to send metrics to the OpenTelemetry Collector. | ||||
|  | ||||
| ##### `ca` | ||||
|  | ||||
| _Optional_ | ||||
|  | ||||
| `ca` is the path to the certificate authority used for the secure connection to the OpenTelemetry Collector, | ||||
| it defaults to the system bundle. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   openTelemetry: | ||||
|     tls: | ||||
|       ca: path/to/ca.crt | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics.openTelemetry.tls] | ||||
|   ca = "path/to/ca.crt" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.openTelemetry.tls.ca=path/to/ca.crt | ||||
| ``` | ||||
|  | ||||
| ##### `cert` | ||||
|  | ||||
| _Optional_ | ||||
|  | ||||
| `cert` is the path to the public certificate used for the secure connection to the OpenTelemetry Collector. | ||||
| When using this option, setting the `key` option is required. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   openTelemetry: | ||||
|     tls: | ||||
|       cert: path/to/foo.cert | ||||
|       key: path/to/foo.key | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics.openTelemetry.tls] | ||||
|   cert = "path/to/foo.cert" | ||||
|   key = "path/to/foo.key" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.openTelemetry.tls.cert=path/to/foo.cert | ||||
| --metrics.openTelemetry.tls.key=path/to/foo.key | ||||
| ``` | ||||
|  | ||||
| ##### `key` | ||||
|  | ||||
| _Optional_ | ||||
|  | ||||
| `key` is the path to the private key used for the secure connection to the OpenTelemetry Collector. | ||||
| When using this option, setting the `cert` option is required. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   openTelemetry: | ||||
|     tls: | ||||
|       cert: path/to/foo.cert | ||||
|       key: path/to/foo.key | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics.openTelemetry.tls] | ||||
|   cert = "path/to/foo.cert" | ||||
|   key = "path/to/foo.key" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.openTelemetry.tls.cert=path/to/foo.cert | ||||
| --metrics.openTelemetry.tls.key=path/to/foo.key | ||||
| ``` | ||||
|  | ||||
| ##### `insecureSkipVerify` | ||||
|  | ||||
| _Optional, Default=false_ | ||||
|  | ||||
| If `insecureSkipVerify` is `true`, | ||||
| the TLS connection to the OpenTelemetry Collector accepts any certificate presented by the server regardless of the hostnames it covers. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   openTelemetry: | ||||
|     tls: | ||||
|       insecureSkipVerify: true | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics.openTelemetry.tls] | ||||
|   insecureSkipVerify = true | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.openTelemetry.tls.insecureSkipVerify=true | ||||
| ``` | ||||
|  | ||||
| #### gRPC configuration | ||||
|  | ||||
| This instructs the reporter to send metrics to the OpenTelemetry Collector using gRPC. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| metrics: | ||||
|   openTelemetry: | ||||
|     grpc: {} | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [metrics] | ||||
|   [metrics.openTelemetry.grpc] | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --metrics.openTelemetry.grpc=true | ||||
| ``` | ||||
| @@ -1,6 +1,6 @@ | ||||
| --- | ||||
| title: "Traefik Metrics Overview" | ||||
| description: "Traefik Proxy supports these metrics backend systems: Datadog, InfluxDB, Prometheus, and StatsD. Read the full documentation to get started." | ||||
| description: "Traefik Proxy supports these metrics backend systems: Datadog, InfluxDB 2.X, Prometheus, and StatsD. Read the full documentation to get started." | ||||
| --- | ||||
|  | ||||
| # Metrics | ||||
| @@ -8,34 +8,39 @@ description: "Traefik Proxy supports these metrics backend systems: Datadog, Inf | ||||
| Traefik supports these metrics backends: | ||||
|  | ||||
| - [Datadog](./datadog.md) | ||||
| - [InfluxDB](./influxdb.md) | ||||
| - [InfluxDB2](./influxdb2.md) | ||||
| - [Prometheus](./prometheus.md) | ||||
| - [StatsD](./statsd.md) | ||||
|  | ||||
| Traefik Proxy hosts an official Grafana dashboard for both [on-premises](https://grafana.com/grafana/dashboards/17346) and [Kubernetes](https://grafana.com/grafana/dashboards/17347) deployments. | ||||
|  | ||||
| ## Global Metrics | ||||
|  | ||||
| | Metric                                      | Type    | Description                                             | | ||||
| |---------------------------------------------|---------|---------------------------------------------------------| | ||||
| | Config reload total                         | Count   | The total count of configuration reloads.               | | ||||
| | Config reload last success                  | Gauge   | The timestamp of the last configuration reload success. | | ||||
| | TLS certificates not after                  | Gauge   | The expiration date of certificates.                    | | ||||
| | Metric                     | Type  | [Labels](#labels)        | Description                                                        | | ||||
| |----------------------------|-------|--------------------------|--------------------------------------------------------------------| | ||||
| | Config reload total        | Count |                          | The total count of configuration reloads.                          | | ||||
| | Config reload last success | Gauge |                          | The timestamp of the last configuration reload success.            | | ||||
| | Open connections           | Gauge | `entrypoint`, `protocol` | The current count of open connections, by entrypoint and protocol. | | ||||
| | TLS certificates not after | Gauge |                          | The expiration date of certificates.                               | | ||||
|  | ||||
| ```prom tab="Prometheus" | ||||
| traefik_config_reloads_total | ||||
| traefik_config_last_reload_success | ||||
| traefik_open_connections | ||||
| traefik_tls_certs_not_after | ||||
| ``` | ||||
|  | ||||
| ```dd tab="Datadog" | ||||
| config.reload.total | ||||
| config.reload.lastSuccessTimestamp | ||||
| open.connections | ||||
| tls.certs.notAfterTimestamp | ||||
| ``` | ||||
|  | ||||
| ```influxdb tab="InfluxDB / InfluxDB2" | ||||
| ```influxdb tab="InfluxDB2" | ||||
| traefik.config.reload.total | ||||
| traefik.config.reload.lastSuccessTimestamp | ||||
| traefik.open.connections | ||||
| traefik.tls.certs.notAfterTimestamp | ||||
| ``` | ||||
|  | ||||
| @@ -43,17 +48,35 @@ traefik.tls.certs.notAfterTimestamp | ||||
| # Default prefix: "traefik" | ||||
| {prefix}.config.reload.total | ||||
| {prefix}.config.reload.lastSuccessTimestamp | ||||
| {prefix}.open.connections | ||||
| {prefix}.tls.certs.notAfterTimestamp | ||||
| ``` | ||||
|  | ||||
| ## EntryPoint Metrics | ||||
| ```opentelemetry tab="OpenTelemetry" | ||||
| traefik_config_reloads_total | ||||
| traefik_config_last_reload_success | ||||
| traefik_open_connections | ||||
| traefik_tls_certs_not_after | ||||
| ``` | ||||
|  | ||||
| ### Labels | ||||
|  | ||||
| Here is a comprehensive list of labels that are provided by the global metrics: | ||||
|  | ||||
| | Label         | Description                            | example              | | ||||
| |---------------|----------------------------------------|----------------------| | ||||
| | `entrypoint`  | Entrypoint that handled the connection | "example_entrypoint" | | ||||
| | `protocol`    | Connection protocol                    | "TCP"                | | ||||
|  | ||||
| ## HTTP Metrics | ||||
|  | ||||
| ### EntryPoint Metrics | ||||
|  | ||||
| | Metric                | Type      | [Labels](#labels)                          | Description                                                         | | ||||
| |-----------------------|-----------|--------------------------------------------|---------------------------------------------------------------------| | ||||
| | Requests total        | Count     | `code`, `method`, `protocol`, `entrypoint` | The total count of HTTP requests received by an entrypoint.         | | ||||
| | Requests TLS total    | Count     | `tls_version`, `tls_cipher`, `entrypoint`  | The total count of HTTPS requests received by an entrypoint.        | | ||||
| | Request duration      | Histogram | `code`, `method`, `protocol`, `entrypoint` | Request processing duration histogram on an entrypoint.             | | ||||
| | Open connections      | Count     | `method`, `protocol`, `entrypoint`         | The current count of open connections on an entrypoint.             | | ||||
| | Requests bytes total  | Count     | `code`, `method`, `protocol`, `entrypoint` | The total size of HTTP requests in bytes handled by an entrypoint.  | | ||||
| | Responses bytes total | Count     | `code`, `method`, `protocol`, `entrypoint` | The total size of HTTP responses in bytes handled by an entrypoint. | | ||||
|  | ||||
| @@ -61,7 +84,6 @@ traefik.tls.certs.notAfterTimestamp | ||||
| traefik_entrypoint_requests_total | ||||
| traefik_entrypoint_requests_tls_total | ||||
| traefik_entrypoint_request_duration_seconds | ||||
| traefik_entrypoint_open_connections | ||||
| traefik_entrypoint_requests_bytes_total | ||||
| traefik_entrypoint_responses_bytes_total | ||||
| ``` | ||||
| @@ -70,16 +92,14 @@ traefik_entrypoint_responses_bytes_total | ||||
| entrypoint.request.total | ||||
| entrypoint.request.tls.total | ||||
| entrypoint.request.duration | ||||
| entrypoint.connections.open | ||||
| entrypoint.requests.bytes.total | ||||
| entrypoint.responses.bytes.total | ||||
| ``` | ||||
|  | ||||
| ```influxdb tab="InfluxDB / InfluxDB2" | ||||
| ```influxdb tab="InfluxDB2" | ||||
| traefik.entrypoint.requests.total | ||||
| traefik.entrypoint.requests.tls.total | ||||
| traefik.entrypoint.request.duration | ||||
| traefik.entrypoint.connections.open | ||||
| traefik.entrypoint.requests.bytes.total | ||||
| traefik.entrypoint.responses.bytes.total | ||||
| ``` | ||||
| @@ -89,19 +109,25 @@ traefik.entrypoint.responses.bytes.total | ||||
| {prefix}.entrypoint.request.total | ||||
| {prefix}.entrypoint.request.tls.total | ||||
| {prefix}.entrypoint.request.duration | ||||
| {prefix}.entrypoint.connections.open | ||||
| {prefix}.entrypoint.requests.bytes.total | ||||
| {prefix}.entrypoint.responses.bytes.total | ||||
| ``` | ||||
|  | ||||
| ## Router Metrics | ||||
| ```opentelemetry tab="OpenTelemetry" | ||||
| traefik_entrypoint_requests_total | ||||
| traefik_entrypoint_requests_tls_total | ||||
| traefik_entrypoint_request_duration_seconds | ||||
| traefik_entrypoint_requests_bytes_total | ||||
| traefik_entrypoint_responses_bytes_total | ||||
| ``` | ||||
|  | ||||
| ### Router Metrics | ||||
|  | ||||
| | Metric                | Type      | [Labels](#labels)                                 | Description                                                    | | ||||
| |-----------------------|-----------|---------------------------------------------------|----------------------------------------------------------------| | ||||
| | Requests total        | Count     | `code`, `method`, `protocol`, `router`, `service` | The total count of HTTP requests handled by a router.          | | ||||
| | Requests TLS total    | Count     | `tls_version`, `tls_cipher`, `router`, `service`  | The total count of HTTPS requests handled by a router.         | | ||||
| | Request duration      | Histogram | `code`, `method`, `protocol`, `router`, `service` | Request processing duration histogram on a router.             | | ||||
| | Open connections      | Count     | `method`, `protocol`, `router`, `service`         | The current count of open connections on a router.             | | ||||
| | Requests bytes total  | Count     | `code`, `method`, `protocol`, `router`, `service` | The total size of HTTP requests in bytes handled by a router.  | | ||||
| | Responses bytes total | Count     | `code`, `method`, `protocol`, `router`, `service` | The total size of HTTP responses in bytes handled by a router. | | ||||
|  | ||||
| @@ -109,7 +135,6 @@ traefik.entrypoint.responses.bytes.total | ||||
| traefik_router_requests_total | ||||
| traefik_router_requests_tls_total | ||||
| traefik_router_request_duration_seconds | ||||
| traefik_router_open_connections | ||||
| traefik_router_requests_bytes_total | ||||
| traefik_router_responses_bytes_total | ||||
| ``` | ||||
| @@ -118,16 +143,14 @@ traefik_router_responses_bytes_total | ||||
| router.request.total | ||||
| router.request.tls.total | ||||
| router.request.duration | ||||
| router.connections.open | ||||
| router.requests.bytes.total | ||||
| router.responses.bytes.total | ||||
| ``` | ||||
|  | ||||
| ```influxdb tab="InfluxDB / InfluxDB2" | ||||
| ```influxdb tab="InfluxDB2" | ||||
| traefik.router.requests.total | ||||
| traefik.router.requests.tls.total | ||||
| traefik.router.request.duration | ||||
| traefik.router.connections.open | ||||
| traefik.router.requests.bytes.total | ||||
| traefik.router.responses.bytes.total | ||||
| ``` | ||||
| @@ -137,19 +160,25 @@ traefik.router.responses.bytes.total | ||||
| {prefix}.router.request.total | ||||
| {prefix}.router.request.tls.total | ||||
| {prefix}.router.request.duration | ||||
| {prefix}.router.connections.open | ||||
| {prefix}.router.requests.bytes.total | ||||
| {prefix}.router.responses.bytes.total | ||||
| ``` | ||||
|  | ||||
| ## Service Metrics | ||||
| ```opentelemetry tab="OpenTelemetry" | ||||
| traefik_router_requests_total | ||||
| traefik_router_requests_tls_total | ||||
| traefik_router_request_duration_seconds | ||||
| traefik_router_requests_bytes_total | ||||
| traefik_router_responses_bytes_total | ||||
| ``` | ||||
|  | ||||
| ### Service Metrics | ||||
|  | ||||
| | Metric                | Type      | Labels                                  | Description                                                 | | ||||
| |-----------------------|-----------|-----------------------------------------|-------------------------------------------------------------| | ||||
| | Requests total        | Count     | `code`, `method`, `protocol`, `service` | The total count of HTTP requests processed on a service.    | | ||||
| | Requests TLS total    | Count     | `tls_version`, `tls_cipher`, `service`  | The total count of HTTPS requests processed on a service.   | | ||||
| | Request duration      | Histogram | `code`, `method`, `protocol`, `service` | Request processing duration histogram on a service.         | | ||||
| | Open connections      | Count     | `method`, `protocol`, `service`         | The current count of open connections on a service.         | | ||||
| | Retries total         | Count     | `service`                               | The count of requests retries on a service.                 | | ||||
| | Server UP             | Gauge     | `service`, `url`                        | Current service's server status, 0 for a down or 1 for up.  | | ||||
| | Requests bytes total  | Count     | `code`, `method`, `protocol`, `service` | The total size of requests in bytes received by a service.  | | ||||
| @@ -159,7 +188,6 @@ traefik.router.responses.bytes.total | ||||
| traefik_service_requests_total | ||||
| traefik_service_requests_tls_total | ||||
| traefik_service_request_duration_seconds | ||||
| traefik_service_open_connections | ||||
| traefik_service_retries_total | ||||
| traefik_service_server_up | ||||
| traefik_service_requests_bytes_total | ||||
| @@ -170,18 +198,16 @@ traefik_service_responses_bytes_total | ||||
| service.request.total | ||||
| router.service.tls.total | ||||
| service.request.duration | ||||
| service.connections.open | ||||
| service.retries.total | ||||
| service.server.up | ||||
| service.requests.bytes.total | ||||
| service.responses.bytes.total | ||||
| ``` | ||||
|  | ||||
| ```influxdb tab="InfluxDB / InfluxDB2" | ||||
| ```influxdb tab="InfluxDB2" | ||||
| traefik.service.requests.total | ||||
| traefik.service.requests.tls.total | ||||
| traefik.service.request.duration | ||||
| traefik.service.connections.open | ||||
| traefik.service.retries.total | ||||
| traefik.service.server.up | ||||
| traefik.service.requests.bytes.total | ||||
| @@ -193,14 +219,23 @@ traefik.service.responses.bytes.total | ||||
| {prefix}.service.request.total | ||||
| {prefix}.service.request.tls.total | ||||
| {prefix}.service.request.duration | ||||
| {prefix}.service.connections.open | ||||
| {prefix}.service.retries.total | ||||
| {prefix}.service.server.up | ||||
| {prefix}.service.requests.bytes.total | ||||
| {prefix}.service.responses.bytes.total | ||||
| ``` | ||||
|  | ||||
| ## Labels | ||||
| ```opentelemetry tab="OpenTelemetry" | ||||
| traefik_service_requests_total | ||||
| traefik_service_requests_tls_total | ||||
| traefik_service_request_duration_seconds | ||||
| traefik_service_retries_total | ||||
| traefik_service_server_up | ||||
| traefik_service_requests_bytes_total | ||||
| traefik_service_responses_bytes_total | ||||
| ``` | ||||
|  | ||||
| ### Labels | ||||
|  | ||||
| Here is a comprehensive list of labels that are provided by the metrics: | ||||
|  | ||||
|   | ||||
| @@ -87,30 +87,6 @@ tracing: | ||||
| --tracing.datadog.debug=true | ||||
| ``` | ||||
|  | ||||
| #### `globalTag` | ||||
|  | ||||
| ??? warning "Deprecated in favor of the [`globalTags`](#globaltags) option." | ||||
|  | ||||
|     _Optional, Default=empty_ | ||||
|      | ||||
|     Applies a shared key:value tag on all spans. | ||||
|      | ||||
|     ```yaml tab="File (YAML)" | ||||
|     tracing: | ||||
|       datadog: | ||||
|         globalTag: sample | ||||
|     ``` | ||||
|      | ||||
|     ```toml tab="File (TOML)" | ||||
|     [tracing] | ||||
|       [tracing.datadog] | ||||
|         globalTag = "sample" | ||||
|     ``` | ||||
|      | ||||
|     ```bash tab="CLI" | ||||
|     --tracing.datadog.globalTag=sample | ||||
|     ``` | ||||
|  | ||||
| #### `globalTags` | ||||
|  | ||||
| _Optional, Default=empty_ | ||||
|   | ||||
							
								
								
									
										246
									
								
								docs/content/observability/tracing/opentelemetry.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										246
									
								
								docs/content/observability/tracing/opentelemetry.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,246 @@ | ||||
| --- | ||||
| title: "Traefik OpenTelemetry Documentation" | ||||
| description: "Traefik supports several tracing backends, including OpenTelemetry. Learn how to implement it for observability in Traefik Proxy. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # OpenTelemetry | ||||
|  | ||||
| To enable the OpenTelemetry tracer: | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| tracing: | ||||
|   openTelemetry: {} | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [tracing] | ||||
|   [tracing.openTelemetry] | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --tracing.openTelemetry=true | ||||
| ``` | ||||
|  | ||||
| !!! info "The OpenTelemetry trace reporter will export traces to the collector using HTTP by default, see the [gRPC Section](#grpc-configuration) to use gRPC." | ||||
|  | ||||
| !!! info "Trace sampling" | ||||
|  | ||||
| 	By default, the OpenTelemetry trace reporter will sample 100% of traces. | ||||
| 	See [OpenTelemetry's SDK configuration](https://opentelemetry.io/docs/reference/specification/sdk-environment-variables/#general-sdk-configuration) to customize the sampling strategy. | ||||
|  | ||||
| #### `address` | ||||
|  | ||||
| _Required, Default="localhost:4318", Format="`<host>:<port>`"_ | ||||
|  | ||||
| Address of the OpenTelemetry Collector to send spans to. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| tracing: | ||||
|   openTelemetry: | ||||
|     address: localhost:4318 | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [tracing] | ||||
|   [tracing.openTelemetry] | ||||
|     address = "localhost:4318" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --tracing.openTelemetry.address=localhost:4318 | ||||
| ``` | ||||
|  | ||||
| #### `headers` | ||||
|  | ||||
| _Optional, Default={}_ | ||||
|  | ||||
| Additional headers sent with spans by the reporter to the OpenTelemetry Collector. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| tracing: | ||||
|   openTelemetry: | ||||
|     headers: | ||||
|       foo: bar | ||||
|       baz: buz | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [tracing] | ||||
|   [tracing.openTelemetry.headers] | ||||
|     foo = "bar" | ||||
|     baz = "buz" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --tracing.openTelemetry.headers.foo=bar --tracing.openTelemetry.headers.baz=buz | ||||
| ``` | ||||
|  | ||||
| #### `insecure` | ||||
|  | ||||
| _Optional, Default=false_ | ||||
|  | ||||
| Allows reporter to send spans to the OpenTelemetry Collector without using a secured protocol. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| tracing: | ||||
|   openTelemetry: | ||||
|     insecure: true | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [tracing] | ||||
|   [tracing.openTelemetry] | ||||
|     insecure = true | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --tracing.openTelemetry.insecure=true | ||||
| ``` | ||||
|  | ||||
| #### `path` | ||||
|  | ||||
| _Required, Default="/v1/traces"_ | ||||
|  | ||||
| Allows to override the default URL path used for sending traces. | ||||
| This option has no effect when using gRPC transport. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| tracing: | ||||
|   openTelemetry: | ||||
|     path: /foo/v1/traces | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [tracing] | ||||
|   [tracing.openTelemetry] | ||||
|     path = "/foo/v1/traces" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --tracing.openTelemetry.path=/foo/v1/traces | ||||
| ``` | ||||
|  | ||||
| #### `tls` | ||||
|  | ||||
| _Optional_ | ||||
|  | ||||
| Defines the TLS configuration used by the reporter to send spans to the OpenTelemetry Collector. | ||||
|  | ||||
| ##### `ca` | ||||
|  | ||||
| _Optional_ | ||||
|  | ||||
| `ca` is the path to the certificate authority used for the secure connection to the OpenTelemetry Collector, | ||||
| it defaults to the system bundle. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| tracing: | ||||
|   openTelemetry: | ||||
|     tls: | ||||
|       ca: path/to/ca.crt | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [tracing.openTelemetry.tls] | ||||
|   ca = "path/to/ca.crt" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --tracing.openTelemetry.tls.ca=path/to/ca.crt | ||||
| ``` | ||||
|  | ||||
| ##### `cert` | ||||
|  | ||||
| _Optional_ | ||||
|  | ||||
| `cert` is the path to the public certificate used for the secure connection to the OpenTelemetry Collector. | ||||
| When using this option, setting the `key` option is required. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| tracing: | ||||
|   openTelemetry: | ||||
|     tls: | ||||
|       cert: path/to/foo.cert | ||||
|       key: path/to/foo.key | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [tracing.openTelemetry.tls] | ||||
|   cert = "path/to/foo.cert" | ||||
|   key = "path/to/foo.key" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --tracing.openTelemetry.tls.cert=path/to/foo.cert | ||||
| --tracing.openTelemetry.tls.key=path/to/foo.key | ||||
| ``` | ||||
|  | ||||
| ##### `key` | ||||
|  | ||||
| _Optional_ | ||||
|  | ||||
| `key` is the path to the private key used for the secure connection to the OpenTelemetry Collector. | ||||
| When using this option, setting the `cert` option is required. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| tracing: | ||||
|   openTelemetry: | ||||
|     tls: | ||||
|       cert: path/to/foo.cert | ||||
|       key: path/to/foo.key | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [tracing.openTelemetry.tls] | ||||
|   cert = "path/to/foo.cert" | ||||
|   key = "path/to/foo.key" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --tracing.openTelemetry.tls.cert=path/to/foo.cert | ||||
| --tracing.openTelemetry.tls.key=path/to/foo.key | ||||
| ``` | ||||
|  | ||||
| ##### `insecureSkipVerify` | ||||
|  | ||||
| _Optional, Default=false_ | ||||
|  | ||||
| If `insecureSkipVerify` is `true`, | ||||
| the TLS connection to the OpenTelemetry Collector accepts any certificate presented by the server regardless of the hostnames it covers. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| tracing: | ||||
|   openTelemetry: | ||||
|     tls: | ||||
|       insecureSkipVerify: true | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [tracing.openTelemetry.tls] | ||||
|   insecureSkipVerify = true | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --tracing.openTelemetry.tls.insecureSkipVerify=true | ||||
| ``` | ||||
|  | ||||
| #### gRPC configuration | ||||
|  | ||||
| _Optional_ | ||||
|  | ||||
| This instructs the reporter to send spans to the OpenTelemetry Collector using gRPC. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| tracing: | ||||
|   openTelemetry: | ||||
|     grpc: {} | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [tracing] | ||||
|   [tracing.openTelemetry.grpc] | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --tracing.openTelemetry.grpc=true | ||||
| ``` | ||||
| @@ -12,7 +12,7 @@ The tracing system allows developers to visualize call flows in their infrastruc | ||||
|  | ||||
| Traefik uses OpenTracing, an open standard designed for distributed tracing. | ||||
|  | ||||
| Traefik supports six tracing backends: | ||||
| Traefik supports seven tracing backends: | ||||
|  | ||||
| - [Jaeger](./jaeger.md) | ||||
| - [Zipkin](./zipkin.md) | ||||
| @@ -20,6 +20,7 @@ Traefik supports six tracing backends: | ||||
| - [Instana](./instana.md) | ||||
| - [Haystack](./haystack.md) | ||||
| - [Elastic](./elastic.md) | ||||
| - [OpenTelemetry](./opentelemetry.md) | ||||
|  | ||||
| ## Configuration | ||||
|  | ||||
|   | ||||
| @@ -72,7 +72,7 @@ to allow defining: | ||||
|  | ||||
| - One or more security features through [middlewares](../middlewares/overview.md) | ||||
|   like authentication ([basicAuth](../middlewares/http/basicauth.md) , [digestAuth](../middlewares/http/digestauth.md), | ||||
|   [forwardAuth](../middlewares/http/forwardauth.md)) or [whitelisting](../middlewares/http/ipwhitelist.md). | ||||
|   [forwardAuth](../middlewares/http/forwardauth.md)) or [allowlisting](../middlewares/http/ipallowlist.md). | ||||
|  | ||||
| - A [router rule](#dashboard-router-rule) for accessing the dashboard, | ||||
|   through Traefik itself (sometimes referred as "Traefik-ception"). | ||||
| @@ -93,12 +93,12 @@ rule = "Host(`traefik.example.com`)" | ||||
|  | ||||
| ```bash tab="Path Prefix Rule" | ||||
| # The dashboard can be accessed on http://example.com/dashboard/ or http://traefik.example.com/dashboard/ | ||||
| rule = "PathPrefix(`/api`, `/dashboard`)" | ||||
| rule = "PathPrefix(`/api`) || PathPrefix(`/dashboard`)" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="Combination of Rules" | ||||
| # The dashboard can be accessed on http://traefik.example.com/dashboard/ | ||||
| rule = "Host(`traefik.example.com`) && PathPrefix(`/api`, `/dashboard`)" | ||||
| rule = "Host(`traefik.example.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))" | ||||
| ``` | ||||
|  | ||||
| ??? example "Dashboard Dynamic Configuration Examples" | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Dynamic Configuration | ||||
| labels: | ||||
|   - "traefik.http.routers.api.rule=Host(`traefik.example.com`)" | ||||
| @@ -51,24 +51,6 @@ spec: | ||||
| - "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.example.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.example.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="File (YAML)" | ||||
| # Dynamic Configuration | ||||
| http: | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Dynamic Configuration | ||||
| labels: | ||||
|   - "traefik.http.routers.dashboard.rule=Host(`traefik.example.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))" | ||||
| @@ -51,24 +51,6 @@ spec: | ||||
| - "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.routers.dashboard.rule": "Host(`traefik.example.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))", | ||||
|   "traefik.http.routers.dashboard.service": "api@internal", | ||||
|   "traefik.http.routers.dashboard.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.dashboard.rule=Host(`traefik.example.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))" | ||||
|   - "traefik.http.routers.dashboard.service=api@internal" | ||||
|   - "traefik.http.routers.dashboard.middlewares=auth" | ||||
|   - "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Dynamic Configuration | ||||
| http: | ||||
|   | ||||
| @@ -667,41 +667,6 @@ providers: | ||||
|  | ||||
| For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery). | ||||
|  | ||||
| ### `namespace` | ||||
|  | ||||
| ??? warning "Deprecated in favor of the [`namespaces`](#namespaces) option." | ||||
|  | ||||
|     _Optional, Default=""_ | ||||
|      | ||||
|     The `namespace` option defines the namespace in which the consul catalog services will be discovered. | ||||
|      | ||||
|     !!! warning | ||||
|      | ||||
|         The namespace option only works with [Consul Enterprise](https://www.consul.io/docs/enterprise), | ||||
|         which provides the [Namespaces](https://www.consul.io/docs/enterprise/namespaces) feature. | ||||
|      | ||||
|     !!! warning | ||||
|      | ||||
|         One should only define either the `namespaces` option or the `namespace` option. | ||||
|      | ||||
|     ```yaml tab="File (YAML)" | ||||
|     providers: | ||||
|       consulCatalog: | ||||
|         namespace: "production"  | ||||
|         # ... | ||||
|     ``` | ||||
|      | ||||
|     ```toml tab="File (TOML)" | ||||
|     [providers.consulCatalog] | ||||
|       namespace = "production" | ||||
|       # ... | ||||
|     ``` | ||||
|      | ||||
|     ```bash tab="CLI" | ||||
|     --providers.consulcatalog.namespace=production | ||||
|     # ... | ||||
|     ``` | ||||
|  | ||||
| ### `namespaces` | ||||
|  | ||||
| _Optional, Default=""_ | ||||
|   | ||||
| @@ -59,40 +59,6 @@ providers: | ||||
| --providers.consul.rootkey=traefik | ||||
| ``` | ||||
|  | ||||
| ### `namespace` | ||||
|  | ||||
| ??? warning "Deprecated in favor of the [`namespaces`](#namespaces) option." | ||||
|  | ||||
|     _Optional, Default=""_ | ||||
|      | ||||
|     The `namespace` option defines the namespace to query. | ||||
|      | ||||
|     !!! warning | ||||
|      | ||||
|         The namespace option only works with [Consul Enterprise](https://www.consul.io/docs/enterprise), | ||||
|         which provides the [Namespaces](https://www.consul.io/docs/enterprise/namespaces) feature. | ||||
|      | ||||
|     !!! warning | ||||
|      | ||||
|         One should only define either the `namespaces` option or the `namespace` option. | ||||
|      | ||||
|     ```yaml tab="File (YAML)" | ||||
|     providers: | ||||
|       consul: | ||||
|         # ... | ||||
|         namespace: "production" | ||||
|     ``` | ||||
|      | ||||
|     ```toml tab="File (TOML)" | ||||
|     [providers.consul] | ||||
|       # ... | ||||
|       namespace = "production" | ||||
|     ``` | ||||
|      | ||||
|     ```bash tab="CLI" | ||||
|     --providers.consul.namespace=production | ||||
|     ``` | ||||
|  | ||||
| ### `namespaces` | ||||
|  | ||||
| _Optional, Default=""_ | ||||
|   | ||||
| @@ -12,8 +12,7 @@ A Story of Labels & Containers | ||||
|  | ||||
| Attach labels to your containers and let Traefik do the rest! | ||||
|  | ||||
| Traefik works with both [Docker (standalone) Engine](https://docs.docker.com/engine/) | ||||
| and [Docker Swarm Mode](https://docs.docker.com/engine/swarm/). | ||||
| This provider works with [Docker (standalone) Engine](https://docs.docker.com/engine/). | ||||
|  | ||||
| !!! tip "The Quick Start Uses Docker" | ||||
|  | ||||
| @@ -49,49 +48,6 @@ and [Docker Swarm Mode](https://docs.docker.com/engine/swarm/). | ||||
|           - traefik.http.routers.my-container.rule=Host(`example.com`) | ||||
|     ``` | ||||
|  | ||||
| ??? example "Configuring Docker Swarm & Deploying / Exposing Services" | ||||
|  | ||||
|     Enabling the docker provider (Swarm Mode) | ||||
|  | ||||
|     ```yaml tab="File (YAML)" | ||||
|     providers: | ||||
|       docker: | ||||
|         # swarm classic (1.12-) | ||||
|         # endpoint: "tcp://127.0.0.1:2375" | ||||
|         # docker swarm mode (1.12+) | ||||
|         endpoint: "tcp://127.0.0.1:2377" | ||||
|         swarmMode: true | ||||
|     ``` | ||||
|  | ||||
|     ```toml tab="File (TOML)" | ||||
|     [providers.docker] | ||||
|       # swarm classic (1.12-) | ||||
|       # endpoint = "tcp://127.0.0.1:2375" | ||||
|       # docker swarm mode (1.12+) | ||||
|       endpoint = "tcp://127.0.0.1:2377" | ||||
|       swarmMode = true | ||||
|     ``` | ||||
|  | ||||
|     ```bash tab="CLI" | ||||
|     # swarm classic (1.12-) | ||||
|     # --providers.docker.endpoint=tcp://127.0.0.1:2375 | ||||
|     # docker swarm mode (1.12+) | ||||
|     --providers.docker.endpoint=tcp://127.0.0.1:2377 | ||||
|     --providers.docker.swarmMode=true | ||||
|     ``` | ||||
|  | ||||
|     Attach labels to services (not to containers) while in Swarm mode (in your docker compose file) | ||||
|  | ||||
|     ```yaml | ||||
|     version: "3" | ||||
|     services: | ||||
|       my-container: | ||||
|         deploy: | ||||
|           labels: | ||||
|             - traefik.http.routers.my-container.rule=Host(`example.com`) | ||||
|             - traefik.http.services.my-container-service.loadbalancer.server.port=8080 | ||||
|     ``` | ||||
|  | ||||
| ## Routing Configuration | ||||
|  | ||||
| When using Docker as a [provider](./overview.md), | ||||
| @@ -124,14 +80,13 @@ Port detection works as follows: | ||||
| - If a container [exposes](https://docs.docker.com/engine/reference/builder/#expose) multiple ports, | ||||
|   or does not expose any port, then you must manually specify which port Traefik should use for communication | ||||
|   by using the label `traefik.http.services.<service_name>.loadbalancer.server.port` | ||||
|   (Read more on this label in the dedicated section in [routing](../routing/providers/docker.md#port)). | ||||
|   (Read more on this label in the dedicated section in [routing](../routing/providers/docker.md#services)). | ||||
|  | ||||
| ### Host networking | ||||
|  | ||||
| When exposing containers that are configured with [host networking](https://docs.docker.com/network/host/), | ||||
| the IP address of the host is resolved as follows: | ||||
|  | ||||
| <!-- TODO: verify and document the swarm mode case with container.Node.IPAddress coming from the API --> | ||||
| - try a lookup of `host.docker.internal` | ||||
| - if the lookup was unsuccessful, try a lookup of `host.containers.internal`, ([Podman](https://docs.podman.io/en/latest/) equivalent of `host.docker.internal`) | ||||
| - if that lookup was also unsuccessful, fall back to `127.0.0.1` | ||||
| @@ -175,7 +130,6 @@ You can specify which Docker API Endpoint to use with the directive [`endpoint`] | ||||
|         - Authorization with the [Docker Authorization Plugin Mechanism](https://web.archive.org/web/20190920092526/https://docs.docker.com/engine/extend/plugins_authorization/) | ||||
|         - Accounting at networking level, by exposing the socket only inside a Docker private network, only available for Traefik. | ||||
|         - Accounting at container level, by exposing the socket on a another container than Traefik's. | ||||
|           With Swarm mode, it allows scheduling of Traefik on worker nodes, with only the "socket exposer" container on the manager nodes. | ||||
|         - Accounting at kernel level, by enforcing kernel calls with mechanisms like [SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux), to only allows an identified set of actions for Traefik's process (or the "socket exposer" process). | ||||
|         - SSH public key authentication (SSH is supported with Docker > 18.09) | ||||
|  | ||||
| @@ -192,69 +146,13 @@ You can specify which Docker API Endpoint to use with the directive [`endpoint`] | ||||
|         - [Letting Traefik run on Worker Nodes](https://blog.mikesir87.io/2018/07/letting-traefik-run-on-worker-nodes/) | ||||
|         - [Docker Socket Proxy from Tecnativa](https://github.com/Tecnativa/docker-socket-proxy) | ||||
|  | ||||
| ## Docker Swarm Mode | ||||
|  | ||||
| To enable Docker Swarm (instead of standalone Docker) as a configuration provider, | ||||
| set the [`swarmMode`](#swarmmode) directive to `true`. | ||||
|  | ||||
| ### Routing Configuration with Labels | ||||
|  | ||||
| While in Swarm Mode, Traefik uses labels found on services, not on individual containers. | ||||
|  | ||||
| Therefore, if you use a compose file with Swarm Mode, labels should be defined in the | ||||
| [`deploy`](https://docs.docker.com/compose/compose-file/compose-file-v3/#labels-1) part of your service. | ||||
|  | ||||
| This behavior is only enabled for docker-compose version 3+ ([Compose file reference](https://docs.docker.com/compose/compose-file/compose-file-v3/)). | ||||
|  | ||||
| ### Port Detection | ||||
|  | ||||
| Docker Swarm does not provide any [port detection](#port-detection) information to Traefik. | ||||
|  | ||||
| Therefore, you **must** specify the port to use for communication by using the label `traefik.http.services.<service_name>.loadbalancer.server.port` | ||||
| (Check the reference for this label in the [routing section for Docker](../routing/providers/docker.md#port)). | ||||
|  | ||||
| ### Docker API Access | ||||
|  | ||||
| Docker Swarm Mode follows the same rules as Docker [API Access](#docker-api-access). | ||||
|  | ||||
| Since the Swarm API is only exposed on the [manager nodes](https://docs.docker.com/engine/swarm/how-swarm-mode-works/nodes/#manager-nodes), | ||||
| these are the nodes that Traefik should be scheduled on by deploying Traefik with a constraint on the node "role": | ||||
|  | ||||
| ```shell tab="With Docker CLI" | ||||
| docker service create \ | ||||
|   --constraint=node.role==manager \ | ||||
|   #... \ | ||||
| ``` | ||||
|  | ||||
| ```yml tab="With Docker Compose" | ||||
| version: '3' | ||||
|  | ||||
| services: | ||||
|   traefik: | ||||
|     # ... | ||||
|     deploy: | ||||
|       placement: | ||||
|         constraints: | ||||
|           - node.role == manager | ||||
| ``` | ||||
|  | ||||
| !!! tip "Scheduling Traefik on Worker Nodes" | ||||
|  | ||||
|     Following the guidelines given in the previous section ["Docker API Access"](#docker-api-access), | ||||
|     if you expose the Docker API through TCP, then Traefik can be scheduled on any node if the TCP | ||||
|     socket is reachable. | ||||
|  | ||||
|     Please consider the security implications by reading the [Security Note](#security-note). | ||||
|  | ||||
|     A good example can be found on [Bret Fisher's repository](https://github.com/BretFisher/dogvscat/blob/master/stack-proxy-global.yml#L124). | ||||
|  | ||||
| ## Provider Configuration | ||||
|  | ||||
| ### `endpoint` | ||||
|  | ||||
| _Required, Default="unix:///var/run/docker.sock"_ | ||||
|  | ||||
| See the sections [Docker API Access](#docker-api-access) and [Docker Swarm API Access](#docker-api-access_1) for more information. | ||||
| See the [Docker API Access](#docker-api-access) section for more information. | ||||
|  | ||||
| ??? example "Using the docker.sock" | ||||
|  | ||||
| @@ -265,7 +163,7 @@ See the sections [Docker API Access](#docker-api-access) and [Docker Swarm API A | ||||
|  | ||||
|     services: | ||||
|       traefik: | ||||
|          image: traefik:v2.10 # The official v2 Traefik docker image | ||||
|          image: traefik:v3.0 # The official v2 Traefik docker image | ||||
|          ports: | ||||
|            - "80:80" | ||||
|          volumes: | ||||
| @@ -464,54 +362,6 @@ providers: | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `swarmMode` | ||||
|  | ||||
| _Optional, Default=false_ | ||||
|  | ||||
| Enables the Swarm Mode (instead of standalone Docker). | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   docker: | ||||
|     swarmMode: true | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.docker] | ||||
|   swarmMode = true | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.docker.swarmMode=true | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `swarmModeRefreshSeconds` | ||||
|  | ||||
| _Optional, Default=15_ | ||||
|  | ||||
| Defines the polling interval (in seconds) for Swarm Mode. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   docker: | ||||
|     swarmModeRefreshSeconds: 30 | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.docker] | ||||
|   swarmModeRefreshSeconds = 30 | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.docker.swarmModeRefreshSeconds=30 | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `httpClientTimeout` | ||||
|  | ||||
| _Optional, Default=0_ | ||||
|   | ||||
| @@ -234,6 +234,30 @@ providers: | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `healthyTasksOnly` | ||||
|  | ||||
| _Optional, Default=false_ | ||||
|  | ||||
| Determines whether Traefik discovers only healthy tasks (`HEALTHY` healthStatus). | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   ecs: | ||||
|     healthyTasksOnly: true | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.ecs] | ||||
|   healthyTasksOnly = true | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.ecs.healthyTasksOnly=true | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `defaultRule` | ||||
|  | ||||
| _Optional, Default=```Host(`{{ normalize .Name }}`)```_ | ||||
|   | ||||
| @@ -18,7 +18,7 @@ It supports providing configuration through a [single configuration file](#filen | ||||
|  | ||||
| !!! tip | ||||
|  | ||||
|     The file provider can be a good solution for reusing common elements from other providers (e.g. declaring whitelist middlewares, basic authentication, ...) | ||||
|     The file provider can be a good solution for reusing common elements from other providers (e.g. declaring allowlist middlewares, basic authentication, ...) | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
|   | ||||
| @@ -76,6 +76,26 @@ providers: | ||||
| --providers.http.pollTimeout=5s | ||||
| ``` | ||||
|  | ||||
| ### `headers` | ||||
|  | ||||
| _Optional_ | ||||
|  | ||||
| Defines custom headers to be sent to the endpoint. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   headers: | ||||
|     name: value | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.http.headers] | ||||
|   name = "value" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.http.headers.name=value | ||||
|  | ||||
| ### `tls` | ||||
|  | ||||
| _Optional_ | ||||
|   | ||||
| @@ -14,7 +14,9 @@ However, as the community expressed the need to benefit from Traefik features wi | ||||
| the Traefik engineering team developed a [Custom Resource Definition](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) | ||||
| (CRD) for an IngressRoute type, defined below, in order to provide a better way to configure access to a Kubernetes cluster. | ||||
|  | ||||
| ## Configuration Requirements | ||||
| ## Requirements | ||||
|  | ||||
| {!kubernetes-requirements.md!} | ||||
|  | ||||
| !!! tip "All Steps for a Successful Deployment" | ||||
|  | ||||
| @@ -25,20 +27,14 @@ the Traefik engineering team developed a [Custom Resource Definition](https://ku | ||||
|         * Apply the needed kubernetesCRD provider [configuration](#provider-configuration) | ||||
|     * Add all necessary Traefik custom [resources](../reference/dynamic-configuration/kubernetes-crd.md#resources) | ||||
|  | ||||
| !!! warning "Deprecated apiextensions.k8s.io/v1beta1 CRD" | ||||
|  | ||||
|     The `apiextensions.k8s.io/v1beta1` CustomResourceDefinition is deprecated in Kubernetes `v1.16+` and will be removed in `v1.22+`. | ||||
|      | ||||
|     For Kubernetes `v1.16+`, please use the Traefik `apiextensions.k8s.io/v1` CRDs instead. | ||||
|  | ||||
| !!! example "Installing Resource Definition and RBAC" | ||||
|  | ||||
|     ```bash | ||||
|     # Install Traefik Resource Definitions: | ||||
|     kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml | ||||
|     kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.0/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml | ||||
|      | ||||
|     # Install RBAC for Traefik: | ||||
|     kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml | ||||
|     kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.0/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml | ||||
|     ``` | ||||
|  | ||||
| ## Resource Configuration | ||||
| @@ -345,4 +341,4 @@ providers: | ||||
|  | ||||
| For additional information, refer to the [full example](../user-guides/crd-acme/index.md) with Let's Encrypt. | ||||
|  | ||||
| {!traefik-for-business-applications.md!} | ||||
| {!traefik-api-management-kubernetes.md!} | ||||
|   | ||||
| @@ -41,7 +41,9 @@ This provider is proposed as an experimental feature and partially supports the | ||||
|     --experimental.kubernetesgateway=true --providers.kubernetesgateway=true #... | ||||
|     ``` | ||||
|  | ||||
| ## Configuration Requirements | ||||
| ## Requirements | ||||
|  | ||||
| {!kubernetes-requirements.md!} | ||||
|  | ||||
| !!! tip "All Steps for a Successful Deployment" | ||||
|  | ||||
| @@ -268,3 +270,5 @@ providers: | ||||
| ```bash tab="CLI" | ||||
| --providers.kubernetesgateway.throttleDuration=10s | ||||
| ``` | ||||
|  | ||||
| {!traefik-api-management-kubernetes.md!} | ||||
|   | ||||
| @@ -13,7 +13,7 @@ it manages access to cluster services by supporting the [Ingress](https://kubern | ||||
|  | ||||
| ## Requirements | ||||
|  | ||||
| Traefik supports `1.14+` Kubernetes clusters. | ||||
| {!kubernetes-requirements.md!} | ||||
|  | ||||
| ## Routing Configuration | ||||
|  | ||||
| @@ -68,28 +68,6 @@ spec: | ||||
|                   number: 80 | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Ingress v1beta1 (deprecated)" | ||||
| apiVersion: networking.k8s.io/v1beta1 | ||||
| kind: Ingress | ||||
| metadata: | ||||
|   name: foo | ||||
|   namespace: production | ||||
|  | ||||
| spec: | ||||
|   rules: | ||||
|     - host: example.net | ||||
|       http: | ||||
|         paths: | ||||
|           - path: /bar | ||||
|             backend: | ||||
|               serviceName: service1 | ||||
|               servicePort: 80 | ||||
|           - path: /foo | ||||
|             backend: | ||||
|               serviceName: service1 | ||||
|               servicePort: 80 | ||||
| ``` | ||||
|  | ||||
| ## LetsEncrypt Support with the Ingress Provider | ||||
|  | ||||
| By design, Traefik is a stateless application, | ||||
| @@ -257,46 +235,7 @@ Value of `kubernetes.io/ingress.class` annotation that identifies Ingress object | ||||
| If the parameter is set, only Ingresses containing an annotation with the same value are processed. | ||||
| Otherwise, Ingresses missing the annotation, having an empty value, or the value `traefik` are processed. | ||||
|  | ||||
| ??? info "Kubernetes 1.18+" | ||||
|  | ||||
|     If the Kubernetes cluster version is 1.18+, | ||||
|     the new `IngressClass` resource can be leveraged to identify Ingress objects that should be processed. | ||||
|     In that case, Traefik will look for an `IngressClass` in the cluster with the controller value equal to *traefik.io/ingress-controller*. | ||||
|  | ||||
|     In addition to the controller value matching mechanism, the property `ingressClass` (if set) will be used to select IngressClasses by applying a strict matching on their name. | ||||
|  | ||||
|     Please see [this article](https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/) for more information or the example below. | ||||
|  | ||||
|     ```yaml tab="IngressClass" | ||||
|     apiVersion: networking.k8s.io/v1beta1 | ||||
|     kind: IngressClass | ||||
|     metadata: | ||||
|       name: traefik-lb | ||||
|     spec: | ||||
|       controller: traefik.io/ingress-controller | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="Ingress" | ||||
|     apiVersion: networking.k8s.io/v1beta1 | ||||
|     kind: Ingress | ||||
|     metadata: | ||||
|       name: example-ingress | ||||
|     spec: | ||||
|       ingressClassName: traefik-lb | ||||
|       rules: | ||||
|       - host: "*.example.com" | ||||
|         http: | ||||
|           paths: | ||||
|           - path: /example | ||||
|             backend: | ||||
|               serviceName: example-service | ||||
|               servicePort: 80 | ||||
|     ``` | ||||
|  | ||||
| ??? info "Kubernetes 1.19+" | ||||
|  | ||||
|     If the Kubernetes cluster version is 1.19+, | ||||
|     prefer using the `networking.k8s.io/v1` [apiVersion](https://v1-19.docs.kubernetes.io/docs/setup/release/notes/#api-change) of `Ingress` and `IngressClass`. | ||||
| ??? info "Example" | ||||
|  | ||||
|     ```yaml tab="IngressClass" | ||||
|     apiVersion: networking.k8s.io/v1 | ||||
| @@ -344,6 +283,35 @@ providers: | ||||
| --providers.kubernetesingress.ingressclass=traefik-internal | ||||
| ``` | ||||
|  | ||||
| ### `disableIngressClassLookup` | ||||
|  | ||||
| _Optional, Default: false_ | ||||
|  | ||||
| If the parameter is set to `true`, | ||||
| Traefik will not discover IngressClasses in the cluster. | ||||
| By doing so, it alleviates the requirement of giving Traefik the rights to look IngressClasses up. | ||||
| Furthermore, when this option is set to `true`, | ||||
| Traefik is not able to handle Ingresses with IngressClass references, | ||||
| therefore such Ingresses will be ignored. | ||||
| Please note that annotations are not affected by this option. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   kubernetesIngress: | ||||
|     disableIngressClassLookup: true | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.kubernetesIngress] | ||||
|   disableIngressClassLookup = true | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.kubernetesingress.disableingressclasslookup=true | ||||
| ``` | ||||
|  | ||||
| ### `ingressEndpoint` | ||||
|  | ||||
| #### `hostname` | ||||
| @@ -502,6 +470,6 @@ providers: | ||||
| ### Further | ||||
|  | ||||
| To learn more about the various aspects of the Ingress specification that Traefik supports, | ||||
| many examples of Ingresses definitions are located in the test [examples](https://github.com/traefik/traefik/tree/v2.10/pkg/provider/kubernetes/ingress/fixtures) of the Traefik repository. | ||||
| many examples of Ingresses definitions are located in the test [examples](https://github.com/traefik/traefik/tree/v3.0/pkg/provider/kubernetes/ingress/fixtures) of the Traefik repository. | ||||
|  | ||||
| {!traefik-for-business-applications.md!} | ||||
| {!traefik-api-management-kubernetes.md!} | ||||
|   | ||||
| @@ -1,583 +0,0 @@ | ||||
| --- | ||||
| title: "Traefik Configuration for Marathon" | ||||
| description: "Traefik Proxy can be configured to use Marathon as a provider. Read the technical documentation to learn how." | ||||
| --- | ||||
|  | ||||
| # Traefik & Marathon | ||||
|  | ||||
| Traefik can be configured to use Marathon as a provider. | ||||
| {: .subtitle } | ||||
|  | ||||
| For additional information, refer to [Marathon user guide](../user-guides/marathon.md). | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ??? example "Configuring Marathon & Deploying / Exposing Applications" | ||||
|  | ||||
|     Enabling the Marathon provider | ||||
|  | ||||
|     ```yaml tab="File (YAML)" | ||||
|     providers: | ||||
|       marathon: {} | ||||
|     ``` | ||||
|  | ||||
|     ```toml tab="File (TOML)" | ||||
|     [providers.marathon] | ||||
|     ``` | ||||
|  | ||||
|     ```bash tab="CLI" | ||||
|     --providers.marathon=true | ||||
|     ``` | ||||
|  | ||||
|     Attaching labels to Marathon applications | ||||
|  | ||||
|     ```json | ||||
| 	{ | ||||
| 		"id": "/whoami", | ||||
| 		"container": { | ||||
| 			"type": "DOCKER", | ||||
| 			"docker": { | ||||
| 				"image": "traefik/whoami", | ||||
| 				"network": "BRIDGE", | ||||
| 				"portMappings": [ | ||||
| 					{ | ||||
| 						"containerPort": 80, | ||||
| 						"hostPort": 0, | ||||
| 						"protocol": "tcp" | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		}, | ||||
| 		"labels": { | ||||
| 			"traefik.http.Routers.app.Rule": "PathPrefix(`/app`)" | ||||
| 		} | ||||
| 	} | ||||
|     ``` | ||||
|  | ||||
| ## Routing Configuration | ||||
|  | ||||
| See the dedicated section in [routing](../routing/providers/marathon.md). | ||||
|  | ||||
| ## Provider Configuration | ||||
|  | ||||
| ### `basic` | ||||
|  | ||||
| _Optional_ | ||||
|  | ||||
| Enables Marathon basic authentication. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   marathon: | ||||
|     basic: | ||||
|       httpBasicAuthUser: foo | ||||
|       httpBasicPassword: bar | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.marathon.basic] | ||||
|   httpBasicAuthUser = "foo" | ||||
|   httpBasicPassword = "bar" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.marathon.basic.httpbasicauthuser=foo | ||||
| --providers.marathon.basic.httpbasicpassword=bar | ||||
| ``` | ||||
|  | ||||
| ### `dcosToken` | ||||
|  | ||||
| _Optional_ | ||||
|  | ||||
| Datacenter Operating System (DCOS) Token for DCOS environment. | ||||
|  | ||||
| If set, it overrides the Authorization header. | ||||
|  | ||||
| ```toml tab="File (YAML)" | ||||
| providers: | ||||
|   marathon: | ||||
|     dcosToken: "xxxxxx" | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.marathon] | ||||
|   dcosToken = "xxxxxx" | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.marathon.dcosToken=xxxxxx | ||||
| ``` | ||||
|  | ||||
| ### `defaultRule` | ||||
|  | ||||
| _Optional, Default=```Host(`{{ normalize .Name }}`)```_ | ||||
|  | ||||
| The default host rule for all services. | ||||
|  | ||||
| For a given application, if no routing rule was defined by a label, it is defined by this `defaultRule` instead. | ||||
|  | ||||
| It must be a valid [Go template](https://pkg.go.dev/text/template/), | ||||
| and can include [sprig template functions](https://masterminds.github.io/sprig/). | ||||
|  | ||||
| The app ID can be accessed with the `Name` identifier, | ||||
| and the template has access to all the labels defined on this Marathon application. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   marathon: | ||||
|     defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.marathon] | ||||
|   defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.marathon.defaultRule=Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`) | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `dialerTimeout` | ||||
|  | ||||
| _Optional, Default=5s_ | ||||
|  | ||||
| Amount of time the Marathon provider should wait before timing out, | ||||
| when trying to open a TCP connection to a Marathon master. | ||||
|  | ||||
| The value of `dialerTimeout` should be provided in seconds or as a valid duration format, | ||||
| see [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration). | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   marathon: | ||||
|     dialerTimeout: "10s" | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.marathon] | ||||
|   dialerTimeout = "10s" | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.marathon.dialerTimeout=10s | ||||
| ``` | ||||
|  | ||||
| ### `endpoint` | ||||
|  | ||||
| _Optional, Default=http://127.0.0.1:8080_ | ||||
|  | ||||
| Marathon server endpoint. | ||||
|  | ||||
| You can optionally specify multiple endpoints. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   marathon: | ||||
|     endpoint: "http://10.241.1.71:8080,10.241.1.72:8080,10.241.1.73:8080" | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.marathon] | ||||
|   endpoint = "http://10.241.1.71:8080,10.241.1.72:8080,10.241.1.73:8080" | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.marathon.endpoint=http://10.241.1.71:8080,10.241.1.72:8080,10.241.1.73:8080 | ||||
| ``` | ||||
|  | ||||
| ### `exposedByDefault` | ||||
|  | ||||
| _Optional, Default=true_ | ||||
|  | ||||
| Exposes Marathon applications by default through Traefik. | ||||
|  | ||||
| If set to `false`, applications that do not have a `traefik.enable=true` label are ignored from the resulting routing configuration. | ||||
|  | ||||
| For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery). | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   marathon: | ||||
|     exposedByDefault: false | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.marathon] | ||||
|   exposedByDefault = false | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.marathon.exposedByDefault=false | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `constraints` | ||||
|  | ||||
| _Optional, Default=""_ | ||||
|  | ||||
| The `constraints` option can be set to an expression that Traefik matches against the application labels to determine whether | ||||
| to create any route for that application. If none of the application labels match the expression, no route for that application is | ||||
| created. In addition, the expression is also matched against the application constraints, such as described | ||||
| in [Marathon constraints](https://mesosphere.github.io/marathon/docs/constraints.html). | ||||
| If the expression is empty, all detected applications are included. | ||||
|  | ||||
| The expression syntax is based on the `Label("key", "value")`, and `LabelRegex("key", "value")` functions, as well as the usual boolean logic. | ||||
| In addition, to match against Marathon constraints, the function `MarathonConstraint("field:operator:value")` can be used, where the field, operator, and value parts are concatenated in a single string using the `:` separator. | ||||
|  | ||||
| ??? example "Constraints Expression Examples" | ||||
|  | ||||
|     ```toml | ||||
|     # Includes only applications having a label with key `a.label.name` and value `foo` | ||||
|     constraints = "Label(`a.label.name`, `foo`)" | ||||
|     ``` | ||||
|  | ||||
|     ```toml | ||||
|     # Excludes applications having any label with key `a.label.name` and value `foo` | ||||
|     constraints = "!Label(`a.label.name`, `value`)" | ||||
|     ``` | ||||
|  | ||||
|     ```toml | ||||
|     # With logical AND. | ||||
|     constraints = "Label(`a.label.name`, `valueA`) && Label(`another.label.name`, `valueB`)" | ||||
|     ``` | ||||
|  | ||||
|     ```toml | ||||
|     # With logical OR. | ||||
|     constraints = "Label(`a.label.name`, `valueA`) || Label(`another.label.name`, `valueB`)" | ||||
|     ``` | ||||
|  | ||||
|     ```toml | ||||
|     # With logical AND and OR, with precedence set by parentheses. | ||||
|     constraints = "Label(`a.label.name`, `valueA`) && (Label(`another.label.name`, `valueB`) || Label(`yet.another.label.name`, `valueC`))" | ||||
|     ``` | ||||
|  | ||||
|     ```toml | ||||
|     # Includes only applications having a label with key `a.label.name` and a value matching the `a.+` regular expression. | ||||
|     constraints = "LabelRegex(`a.label.name`, `a.+`)" | ||||
|     ``` | ||||
|  | ||||
|     ```toml | ||||
|     # Includes only applications having a Marathon constraint with field `A`, operator `B`, and value `C`. | ||||
|     constraints = "MarathonConstraint(`A:B:C`)" | ||||
|     ``` | ||||
|  | ||||
|     ```toml | ||||
|     # Uses both Marathon constraint and application label with logical operator. | ||||
|     constraints = "MarathonConstraint(`A:B:C`) && Label(`a.label.name`, `value`)" | ||||
|     ``` | ||||
|  | ||||
| For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery). | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   marathon: | ||||
|     constraints: "Label(`a.label.name`,`foo`)" | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.marathon] | ||||
|   constraints = "Label(`a.label.name`,`foo`)" | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.marathon.constraints=Label(`a.label.name`,`foo`) | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `forceTaskHostname` | ||||
|  | ||||
| _Optional, Default=false_ | ||||
|  | ||||
| By default, the task IP address (as returned by the Marathon API) is used as backend server if an IP-per-task configuration can be found; | ||||
| otherwise, the name of the host running the task is used. | ||||
| The latter behavior can be enforced by setting this option to `true`. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   marathon: | ||||
|     forceTaskHostname: true | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.marathon] | ||||
|   forceTaskHostname = true | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.marathon.forceTaskHostname=true | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `keepAlive` | ||||
|  | ||||
| _Optional, Default=10s_ | ||||
|  | ||||
| Set the TCP Keep Alive duration for the Marathon HTTP Client. | ||||
| The value of `keepAlive` should be provided in seconds or as a valid duration format, | ||||
| see [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration). | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   marathon: | ||||
|     keepAlive: "30s" | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.marathon] | ||||
|   keepAlive = "30s" | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.marathon.keepAlive=30s | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `respectReadinessChecks` | ||||
|  | ||||
| _Optional, Default=false_ | ||||
|  | ||||
| Applications may define readiness checks which are probed by Marathon during deployments periodically, and these check results are exposed via the API. | ||||
| Enabling `respectReadinessChecks` causes Traefik to filter out tasks whose readiness checks have not succeeded. | ||||
| Note that the checks are only valid during deployments. | ||||
|  | ||||
| See the Marathon guide for details. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   marathon: | ||||
|     respectReadinessChecks: true | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.marathon] | ||||
|   respectReadinessChecks = true | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.marathon.respectReadinessChecks=true | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `responseHeaderTimeout` | ||||
|  | ||||
| _Optional, Default=60s_ | ||||
|  | ||||
| Amount of time the Marathon provider should wait before timing out when waiting for the first response header | ||||
| from a Marathon master. | ||||
|  | ||||
| The value of `responseHeaderTimeout` should be provided in seconds or as a valid duration format, | ||||
| see [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration). | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   marathon: | ||||
|     responseHeaderTimeout: "66s" | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.marathon] | ||||
|   responseHeaderTimeout = "66s" | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.marathon.responseHeaderTimeout=66s | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `tls` | ||||
|  | ||||
| _Optional_ | ||||
|  | ||||
| Defines the TLS configuration used for the secure connection to Marathon. | ||||
|  | ||||
| #### `ca` | ||||
|  | ||||
| `ca` is the path to the certificate authority used for the secure connection to Marathon, | ||||
| it defaults to the system bundle. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   marathon: | ||||
|     tls: | ||||
|       ca: path/to/ca.crt | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.marathon.tls] | ||||
|   ca = "path/to/ca.crt" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.marathon.tls.ca=path/to/ca.crt | ||||
| ``` | ||||
|  | ||||
| #### `cert` | ||||
|  | ||||
| _Optional_ | ||||
|  | ||||
| `cert` is the path to the public certificate used for the secure connection to Marathon. | ||||
| When using this option, setting the `key` option is required. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   marathon: | ||||
|     tls: | ||||
|       cert: path/to/foo.cert | ||||
|       key: path/to/foo.key | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.marathon.tls] | ||||
|   cert = "path/to/foo.cert" | ||||
|   key = "path/to/foo.key" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.marathon.tls.cert=path/to/foo.cert | ||||
| --providers.marathon.tls.key=path/to/foo.key | ||||
| ``` | ||||
|  | ||||
| #### `key` | ||||
|  | ||||
| _Optional_ | ||||
|  | ||||
| `key` is the path to the private key used for the secure connection to Marathon. | ||||
| When using this option, setting the `cert` option is required. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   marathon: | ||||
|     tls: | ||||
|       cert: path/to/foo.cert | ||||
|       key: path/to/foo.key | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.marathon.tls] | ||||
|   cert = "path/to/foo.cert" | ||||
|   key = "path/to/foo.key" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.marathon.tls.cert=path/to/foo.cert | ||||
| --providers.marathon.tls.key=path/to/foo.key | ||||
| ``` | ||||
|  | ||||
| #### `insecureSkipVerify` | ||||
|  | ||||
| _Optional, Default=false_ | ||||
|  | ||||
| If `insecureSkipVerify` is `true`, the TLS connection to Marathon accepts any certificate presented by the server regardless of the hostnames it covers. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   marathon: | ||||
|     tls: | ||||
|       insecureSkipVerify: true | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.marathon.tls] | ||||
|   insecureSkipVerify = true | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.marathon.tls.insecureSkipVerify=true | ||||
| ``` | ||||
|  | ||||
| ### `tlsHandshakeTimeout` | ||||
|  | ||||
| _Optional, Default=5s_ | ||||
|  | ||||
| Amount of time the Marathon provider should wait before timing out, | ||||
| when waiting for the TLS handshake to complete. | ||||
|  | ||||
| The value of `tlsHandshakeTimeout` should be provided in seconds or as a valid duration format, | ||||
| see [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration). | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   marathon: | ||||
|     tlsHandshakeTimeout: "10s" | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.marathon] | ||||
|   tlsHandshakeTimeout = "10s" | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.marathon.tlsHandshakeTimeout=10s | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `trace` | ||||
|  | ||||
| _Optional, Default=false_ | ||||
|  | ||||
| Displays additional provider logs when available. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   marathon: | ||||
|     trace: true | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.marathon] | ||||
|   trace = true | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.marathon.trace=true | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `watch` | ||||
|  | ||||
| _Optional, Default=true_ | ||||
|  | ||||
| When set to `true`, watches for Marathon changes. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   marathon: | ||||
|     watch: false | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.marathon] | ||||
|   watch = false | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.marathon.watch=false | ||||
| # ... | ||||
| ``` | ||||
| @@ -440,7 +440,7 @@ providers: | ||||
|  | ||||
| For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery). | ||||
|  | ||||
| ### `namespace` | ||||
| ### `namespaces` | ||||
|  | ||||
| ??? warning "Deprecated in favor of the [`namespaces`](#namespaces) option." | ||||
|  | ||||
|   | ||||
| @@ -72,7 +72,7 @@ For the list of the providers names, see the [supported providers](#supported-pr | ||||
|  | ||||
|     Using the add-foo-prefix middleware from other providers: | ||||
|  | ||||
|     ```yaml tab="Docker" | ||||
|     ```yaml tab="Docker & Swarm" | ||||
|     your-container: # | ||||
|       image: your-docker-image | ||||
|  | ||||
| @@ -141,8 +141,6 @@ Below is the list of the currently supported providers in Traefik. | ||||
| | [Consul Catalog](./consul-catalog.md)             | Orchestrator | Label                | `consulcatalog`     | | ||||
| | [Nomad](./nomad.md)                               | Orchestrator | Label                | `nomad`             | | ||||
| | [ECS](./ecs.md)                                   | Orchestrator | Label                | `ecs`               | | ||||
| | [Marathon](./marathon.md)                         | Orchestrator | Label                | `marathon`          | | ||||
| | [Rancher](./rancher.md)                           | Orchestrator | Label                | `rancher`           | | ||||
| | [File](./file.md)                                 | Manual       | YAML/TOML format     | `file`              | | ||||
| | [Consul](./consul.md)                             | KV           | KV                   | `consul`            | | ||||
| | [Etcd](./etcd.md)                                 | KV           | KV                   | `etcd`              | | ||||
| @@ -216,8 +214,6 @@ List of providers that support these features: | ||||
| - [ECS](./ecs.md#exposedbydefault) | ||||
| - [Consul Catalog](./consul-catalog.md#exposedbydefault) | ||||
| - [Nomad](./nomad.md#exposedbydefault) | ||||
| - [Rancher](./rancher.md#exposedbydefault) | ||||
| - [Marathon](./marathon.md#exposedbydefault) | ||||
|  | ||||
| ### Constraints | ||||
|  | ||||
| @@ -227,8 +223,6 @@ List of providers that support constraints: | ||||
| - [ECS](./ecs.md#constraints) | ||||
| - [Consul Catalog](./consul-catalog.md#constraints) | ||||
| - [Nomad](./nomad.md#constraints) | ||||
| - [Rancher](./rancher.md#constraints) | ||||
| - [Marathon](./marathon.md#constraints) | ||||
| - [Kubernetes CRD](./kubernetes-crd.md#labelselector) | ||||
| - [Kubernetes Ingress](./kubernetes-ingress.md#labelselector) | ||||
| - [Kubernetes Gateway](./kubernetes-gateway.md#labelselector) | ||||
|   | ||||
| @@ -1,286 +0,0 @@ | ||||
| --- | ||||
| title: ""Traefik Configuration Discovery: Rancher"" | ||||
| description: "Read the official Traefik documentation to learn how to expose Rancher services by default in Traefik Proxy." | ||||
| --- | ||||
|  | ||||
| # Traefik & Rancher | ||||
|  | ||||
| A Story of Labels, Services & Containers | ||||
| {: .subtitle } | ||||
|  | ||||
|  | ||||
|  | ||||
| Attach labels to your services and let Traefik do the rest! | ||||
|  | ||||
| !!! important "This provider is specific to Rancher 1.x." | ||||
|  | ||||
|     Rancher 2.x requires Kubernetes and does not have a metadata endpoint of its own for Traefik to query. | ||||
|     As such, Rancher 2.x users should utilize the [Kubernetes CRD provider](./kubernetes-crd.md) directly. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ??? example "Configuring Rancher & Deploying / Exposing Services" | ||||
|  | ||||
|     Enabling the Rancher provider | ||||
|  | ||||
|     ```yaml tab="File (YAML)" | ||||
|     providers: | ||||
|       rancher: {} | ||||
|     ``` | ||||
|  | ||||
|     ```toml tab="File (TOML)" | ||||
|     [providers.rancher] | ||||
|     ``` | ||||
|  | ||||
|     ```bash tab="CLI" | ||||
|     --providers.rancher=true | ||||
|     ``` | ||||
|  | ||||
|     Attaching labels to services | ||||
|  | ||||
|     ```yaml | ||||
|     labels: | ||||
|       - traefik.http.services.my-service.rule=Host(`example.com`) | ||||
|     ``` | ||||
|  | ||||
| ## Routing Configuration | ||||
|  | ||||
| See the dedicated section in [routing](../routing/providers/rancher.md). | ||||
|  | ||||
| ## Provider Configuration | ||||
|  | ||||
| ??? tip "Browse the Reference" | ||||
|  | ||||
|     For an overview of all the options that can be set with the Rancher provider, see the following snippets: | ||||
|  | ||||
|     ```yaml tab="File (YAML)" | ||||
|     --8<-- "content/providers/rancher.yml" | ||||
|     ``` | ||||
|  | ||||
|     ```toml tab="File (TOML)" | ||||
|     --8<-- "content/providers/rancher.toml" | ||||
|     ``` | ||||
|  | ||||
|     ```bash tab="CLI" | ||||
|     --8<-- "content/providers/rancher.txt" | ||||
|     ``` | ||||
|  | ||||
| ### `exposedByDefault` | ||||
|  | ||||
| _Optional, Default=true_ | ||||
|  | ||||
| Expose Rancher services by default in Traefik. | ||||
| If set to `false`, services that do not have a `traefik.enable=true` label are ignored from the resulting routing configuration. | ||||
|  | ||||
| For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery). | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   rancher: | ||||
|     exposedByDefault: false | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.rancher] | ||||
|   exposedByDefault = false | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.rancher.exposedByDefault=false | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `defaultRule` | ||||
|  | ||||
| _Optional, Default=```Host(`{{ normalize .Name }}`)```_ | ||||
|  | ||||
| The default host rule for all services. | ||||
|  | ||||
| The `defaultRule` option defines what routing rule to apply to a container if no rule is defined by a label. | ||||
|  | ||||
| It must be a valid [Go template](https://pkg.go.dev/text/template/), and can use | ||||
| [sprig template functions](https://masterminds.github.io/sprig/). | ||||
| The service name can be accessed with the `Name` identifier, | ||||
| and the template has access to all the labels defined on this container. | ||||
|  | ||||
| This option can be overridden on a container basis with the `traefik.http.routers.Router1.rule` label. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   rancher: | ||||
|     defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.rancher] | ||||
|   defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.rancher.defaultRule=Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`) | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `enableServiceHealthFilter` | ||||
|  | ||||
| _Optional, Default=true_ | ||||
|  | ||||
| Filter out services with unhealthy states and inactive states. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   rancher: | ||||
|     enableServiceHealthFilter: false | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.rancher] | ||||
|   enableServiceHealthFilter = false | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.rancher.enableServiceHealthFilter=false | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `refreshSeconds` | ||||
|  | ||||
| _Optional, Default=15_ | ||||
|  | ||||
| Defines the polling interval (in seconds). | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   rancher: | ||||
|     refreshSeconds: 30 | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.rancher] | ||||
|   refreshSeconds = 30 | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.rancher.refreshSeconds=30 | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `intervalPoll` | ||||
|  | ||||
| _Optional, Default=false_ | ||||
|  | ||||
| Poll the Rancher metadata service for changes every `rancher.refreshSeconds`, | ||||
| which is less accurate than the default long polling technique which provides near instantaneous updates to Traefik. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   rancher: | ||||
|     intervalPoll: true | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.rancher] | ||||
|   intervalPoll = true | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.rancher.intervalPoll=true | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `prefix` | ||||
|  | ||||
| _Optional, Default="/latest"_ | ||||
|  | ||||
| Prefix used for accessing the Rancher metadata service. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   rancher: | ||||
|     prefix: "/test" | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.rancher] | ||||
|   prefix = "/test" | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.rancher.prefix=/test | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `constraints` | ||||
|  | ||||
| _Optional, Default=""_ | ||||
|  | ||||
| The `constraints` option can be set to an expression that Traefik matches against the container labels to determine whether | ||||
| to create any route for that container. If none of the container tags match the expression, no route for that container is | ||||
| created. If the expression is empty, all detected containers are included. | ||||
|  | ||||
| The expression syntax is based on the `Label("key", "value")`, and `LabelRegex("key", "value")` functions, as well as | ||||
| the usual boolean logic, as shown in examples below. | ||||
|  | ||||
| ??? example "Constraints Expression Examples" | ||||
|  | ||||
|     ```toml | ||||
|     # Includes only containers having a label with key `a.label.name` and value `foo` | ||||
|     constraints = "Label(`a.label.name`, `foo`)" | ||||
|     ``` | ||||
|  | ||||
|     ```toml | ||||
|     # Excludes containers having any label with key `a.label.name` and value `foo` | ||||
|     constraints = "!Label(`a.label.name`, `value`)" | ||||
|     ``` | ||||
|  | ||||
|     ```toml | ||||
|     # With logical AND. | ||||
|     constraints = "Label(`a.label.name`, `valueA`) && Label(`another.label.name`, `valueB`)" | ||||
|     ``` | ||||
|  | ||||
|     ```toml | ||||
|     # With logical OR. | ||||
|     constraints = "Label(`a.label.name`, `valueA`) || Label(`another.label.name`, `valueB`)" | ||||
|     ``` | ||||
|  | ||||
|     ```toml | ||||
|     # With logical AND and OR, with precedence set by parentheses. | ||||
|     constraints = "Label(`a.label.name`, `valueA`) && (Label(`another.label.name`, `valueB`) || Label(`yet.another.label.name`, `valueC`))" | ||||
|     ``` | ||||
|  | ||||
|     ```toml | ||||
|     # Includes only containers having a label with key `a.label.name` and a value matching the `a.+` regular expression. | ||||
|     constraints = "LabelRegex(`a.label.name`, `a.+`)" | ||||
|     ``` | ||||
|  | ||||
| For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery). | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   rancher: | ||||
|     constraints: "Label(`a.label.name`,`foo`)" | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.rancher] | ||||
|   constraints = "Label(`a.label.name`,`foo`)" | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.rancher.constraints=Label(`a.label.name`,`foo`) | ||||
| # ... | ||||
| ``` | ||||
| @@ -1,20 +0,0 @@ | ||||
| # Enable Rancher Provider. | ||||
| [providers.rancher] | ||||
|  | ||||
|   # Expose Rancher services by default in Traefik. | ||||
|   exposedByDefault = true | ||||
|  | ||||
|   # Enable watch Rancher changes. | ||||
|   watch = true | ||||
|  | ||||
|   # Filter services with unhealthy states and inactive states. | ||||
|   enableServiceHealthFilter = true | ||||
|  | ||||
|   # Defines the polling interval (in seconds). | ||||
|   refreshSeconds = 15 | ||||
|  | ||||
|   # Poll the Rancher metadata service for changes every `rancher.refreshSeconds`, which is less accurate | ||||
|   intervalPoll = false | ||||
|  | ||||
|   # Prefix used for accessing the Rancher metadata service | ||||
|   prefix = "/latest" | ||||
| @@ -1,20 +0,0 @@ | ||||
| # Enable Rancher Provider. | ||||
| --providers.rancher=true | ||||
|  | ||||
| # Expose Rancher services by default in Traefik. | ||||
| --providers.rancher.exposedByDefault=true | ||||
|  | ||||
| # Enable watch Rancher changes. | ||||
| --providers.rancher.watch=true | ||||
|  | ||||
| # Filter services with unhealthy states and inactive states. | ||||
| --providers.rancher.enableServiceHealthFilter=true | ||||
|  | ||||
| # Defines the polling interval (in seconds). | ||||
| --providers.rancher.refreshSeconds=15 | ||||
|  | ||||
| # Poll the Rancher metadata service for changes every `rancher.refreshSeconds`, which is less accurate | ||||
| --providers.rancher.intervalPoll=false | ||||
|  | ||||
| # Prefix used for accessing the Rancher metadata service | ||||
| --providers.rancher.prefix=/latest | ||||
| @@ -1,21 +0,0 @@ | ||||
| # Enable Rancher Provider. | ||||
| providers: | ||||
|   rancher: | ||||
|  | ||||
|   # Expose Rancher services by default in Traefik. | ||||
|   exposedByDefault: true | ||||
|  | ||||
|   # Enable watch Rancher changes. | ||||
|   watch: true | ||||
|  | ||||
|   # Filter services with unhealthy states and inactive states. | ||||
|   enableServiceHealthFilter: true | ||||
|  | ||||
|   # Defines the polling interval (in seconds). | ||||
|   refreshSeconds: 15 | ||||
|  | ||||
|   # Poll the Rancher metadata service for changes every `rancher.refreshSeconds`, which is less accurate | ||||
|   intervalPoll: false | ||||
|  | ||||
|   # Prefix used for accessing the Rancher metadata service | ||||
|   prefix: /latest | ||||
							
								
								
									
										697
									
								
								docs/content/providers/swarm.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										697
									
								
								docs/content/providers/swarm.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,697 @@ | ||||
| --- | ||||
| title: "Traefik Docker Swarm Documentation" | ||||
| description: "Learn how to achieve configuration discovery in Traefik through Docker Swarm. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # Traefik & Docker Swarm | ||||
|  | ||||
| A Story of Labels & Containers | ||||
| {: .subtitle } | ||||
|  | ||||
|  | ||||
|  | ||||
| Attach labels to your containers and let Traefik do the rest! | ||||
|  | ||||
| This provider works with [Docker Swarm Mode](https://docs.docker.com/engine/swarm/). | ||||
|  | ||||
| !!! tip "The Quick Start Uses Docker" | ||||
|  | ||||
|     If you have not already read it, maybe you would like to go through the [quick start guide](../getting-started/quick-start.md) that uses the Docker provider. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ??? example "Configuring Docker Swarm & Deploying / Exposing Services" | ||||
|  | ||||
|     Enabling the Swarm provider | ||||
|  | ||||
|     ```yaml tab="File (YAML)" | ||||
|     providers: | ||||
|       swarm: | ||||
|         # swarm classic (1.12-) | ||||
|         # endpoint: "tcp://127.0.0.1:2375" | ||||
|         # docker swarm mode (1.12+) | ||||
|         endpoint: "tcp://127.0.0.1:2377" | ||||
|     ``` | ||||
|  | ||||
|     ```toml tab="File (TOML)" | ||||
|     [providers.swarm] | ||||
|       # swarm classic (1.12-) | ||||
|       # endpoint = "tcp://127.0.0.1:2375" | ||||
|       # docker swarm mode (1.12+) | ||||
|       endpoint = "tcp://127.0.0.1:2377" | ||||
|     ``` | ||||
|  | ||||
|     ```bash tab="CLI" | ||||
|     # swarm classic (1.12-) | ||||
|     # --providers.swarm.endpoint=tcp://127.0.0.1:2375 | ||||
|     # docker swarm mode (1.12+) | ||||
|     --providers.swarm.endpoint=tcp://127.0.0.1:2377 | ||||
|     ``` | ||||
|  | ||||
|     Attach labels to services (not to containers) while in Swarm mode (in your docker compose file) | ||||
|  | ||||
|     ```yaml | ||||
|     version: "3" | ||||
|     services: | ||||
|       my-container: | ||||
|         deploy: | ||||
|           labels: | ||||
|             - traefik.http.routers.my-container.rule=Host(`example.com`) | ||||
|             - traefik.http.services.my-container-service.loadbalancer.server.port=8080 | ||||
|     ``` | ||||
|  | ||||
| ## Routing Configuration | ||||
|  | ||||
| When using Docker as a [provider](./overview.md), | ||||
| Traefik uses [container labels](https://docs.docker.com/engine/reference/commandline/run/#label) to retrieve its routing configuration. | ||||
|  | ||||
| See the list of labels in the dedicated [routing](../routing/providers/docker.md) section. | ||||
|  | ||||
| ### Routing Configuration with Labels | ||||
|  | ||||
| By default, Traefik watches for [container level labels](https://docs.docker.com/config/labels-custom-metadata/) on a standalone Docker Engine. | ||||
|  | ||||
| When using Docker Compose, labels are specified by the directive | ||||
| [`labels`](https://docs.docker.com/compose/compose-file/compose-file-v3/#labels) from the | ||||
| ["services" objects](https://docs.docker.com/compose/compose-file/compose-file-v3/#service-configuration-reference). | ||||
|  | ||||
| !!! tip "Not Only Docker" | ||||
|  | ||||
|     Please note that any tool like Nomad, Terraform, Ansible, etc. | ||||
|     that is able to define a Docker container with labels can work | ||||
|     with Traefik and the  Swarm provider. | ||||
|  | ||||
| While in Swarm Mode, Traefik uses labels found on services, not on individual containers. | ||||
|  | ||||
| Therefore, if you use a compose file with Swarm Mode, labels should be defined in the | ||||
| [`deploy`](https://docs.docker.com/compose/compose-file/compose-file-v3/#labels-1) part of your service. | ||||
|  | ||||
| This behavior is only enabled for docker-compose version 3+ ([Compose file reference](https://docs.docker.com/compose/compose-file/compose-file-v3/)). | ||||
|  | ||||
| ### Port Detection | ||||
|  | ||||
| Traefik retrieves the private IP and port of containers from the Docker API. | ||||
|  | ||||
| Docker Swarm does not provide any port detection information to Traefik. | ||||
|  | ||||
| Therefore, you **must** specify the port to use for communication by using the label `traefik.http.services.<service_name>.loadbalancer.server.port` | ||||
| (Check the reference for this label in the [routing section for Swarm](../routing/providers/swarm.md#services)). | ||||
|  | ||||
| ### Host networking | ||||
|  | ||||
| When exposing containers that are configured with [host networking](https://docs.docker.com/network/host/), | ||||
| the IP address of the host is resolved as follows: | ||||
|  | ||||
| <!-- TODO: verify and document the swarm mode case with container.Node.IPAddress coming from the API --> | ||||
| - try a lookup of `host.docker.internal` | ||||
| - if the lookup was unsuccessful, try a lookup of `host.containers.internal`, ([Podman](https://docs.podman.io/en/latest/) equivalent of `host.docker.internal`) | ||||
| - if that lookup was also unsuccessful, fall back to `127.0.0.1` | ||||
|  | ||||
| On Linux, for versions of Docker older than 20.10.0, for `host.docker.internal` to be defined, it should be provided | ||||
| as an `extra_host` to the Traefik container, using the `--add-host` flag. For example, to set it to the IP address of | ||||
| the bridge interface (`docker0` by default): `--add-host=host.docker.internal:172.17.0.1` | ||||
|  | ||||
| ### IPv4 && IPv6 | ||||
|  | ||||
| When using a docker stack that uses IPv6, | ||||
| Traefik will use the IPv4 container IP before its IPv6 counterpart. | ||||
| Therefore, on an IPv6 Docker stack, | ||||
| Traefik will use the IPv6 container IP. | ||||
|  | ||||
| ### Docker API Access | ||||
|  | ||||
| Traefik requires access to the docker socket to get its dynamic configuration. | ||||
|  | ||||
| You can specify which Docker API Endpoint to use with the directive [`endpoint`](#endpoint). | ||||
|  | ||||
| !!! warning "Security Note" | ||||
|  | ||||
|     Accessing the Docker API without any restriction is a security concern: | ||||
|     If Traefik is attacked, then the attacker might get access to the underlying host. | ||||
|     {: #security-note } | ||||
|  | ||||
|     As explained in the [Docker Daemon Attack Surface documentation](https://docs.docker.com/engine/security/#docker-daemon-attack-surface): | ||||
|  | ||||
|     !!! quote | ||||
|  | ||||
|         [...] only **trusted** users should be allowed to control your Docker daemon [...] | ||||
|  | ||||
|     ??? success "Solutions" | ||||
|  | ||||
|         Expose the Docker socket over TCP or SSH, instead of the default Unix socket file. | ||||
|         It allows different implementation levels of the [AAA (Authentication, Authorization, Accounting) concepts](https://en.wikipedia.org/wiki/AAA_(computer_security)), depending on your security assessment: | ||||
|  | ||||
|         - Authentication with Client Certificates as described in ["Protect the Docker daemon socket."](https://docs.docker.com/engine/security/protect-access/) | ||||
|         - Authorize and filter requests to restrict possible actions with [the TecnativaDocker Socket Proxy](https://github.com/Tecnativa/docker-socket-proxy). | ||||
|         - Authorization with the [Docker Authorization Plugin Mechanism](https://web.archive.org/web/20190920092526/https://docs.docker.com/engine/extend/plugins_authorization/) | ||||
|         - Accounting at networking level, by exposing the socket only inside a Docker private network, only available for Traefik. | ||||
|         - Accounting at container level, by exposing the socket on a another container than Traefik's. | ||||
|           It allows scheduling of Traefik on worker nodes, with only the "socket exposer" container on the manager nodes. | ||||
|         - Accounting at kernel level, by enforcing kernel calls with mechanisms like [SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux), to only allows an identified set of actions for Traefik's process (or the "socket exposer" process). | ||||
|         - SSH public key authentication (SSH is supported with Docker > 18.09) | ||||
|  | ||||
|     ??? info "More Resources and Examples" | ||||
|  | ||||
|         - ["Paranoid about mounting /var/run/docker.sock?"](https://medium.com/@containeroo/traefik-2-0-paranoid-about-mounting-var-run-docker-sock-22da9cb3e78c) | ||||
|         - [Traefik and Docker: A Discussion with Docker Captain, Bret Fisher](https://blog.traefik.io/traefik-and-docker-a-discussion-with-docker-captain-bret-fisher-7f0b9a54ff88) | ||||
|         - [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/) | ||||
|         - [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) | ||||
|         - [Traefik issue GH-4174 about security with Docker socket](https://github.com/traefik/traefik/issues/4174) | ||||
|         - [Inspecting Docker Activity with Socat](https://developers.redhat.com/blog/2015/02/25/inspecting-docker-activity-with-socat/) | ||||
|         - [Letting Traefik run on Worker Nodes](https://blog.mikesir87.io/2018/07/letting-traefik-run-on-worker-nodes/) | ||||
|         - [Docker Socket Proxy from Tecnativa](https://github.com/Tecnativa/docker-socket-proxy) | ||||
|  | ||||
| Since the Swarm API is only exposed on the [manager nodes](https://docs.docker.com/engine/swarm/how-swarm-mode-works/nodes/#manager-nodes), | ||||
| these are the nodes that Traefik should be scheduled on by deploying Traefik with a constraint on the node "role": | ||||
|  | ||||
| ```shell tab="With Docker CLI" | ||||
| docker service create \ | ||||
|   --constraint=node.role==manager \ | ||||
|   #... \ | ||||
| ``` | ||||
|  | ||||
| ```yml tab="With Docker Compose" | ||||
| version: '3' | ||||
|  | ||||
| services: | ||||
|   traefik: | ||||
|     # ... | ||||
|     deploy: | ||||
|       placement: | ||||
|         constraints: | ||||
|           - node.role == manager | ||||
| ``` | ||||
|  | ||||
| !!! tip "Scheduling Traefik on Worker Nodes" | ||||
|  | ||||
|     Following the guidelines given in the previous section ["Docker API Access"](#docker-api-access), | ||||
|     if you expose the Docker API through TCP, then Traefik can be scheduled on any node if the TCP | ||||
|     socket is reachable. | ||||
|  | ||||
|     Please consider the security implications by reading the [Security Note](#security-note). | ||||
|  | ||||
|     A good example can be found on [Bret Fisher's repository](https://github.com/BretFisher/dogvscat/blob/master/stack-proxy-global.yml#L124). | ||||
|  | ||||
| ### `endpoint` | ||||
|  | ||||
| _Required, Default="unix:///var/run/docker.sock"_ | ||||
|  | ||||
| See the [Docker Swarm API Access](#docker-api-access) section for more information. | ||||
|  | ||||
| ??? example "Using the docker.sock" | ||||
|  | ||||
|     The docker-compose file shares the docker sock with the Traefik container | ||||
|  | ||||
|     ```yaml | ||||
|     version: '3' | ||||
|  | ||||
|     services: | ||||
|       traefik: | ||||
|          image: traefik:v3.0 # The official v2 Traefik docker image | ||||
|          ports: | ||||
|            - "80:80" | ||||
|          volumes: | ||||
|            - /var/run/docker.sock:/var/run/docker.sock | ||||
|     ``` | ||||
|  | ||||
|     We specify the docker.sock in traefik's configuration file. | ||||
|  | ||||
|     ```yaml tab="File (YAML)" | ||||
|     providers: | ||||
|       swarm: | ||||
|         endpoint: "unix:///var/run/docker.sock" | ||||
|          # ... | ||||
|     ``` | ||||
|  | ||||
|     ```toml tab="File (TOML)" | ||||
|     [providers.swarm] | ||||
|       endpoint = "unix:///var/run/docker.sock" | ||||
|       # ... | ||||
|     ``` | ||||
|  | ||||
|     ```bash tab="CLI" | ||||
|     --providers.swarm.endpoint=unix:///var/run/docker.sock | ||||
|     # ... | ||||
|     ``` | ||||
|  | ||||
| ??? example "Using SSH" | ||||
|  | ||||
|     Using Docker 18.09+ you can connect Traefik to daemon using SSH | ||||
|     We specify the SSH host and user in Traefik's configuration file. | ||||
|     Note that is server requires public keys for authentication you must have those accessible for user who runs Traefik. | ||||
|  | ||||
|     ```yaml tab="File (YAML)" | ||||
|     providers: | ||||
|       docker: | ||||
|         endpoint: "ssh://traefik@192.168.2.5:2022" | ||||
|          # ... | ||||
|     ``` | ||||
|  | ||||
|     ```toml tab="File (TOML)" | ||||
|     [providers.swarm] | ||||
|       endpoint = "ssh://traefik@192.168.2.5:2022" | ||||
|       # ... | ||||
|     ``` | ||||
|  | ||||
|     ```bash tab="CLI" | ||||
|     --providers.swarm.endpoint=ssh://traefik@192.168.2.5:2022 | ||||
|     # ... | ||||
|     ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   swarm: | ||||
|     endpoint: "unix:///var/run/docker.sock" | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.swarm] | ||||
|   endpoint = "unix:///var/run/docker.sock" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.swarm.endpoint=unix:///var/run/docker.sock | ||||
| ``` | ||||
|  | ||||
| ### `useBindPortIP` | ||||
|  | ||||
| _Optional, Default=false_ | ||||
|  | ||||
| Traefik routes requests to the IP/port of the matching container. | ||||
| When setting `useBindPortIP=true`, you tell Traefik to use the IP/Port attached to the container's _binding_ instead of its inner network IP/Port. | ||||
|  | ||||
| When used in conjunction with the `traefik.http.services.<name>.loadbalancer.server.port` label (that tells Traefik to route requests to a specific port), | ||||
| Traefik tries to find a binding on port `traefik.http.services.<name>.loadbalancer.server.port`. | ||||
| If it cannot find such a binding, Traefik falls back on the internal network IP of the container, | ||||
| but still uses the `traefik.http.services.<name>.loadbalancer.server.port` that is set in the label. | ||||
|  | ||||
| ??? example "Examples of `usebindportip` in different situations." | ||||
|  | ||||
|     | port label         | Container's binding                                | Routes to      | | ||||
|     |--------------------|----------------------------------------------------|----------------| | ||||
|     |          -         |           -                                        | IntIP:IntPort  | | ||||
|     |          -         | ExtPort:IntPort                                    | IntIP:IntPort  | | ||||
|     |          -         | ExtIp:ExtPort:IntPort                              | ExtIp:ExtPort  | | ||||
|     | LblPort            |           -                                        | IntIp:LblPort  | | ||||
|     | LblPort            | ExtIp:ExtPort:LblPort                              | ExtIp:ExtPort  | | ||||
|     | LblPort            | ExtIp:ExtPort:OtherPort                            | IntIp:LblPort  | | ||||
|     | LblPort            | ExtIp1:ExtPort1:IntPort1 & ExtIp2:LblPort:IntPort2 | ExtIp2:LblPort | | ||||
|  | ||||
|     !!! info "" | ||||
|         In the above table: | ||||
|  | ||||
|         - `ExtIp` stands for "external IP found in the binding" | ||||
|         - `IntIp` stands for "internal network container's IP", | ||||
|         - `ExtPort` stands for "external Port found in the binding" | ||||
|         - `IntPort` stands for "internal network container's port." | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   swarm: | ||||
|     useBindPortIP: true | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.swarm] | ||||
|   useBindPortIP = true | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.swarm.useBindPortIP=true | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `exposedByDefault` | ||||
|  | ||||
| _Optional, Default=true_ | ||||
|  | ||||
| Expose containers by default through Traefik. | ||||
| If set to `false`, containers that do not have a `traefik.enable=true` label are ignored from the resulting routing configuration. | ||||
|  | ||||
| For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery). | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   swarm: | ||||
|     exposedByDefault: false | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.swarm] | ||||
|   exposedByDefault = false | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.swarm.exposedByDefault=false | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `network` | ||||
|  | ||||
| _Optional, Default=""_ | ||||
|  | ||||
| Defines a default docker network to use for connections to all containers. | ||||
|  | ||||
| This option can be overridden on a per-container basis with the `traefik.docker.network` label. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   swarm: | ||||
|     network: test | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.swarm] | ||||
|   network = "test" | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.swarm.network=test | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `defaultRule` | ||||
|  | ||||
| _Optional, Default=```Host(`{{ normalize .Name }}`)```_ | ||||
|  | ||||
| The `defaultRule` option defines what routing rule to apply to a container if no rule is defined by a label. | ||||
|  | ||||
| It must be a valid [Go template](https://pkg.go.dev/text/template/), and can use | ||||
| [sprig template functions](https://masterminds.github.io/sprig/). | ||||
| The container service name can be accessed with the `Name` identifier, | ||||
| and the template has access to all the labels defined on this container. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   swarm: | ||||
|     defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.swarm] | ||||
|   defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.swarm.defaultRule=Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`) | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `swarmMode` | ||||
|  | ||||
| _Optional, Default=false_ | ||||
|  | ||||
| Enables the Swarm Mode (instead of standalone Docker). | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   swarm: | ||||
|     swarmMode: true | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.swarm] | ||||
|   swarmMode = true | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.swarm.swarmMode=true | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `swarmModeRefreshSeconds` | ||||
|  | ||||
| _Optional, Default=15_ | ||||
|  | ||||
| Defines the polling interval (in seconds) for Swarm Mode. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   swarm: | ||||
|     swarmModeRefreshSeconds: 30 | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.swarm] | ||||
|   swarmModeRefreshSeconds = 30 | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.swarm.swarmModeRefreshSeconds=30 | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `httpClientTimeout` | ||||
|  | ||||
| _Optional, Default=0_ | ||||
|  | ||||
| Defines the client timeout (in seconds) for HTTP connections. If its value is `0`, no timeout is set. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   swarm: | ||||
|     httpClientTimeout: 300 | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.swarm] | ||||
|   httpClientTimeout = 300 | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.swarm.httpClientTimeout=300 | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `watch` | ||||
|  | ||||
| _Optional, Default=true_ | ||||
|  | ||||
| Watch Docker events. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   swarm: | ||||
|     watch: false | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.swarm] | ||||
|   watch = false | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.swarm.watch=false | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `constraints` | ||||
|  | ||||
| _Optional, Default=""_ | ||||
|  | ||||
| The `constraints` option can be set to an expression that Traefik matches against the container labels to determine whether | ||||
| to create any route for that container. If none of the container labels match the expression, no route for that container is | ||||
| created. If the expression is empty, all detected containers are included. | ||||
|  | ||||
| The expression syntax is based on the `Label("key", "value")`, and `LabelRegex("key", "value")` functions, | ||||
| as well as the usual boolean logic, as shown in examples below. | ||||
|  | ||||
| ??? example "Constraints Expression Examples" | ||||
|  | ||||
|     ```toml | ||||
|     # Includes only containers having a label with key `a.label.name` and value `foo` | ||||
|     constraints = "Label(`a.label.name`, `foo`)" | ||||
|     ``` | ||||
|  | ||||
|     ```toml | ||||
|     # Excludes containers having any label with key `a.label.name` and value `foo` | ||||
|     constraints = "!Label(`a.label.name`, `value`)" | ||||
|     ``` | ||||
|  | ||||
|     ```toml | ||||
|     # With logical AND. | ||||
|     constraints = "Label(`a.label.name`, `valueA`) && Label(`another.label.name`, `valueB`)" | ||||
|     ``` | ||||
|  | ||||
|     ```toml | ||||
|     # With logical OR. | ||||
|     constraints = "Label(`a.label.name`, `valueA`) || Label(`another.label.name`, `valueB`)" | ||||
|     ``` | ||||
|  | ||||
|     ```toml | ||||
|     # With logical AND and OR, with precedence set by parentheses. | ||||
|     constraints = "Label(`a.label.name`, `valueA`) && (Label(`another.label.name`, `valueB`) || Label(`yet.another.label.name`, `valueC`))" | ||||
|     ``` | ||||
|  | ||||
|     ```toml | ||||
|     # Includes only containers having a label with key `a.label.name` and a value matching the `a.+` regular expression. | ||||
|     constraints = "LabelRegex(`a.label.name`, `a.+`)" | ||||
|     ``` | ||||
|  | ||||
| For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery). | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   swarm: | ||||
|     constraints: "Label(`a.label.name`,`foo`)" | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.swarm] | ||||
|   constraints = "Label(`a.label.name`,`foo`)" | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.swarm.constraints=Label(`a.label.name`,`foo`) | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| ### `tls` | ||||
|  | ||||
| _Optional_ | ||||
|  | ||||
| Defines the TLS configuration used for the secure connection to Docker. | ||||
|  | ||||
| #### `ca` | ||||
|  | ||||
| _Optional_ | ||||
|  | ||||
| `ca` is the path to the certificate authority used for the secure connection to Docker, | ||||
| it defaults to the system bundle. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   swarm: | ||||
|     tls: | ||||
|       ca: path/to/ca.crt | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.swarm.tls] | ||||
|   ca = "path/to/ca.crt" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.swarm.tls.ca=path/to/ca.crt | ||||
| ``` | ||||
|  | ||||
| #### `cert` | ||||
|  | ||||
| `cert` is the path to the public certificate used for the secure connection to Docker. | ||||
| When using this option, setting the `key` option is required. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   swarm: | ||||
|     tls: | ||||
|       cert: path/to/foo.cert | ||||
|       key: path/to/foo.key | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.swarm.tls] | ||||
|   cert = "path/to/foo.cert" | ||||
|   key = "path/to/foo.key" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.swarm.tls.cert=path/to/foo.cert | ||||
| --providers.swarm.tls.key=path/to/foo.key | ||||
| ``` | ||||
|  | ||||
| #### `key` | ||||
|  | ||||
| _Optional_ | ||||
|  | ||||
| `key` is the path to the private key used for the secure connection Docker. | ||||
| When using this option, setting the `cert` option is required. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   swarm: | ||||
|     tls: | ||||
|       cert: path/to/foo.cert | ||||
|       key: path/to/foo.key | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.swarm.tls] | ||||
|   cert = "path/to/foo.cert" | ||||
|   key = "path/to/foo.key" | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.swarm.tls.cert=path/to/foo.cert | ||||
| --providers.swarm.tls.key=path/to/foo.key | ||||
| ``` | ||||
|  | ||||
| #### `insecureSkipVerify` | ||||
|  | ||||
| _Optional, Default=false_ | ||||
|  | ||||
| If `insecureSkipVerify` is `true`, the TLS connection to Docker accepts any certificate presented by the server regardless of the hostnames it covers. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   swarm: | ||||
|     tls: | ||||
|       insecureSkipVerify: true | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.swarm.tls] | ||||
|   insecureSkipVerify = true | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.swarm.tls.insecureSkipVerify=true | ||||
| ``` | ||||
|  | ||||
| ### `allowEmptyServices` | ||||
|  | ||||
| _Optional, Default=false_ | ||||
|  | ||||
| If the parameter is set to `true`, | ||||
| any [servers load balancer](../routing/services/index.md#servers-load-balancer) defined for Docker containers is created  | ||||
| regardless of the [healthiness](https://docs.docker.com/engine/reference/builder/#healthcheck) of the corresponding containers. | ||||
| It also then stays alive and responsive even at times when it becomes empty, | ||||
| i.e. when all its children containers become unhealthy. | ||||
| This results in `503` HTTP responses instead of `404` ones, | ||||
| in the above cases. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| providers: | ||||
|   swarm: | ||||
|     allowEmptyServices: true | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [providers.swarm] | ||||
|   allowEmptyServices = true | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --providers.swarm.allowEmptyServices=true | ||||
| ``` | ||||
|  | ||||
| {!traefik-for-business-applications.md!} | ||||
| @@ -17,7 +17,7 @@ | ||||
| - "traefik.http.middlewares.middleware05.compress=true" | ||||
| - "traefik.http.middlewares.middleware05.compress.excludedcontenttypes=foobar, foobar" | ||||
| - "traefik.http.middlewares.middleware05.compress.minresponsebodybytes=42" | ||||
| - "traefik.http.middlewares.middleware06.contenttype.autodetect=true" | ||||
| - "traefik.http.middlewares.middleware06.contenttype=true" | ||||
| - "traefik.http.middlewares.middleware07.digestauth.headerfield=foobar" | ||||
| - "traefik.http.middlewares.middleware07.digestauth.realm=foobar" | ||||
| - "traefik.http.middlewares.middleware07.digestauth.removeheader=true" | ||||
| @@ -31,7 +31,6 @@ | ||||
| - "traefik.http.middlewares.middleware09.forwardauth.authresponseheadersregex=foobar" | ||||
| - "traefik.http.middlewares.middleware09.forwardauth.authrequestheaders=foobar, foobar" | ||||
| - "traefik.http.middlewares.middleware09.forwardauth.tls.ca=foobar" | ||||
| - "traefik.http.middlewares.middleware09.forwardauth.tls.caoptional=true" | ||||
| - "traefik.http.middlewares.middleware09.forwardauth.tls.cert=foobar" | ||||
| - "traefik.http.middlewares.middleware09.forwardauth.tls.insecureskipverify=true" | ||||
| - "traefik.http.middlewares.middleware09.forwardauth.tls.key=foobar" | ||||
| @@ -54,7 +53,6 @@ | ||||
| - "traefik.http.middlewares.middleware10.headers.customrequestheaders.name1=foobar" | ||||
| - "traefik.http.middlewares.middleware10.headers.customresponseheaders.name0=foobar" | ||||
| - "traefik.http.middlewares.middleware10.headers.customresponseheaders.name1=foobar" | ||||
| - "traefik.http.middlewares.middleware10.headers.featurepolicy=foobar" | ||||
| - "traefik.http.middlewares.middleware10.headers.forcestsheader=true" | ||||
| - "traefik.http.middlewares.middleware10.headers.framedeny=true" | ||||
| - "traefik.http.middlewares.middleware10.headers.hostsproxyheaders=foobar, foobar" | ||||
| @@ -62,18 +60,14 @@ | ||||
| - "traefik.http.middlewares.middleware10.headers.permissionspolicy=foobar" | ||||
| - "traefik.http.middlewares.middleware10.headers.publickey=foobar" | ||||
| - "traefik.http.middlewares.middleware10.headers.referrerpolicy=foobar" | ||||
| - "traefik.http.middlewares.middleware10.headers.sslforcehost=true" | ||||
| - "traefik.http.middlewares.middleware10.headers.sslhost=foobar" | ||||
| - "traefik.http.middlewares.middleware10.headers.sslproxyheaders.name0=foobar" | ||||
| - "traefik.http.middlewares.middleware10.headers.sslproxyheaders.name1=foobar" | ||||
| - "traefik.http.middlewares.middleware10.headers.sslredirect=true" | ||||
| - "traefik.http.middlewares.middleware10.headers.ssltemporaryredirect=true" | ||||
| - "traefik.http.middlewares.middleware10.headers.stsincludesubdomains=true" | ||||
| - "traefik.http.middlewares.middleware10.headers.stspreload=true" | ||||
| - "traefik.http.middlewares.middleware10.headers.stsseconds=42" | ||||
| - "traefik.http.middlewares.middleware11.ipwhitelist.ipstrategy.depth=42" | ||||
| - "traefik.http.middlewares.middleware11.ipwhitelist.ipstrategy.excludedips=foobar, foobar" | ||||
| - "traefik.http.middlewares.middleware11.ipwhitelist.sourcerange=foobar, foobar" | ||||
| - "traefik.http.middlewares.middleware11.ipallowlist.ipstrategy.depth=42" | ||||
| - "traefik.http.middlewares.middleware11.ipallowlist.ipstrategy.excludedips=foobar, foobar" | ||||
| - "traefik.http.middlewares.middleware11.ipallowlist.sourcerange=foobar, foobar" | ||||
| - "traefik.http.middlewares.middleware12.inflightreq.amount=42" | ||||
| - "traefik.http.middlewares.middleware12.inflightreq.sourcecriterion.ipstrategy.depth=42" | ||||
| - "traefik.http.middlewares.middleware12.inflightreq.sourcecriterion.ipstrategy.excludedips=foobar, foobar" | ||||
| @@ -118,9 +112,9 @@ | ||||
| - "traefik.http.middlewares.middleware19.replacepathregex.replacement=foobar" | ||||
| - "traefik.http.middlewares.middleware20.retry.attempts=42" | ||||
| - "traefik.http.middlewares.middleware20.retry.initialinterval=42" | ||||
| - "traefik.http.middlewares.middleware21.stripprefix.forceslash=true" | ||||
| - "traefik.http.middlewares.middleware21.stripprefix.prefixes=foobar, foobar" | ||||
| - "traefik.http.middlewares.middleware22.stripprefixregex.regex=foobar, foobar" | ||||
| - "traefik.http.middlewares.middleware23.grpcweb.alloworigins=foobar, foobar" | ||||
| - "traefik.http.routers.router0.entrypoints=foobar, foobar" | ||||
| - "traefik.http.routers.router0.middlewares=foobar, foobar" | ||||
| - "traefik.http.routers.router0.priority=42" | ||||
| @@ -152,8 +146,10 @@ | ||||
| - "traefik.http.services.service01.loadbalancer.healthcheck.interval=foobar" | ||||
| - "traefik.http.services.service01.loadbalancer.healthcheck.path=foobar" | ||||
| - "traefik.http.services.service01.loadbalancer.healthcheck.method=foobar" | ||||
| - "traefik.http.services.service01.loadbalancer.healthcheck.status=42" | ||||
| - "traefik.http.services.service01.loadbalancer.healthcheck.port=42" | ||||
| - "traefik.http.services.service01.loadbalancer.healthcheck.scheme=foobar" | ||||
| - "traefik.http.services.service01.loadbalancer.healthcheck.mode=foobar" | ||||
| - "traefik.http.services.service01.loadbalancer.healthcheck.timeout=foobar" | ||||
| - "traefik.http.services.service01.loadbalancer.passhostheader=true" | ||||
| - "traefik.http.services.service01.loadbalancer.responseforwarding.flushinterval=foobar" | ||||
| @@ -165,7 +161,7 @@ | ||||
| - "traefik.http.services.service01.loadbalancer.sticky.cookie.secure=true" | ||||
| - "traefik.http.services.service01.loadbalancer.server.port=foobar" | ||||
| - "traefik.http.services.service01.loadbalancer.server.scheme=foobar" | ||||
| - "traefik.tcp.middlewares.tcpmiddleware00.ipwhitelist.sourcerange=foobar, foobar" | ||||
| - "traefik.tcp.middlewares.tcpmiddleware00.ipallowlist.sourcerange=foobar, foobar" | ||||
| - "traefik.tcp.middlewares.tcpmiddleware01.inflightconn.amount=42" | ||||
| - "traefik.tcp.routers.tcprouter0.entrypoints=foobar, foobar" | ||||
| - "traefik.tcp.routers.tcprouter0.middlewares=foobar, foobar" | ||||
| @@ -194,8 +190,9 @@ | ||||
| - "traefik.tcp.routers.tcprouter1.tls.options=foobar" | ||||
| - "traefik.tcp.routers.tcprouter1.tls.passthrough=true" | ||||
| - "traefik.tcp.services.tcpservice01.loadbalancer.proxyprotocol.version=42" | ||||
| - "traefik.tcp.services.tcpservice01.loadbalancer.terminationdelay=42" | ||||
| - "traefik.tcp.services.tcpservice01.loadbalancer.server.port=foobar" | ||||
| - "traefik.tcp.services.tcpservice01.loadbalancer.server.tls=true" | ||||
| - "traefik.tcp.services.tcpservice01.loadbalancer.serverstransport=foobar" | ||||
| - "traefik.udp.routers.udprouter0.entrypoints=foobar, foobar" | ||||
| - "traefik.udp.routers.udprouter0.service=foobar" | ||||
| - "traefik.udp.routers.udprouter1.entrypoints=foobar, foobar" | ||||
|   | ||||
| @@ -8,7 +8,7 @@ description: "Reference dynamic configuration with Docker labels in Traefik Prox | ||||
| Dynamic configuration with Docker Labels | ||||
| {: .subtitle } | ||||
|  | ||||
| The labels are case insensitive. | ||||
| The labels are case-insensitive. | ||||
|  | ||||
| ```yaml | ||||
| labels: | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user