diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 022db925c..a6f131353 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -16,36 +16,7 @@ env: jobs: build-webui: - runs-on: ubuntu-latest - - steps: - - name: Check out code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Setup node - uses: actions/setup-node@v4 - with: - node-version-file: webui/.nvmrc - cache: yarn - cache-dependency-path: webui/yarn.lock - - - name: Build webui - working-directory: ./webui - run: | - yarn install - yarn build - - - name: Package webui - run: | - tar czvf webui.tar.gz ./webui/static/ - - - name: Artifact webui - uses: actions/upload-artifact@v4 - with: - name: webui.tar.gz - path: webui.tar.gz + uses: ./.github/workflows/template-webui.yaml build: runs-on: ubuntu-latest @@ -97,7 +68,9 @@ jobs: name: webui.tar.gz - name: Untar webui - run: tar xvf webui.tar.gz + run: | + tar xvf webui.tar.gz + rm webui.tar.gz - name: Build env: diff --git a/.github/workflows/experimental.yaml b/.github/workflows/experimental.yaml index aadce96a8..b089beabc 100644 --- a/.github/workflows/experimental.yaml +++ b/.github/workflows/experimental.yaml @@ -12,34 +12,25 @@ env: jobs: + build-webui: + if: github.repository == 'traefik/traefik' + uses: ./.github/workflows/template-webui.yaml + experimental: if: github.repository == 'traefik/traefik' name: Build experimental image on branch runs-on: ubuntu-latest steps: - - # https://github.com/marketplace/actions/checkout - name: Check out code uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Setup node - uses: actions/setup-node@v4 - with: - node-version-file: webui/.nvmrc - cache: yarn - cache-dependency-path: webui/yarn.lock - - - name: Build webui - working-directory: ./webui - run: | - yarn install - yarn build - - name: Set up Go ${{ env.GO_VERSION }} uses: actions/setup-go@v5 + env: + ImageOS: ${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.goarm }} with: go-version: ${{ env.GO_VERSION }} @@ -61,6 +52,16 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 + - name: Artifact webui + uses: actions/download-artifact@v4 + with: + name: webui.tar.gz + + - name: Untar webui + run: | + tar xvf webui.tar.gz + rm webui.tar.gz + - name: Build docker experimental image env: DOCKER_BUILDX_ARGS: "--push" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 000000000..6ecda4432 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,127 @@ +name: Release + +on: + push: + tags: + - 'v*.*.*' + +env: + GO_VERSION: '1.23' + CGO_ENABLED: 0 + VERSION: ${{ github.ref_name }} + TRAEFIKER_EMAIL: "traefiker@traefik.io" + CODENAME: munster + +jobs: + + build-webui: + if: github.ref_type == 'tag' + uses: ./.github/workflows/template-webui.yaml + + build: + if: github.ref_type == 'tag' + runs-on: ubuntu-latest + + strategy: + matrix: + os: [ linux-amd64, linux-386, linux-arm, linux-arm64, linux-ppc64le, linux-s390x, linux-riscv64, darwin, windows-amd64, windows-arm64, windows-386, freebsd, openbsd ] + needs: + - build-webui + + steps: + - name: Check out code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Go ${{ env.GO_VERSION }} + uses: actions/setup-go@v5 + env: + # Ensure cache consistency on Linux, see https://github.com/actions/setup-go/pull/383 + ImageOS: ${{ matrix.os }} + with: + go-version: ${{ env.GO_VERSION }} + + - name: Artifact webui + uses: actions/download-artifact@v4 + with: + name: webui.tar.gz + + - name: Untar webui + run: | + tar xvf webui.tar.gz + rm webui.tar.gz + + - name: Go generate + run: go generate + + + - name: Generate goreleaser file + run: | + GORELEASER_CONFIG_FILE_PATH=$(go run ./internal/release "${{ matrix.os }}") + echo "GORELEASER_CONFIG_FILE_PATH=$GORELEASER_CONFIG_FILE_PATH" >> $GITHUB_ENV + + - name: Build with goreleaser + uses: goreleaser/goreleaser-action@v6 + with: + distribution: goreleaser + # 'latest', 'nightly', or a semver + version: '~> v2' + args: release --clean --timeout="90m" --config "${{ env.GORELEASER_CONFIG_FILE_PATH }}" + + - name: Artifact binaries + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.os }}-binaries + path: | + dist/**/*_checksums.txt + dist/**/*.tar.gz + dist/**/*.zip + retention-days: 1 + + release: + if: github.ref_type == 'tag' + runs-on: ubuntu-latest + + needs: + - build + + steps: + - name: Check out code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Retrieve the secret and decode it to a file + env: + TRAEFIKER_RSA: ${{ secrets.TRAEFIKER_RSA }} + run: | + mkdir -p ~/.ssh + echo "${TRAEFIKER_RSA}" | base64 --decode > ~/.ssh/traefiker_rsa + + - name: Download All Artifacts + uses: actions/download-artifact@v4 + with: + path: dist/ + pattern: "*-binaries" + merge-multiple: true + + - name: Publish Release + env: + GH_TOKEN: ${{ github.token }} + run: | + cat dist/**/*_checksums.txt >> "dist/traefik_${VERSION}_checksums.txt" + rm dist/**/*_checksums.txt + tar cfz "dist/traefik-${VERSION}.src.tar.gz" \ + --exclude-vcs \ + --exclude .idea \ + --exclude .travis \ + --exclude .semaphoreci \ + --exclude .github \ + --exclude dist . + + chown -R "$(id -u)":"$(id -g)" dist/ + gh release create ${VERSION} ./dist/**/traefik*.{zip,tar.gz} ./dist/traefik*.{tar.gz,txt} --repo traefik/traefik --title ${VERSION} --notes ${VERSION} + + ./script/deploy.sh + diff --git a/.github/workflows/template-webui.yaml b/.github/workflows/template-webui.yaml new file mode 100644 index 000000000..df52d75c1 --- /dev/null +++ b/.github/workflows/template-webui.yaml @@ -0,0 +1,37 @@ +name: Build Web UI +on: + workflow_call: {} +jobs: + + build-webui: + runs-on: ubuntu-latest + + steps: + - name: Check out code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup node + uses: actions/setup-node@v4 + with: + node-version-file: webui/.nvmrc + cache: yarn + cache-dependency-path: webui/yarn.lock + + - name: Build webui + working-directory: ./webui + run: | + yarn install + yarn build + + - name: Package webui + run: | + tar czvf webui.tar.gz ./webui/static/ + + - name: Artifact webui + uses: actions/upload-artifact@v4 + with: + name: webui.tar.gz + path: webui.tar.gz + retention-days: 1 diff --git a/.goreleaser.yml.tmpl b/.goreleaser.yml.tmpl index 5deda441e..fbd27891b 100644 --- a/.goreleaser.yml.tmpl +++ b/.goreleaser.yml.tmpl @@ -1,12 +1,11 @@ project_name: traefik +version: 2 +[[if .GOARCH]] +dist: "./dist/[[ .GOOS ]]-[[ .GOARCH ]]" +[[else]] dist: "./dist/[[ .GOOS ]]" - -[[ if eq .GOOS "linux" ]] -before: - hooks: - - go generate -[[ end ]] +[[end]] builds: - binary: traefik @@ -21,6 +20,9 @@ builds: goos: - "[[ .GOOS ]]" goarch: + [[if .GOARCH]] + - "[[ .GOARCH ]]" + [[else]] - amd64 - '386' - arm @@ -28,6 +30,7 @@ builds: - ppc64le - s390x - riscv64 + [[end]] goarm: - '7' - '6' diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index f72f19b6a..32f22b2b8 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -1,63 +1,13 @@ version: v1.0 -name: Traefik +name: Traefik Release - deprecated agent: machine: - type: e1-standard-4 - os_image: ubuntu2004 - -fail_fast: - stop: - when: "branch != 'master'" - -auto_cancel: - queued: - when: "branch != 'master'" - running: - when: "branch != 'master'" - -global_job_config: - prologue: - commands: - - curl -sSfL https://raw.githubusercontent.com/ldez/semgo/master/godownloader.sh | sudo sh -s -- -b "/usr/local/bin" - - sudo semgo go1.23 - - export "GOPATH=$(go env GOPATH)" - - export "SEMAPHORE_GIT_DIR=${GOPATH}/src/github.com/traefik/${SEMAPHORE_PROJECT_NAME}" - - export "PATH=${GOPATH}/bin:${PATH}" - - mkdir -vp "${SEMAPHORE_GIT_DIR}" "${GOPATH}/bin" - - export GOPROXY=https://proxy.golang.org,direct - - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "${GOPATH}/bin" v1.62.0 - - curl -sSfL https://gist.githubusercontent.com/traefiker/6d7ac019c11d011e4f131bb2cca8900e/raw/goreleaser.sh | bash -s -- -b "${GOPATH}/bin" - - checkout - - cache restore traefik-$(checksum go.sum) - + type: f1-standard-2 + os_image: ubuntu2204 blocks: - - name: Release - dependencies: [] - run: - when: "tag =~ '.*'" + - name: 'Do nothing' task: - agent: - machine: - type: e1-standard-8 - os_image: ubuntu2004 - secrets: - - name: traefik - env_vars: - - name: GH_VERSION - value: 2.32.1 - - name: CODENAME - value: "munster" - prologue: - commands: - - export VERSION=${SEMAPHORE_GIT_TAG_NAME} - - 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 /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 + - name: 'Do nothing' commands: - - make release-packages - - gh release create ${SEMAPHORE_GIT_TAG_NAME} ./dist/**/traefik*.{zip,tar.gz} ./dist/traefik*.{tar.gz,txt} --repo traefik/traefik --title ${SEMAPHORE_GIT_TAG_NAME} --notes ${SEMAPHORE_GIT_TAG_NAME} - - ./script/deploy.sh + - echo "Do nothing" diff --git a/CHANGELOG.md b/CHANGELOG.md index fb05b47b8..68543f6aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,24 @@ +## [v3.2.2](https://github.com/traefik/traefik/tree/v3.2.2) (2024-12-10) +[All Commits](https://github.com/traefik/traefik/compare/v3.2.1...v3.2.2) + +**Bug fixes:** +- **[docker,docker/swarm]** Rename traefik.docker.* labels for Docker Swarm to traefik.swarm.* ([#11247](https://github.com/traefik/traefik/pull/11247) by [anchal00](https://github.com/anchal00)) +- **[k8s/gatewayapi]** Update sigs.k8s.io/gateway-api to v1.2.1 ([#11314](https://github.com/traefik/traefik/pull/11314) by [kevinpollet](https://github.com/kevinpollet)) +- **[plugins]** Fix WASM settings ([#11321](https://github.com/traefik/traefik/pull/11321) by [juliens](https://github.com/juliens)) +- **[rules]** Fix models mechanism for default rule syntax ([#11300](https://github.com/traefik/traefik/pull/11300) by [rtribotte](https://github.com/rtribotte)) + +**Documentation:** +- Move callout to the entrypoint page footer ([#11305](https://github.com/traefik/traefik/pull/11305) by [kevinpollet](https://github.com/kevinpollet)) +- Fix incorrect links in v3 migration sections ([#11297](https://github.com/traefik/traefik/pull/11297) by [kevinpollet](https://github.com/kevinpollet)) +- New Install Reference Documentation ([#11213](https://github.com/traefik/traefik/pull/11213) by [sheddy-traefik](https://github.com/sheddy-traefik)) + +## [v2.11.15](https://github.com/traefik/traefik/tree/v2.11.15) (2024-12-06) +[All Commits](https://github.com/traefik/traefik/compare/v2.11.14...v2.11.15) + +**Bug fixes:** +- **[acme]** Update go-acme/lego to v4.20.4 ([#11295](https://github.com/traefik/traefik/pull/11295) by [ldez](https://github.com/ldez)) +- **[http3]** Update github.com/quic-go/quic-go to v0.48.2 ([#11320](https://github.com/traefik/traefik/pull/11320) by [kevinpollet](https://github.com/kevinpollet)) + ## [v3.2.1](https://github.com/traefik/traefik/tree/v3.2.1) (2024-11-20) [All Commits](https://github.com/traefik/traefik/compare/v3.2.0...v3.2.1) diff --git a/Dockerfile b/Dockerfile index 28f5e946a..fcf9c49b9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1.2 -FROM alpine:3.20 +FROM alpine:3.21 RUN apk add --no-cache --no-progress ca-certificates tzdata diff --git a/docs/check.Dockerfile b/docs/check.Dockerfile index 824a97081..015e6f595 100644 --- a/docs/check.Dockerfile +++ b/docs/check.Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.20 +FROM alpine:3.21 RUN apk --no-cache --no-progress add \ build-base \ @@ -14,7 +14,7 @@ RUN apk --no-cache --no-progress add \ ruby-json \ zlib-dev -RUN gem install nokogiri --version 1.15.3 --no-document -- --use-system-libraries +RUN gem install nokogiri --version 1.16.8 --no-document -- --use-system-libraries RUN gem install html-proofer --version 5.0.7 --no-document -- --use-system-libraries # After Ruby, some NodeJS YAY! diff --git a/docs/content/middlewares/http/basicauth.md b/docs/content/middlewares/http/basicauth.md index 6e5105a5b..68c341a39 100644 --- a/docs/content/middlewares/http/basicauth.md +++ b/docs/content/middlewares/http/basicauth.md @@ -341,4 +341,5 @@ http: [http.middlewares.test-auth.basicAuth] removeHeader = true ``` + {!traefik-for-business-applications.md!} diff --git a/docs/content/migration/v3.md b/docs/content/migration/v3.md index 939cb5f73..01247407e 100644 --- a/docs/content/migration/v3.md +++ b/docs/content/migration/v3.md @@ -80,7 +80,7 @@ Please use the `disableClusterScopeResources` option instead to avoid cluster sc ### Kubernetes CRD Provider -Starting with v3.2, the CRDs has been updated on [TraefikService](../routing/services#mirroring-service) (PR [#11032](https://github.com/traefik/traefik/pull/11032)), on [RateLimit](../middlewares/http/ratelimit) & [InFlightReq](../middlewares/http/inflightreq) middlewares (PR [#9747](https://github.com/traefik/traefik/pull/9747)) and on [Compress](../middlewares/http/compress) middleware (PR [#10943](https://github.com/traefik/traefik/pull/10943)). +Starting with v3.2, the CRDs has been updated on [TraefikService](../../routing/services#mirroring-service) (PR [#11032](https://github.com/traefik/traefik/pull/11032)), on [RateLimit](../../middlewares/http/ratelimit) & [InFlightReq](../../middlewares/http/inflightreq) middlewares (PR [#9747](https://github.com/traefik/traefik/pull/9747)) and on [Compress](../../middlewares/http/compress) middleware (PR [#10943](https://github.com/traefik/traefik/pull/10943)). This update adds only new optional fields. CRDs can be updated with this command: @@ -93,7 +93,7 @@ kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.2/docs/con Starting with v3.2, the Kubernetes Gateway Provider now supports [GRPCRoute](https://gateway-api.sigs.k8s.io/api-types/grpcroute/). -Therefore, in the corresponding RBACs (see [KubernetesGateway](../reference/dynamic-configuration/kubernetes-gateway.md#rbac) provider RBACs), +Therefore, in the corresponding RBACs (see [KubernetesGateway](../reference/dynamic-configuration/kubernetes-gateway-rbac.yml) provider RBACs), the `grcroutes` and `grpcroutes/status` rights have to be added. ```yaml @@ -124,8 +124,8 @@ the `grcroutes` and `grpcroutes/status` rights have to be added. Starting with v3.2, the Kubernetes Gateway Provider now supports [BackendTLSPolicy](https://gateway-api.sigs.k8s.io/api-types/backendtlspolicy/). -Therefore, in the corresponding RBACs (see [KubernetesGateway](../reference/dynamic-configuration/kubernetes-gateway.md#rbac) provider RBACs), -the `configmaps`, `backendtlspolicies` and `backendtlspolicies/status` rights have to be added. +Therefore, in the corresponding RBACs (see [KubernetesGateway](../reference/dynamic-configuration/kubernetes-gateway-rbac.yml) provider RBACs), +the `backendtlspolicies` and `backendtlspolicies/status` rights have to be added. ```yaml ... @@ -161,6 +161,13 @@ the `configmaps`, `backendtlspolicies` and `backendtlspolicies/status` rights ha In `v3.2.1`, the `X-Forwarded-Prefix` header is now handled like the other `X-Forwarded-*` headers: Traefik removes it when it's sent from an untrusted source. Please refer to the Forwarded headers [documentation](../routing/entrypoints.md#forwarded-headers) for more details. +## v3.2.2 + +### Swarm Provider + +In `v3.2.2`, the `traefik.docker.network` and `traefik.docker.lbswarm` labels have been deprecated, +please use the `traefik.swarm.network` and `traefik.swarm.lbswarm` labels instead. + ## v3.2 to v3.3 ### ACME DNS Certificate Resolver diff --git a/docs/content/providers/kubernetes-gateway.md b/docs/content/providers/kubernetes-gateway.md index e21309df8..a8edfadcc 100644 --- a/docs/content/providers/kubernetes-gateway.md +++ b/docs/content/providers/kubernetes-gateway.md @@ -5,7 +5,7 @@ description: "Learn how to use the Kubernetes Gateway API as a provider for conf # Traefik & Kubernetes with Gateway API -The Kubernetes Gateway provider is a Traefik implementation of the [Gateway API](https://gateway-api.sigs.k8s.io/) +The Kubernetes Gateway provider is a Traefik implementation of the [Gateway API](https://gateway-api.sigs.k8s.io/) specification from the Kubernetes Special Interest Groups (SIGs). This provider supports Standard version [v1.2.0](https://github.com/kubernetes-sigs/gateway-api/releases/tag/v1.2.0) of the Gateway API specification. @@ -20,7 +20,7 @@ For more details, check out the conformance [report](https://github.com/kubernet !!! info "Helm Chart" - When using the Traefik [Helm Chart](../getting-started/install-traefik.md#use-the-helm-chart), the CRDs (Custom Resource Definitions) and RBAC (Role-Based Access Control) are automatically managed for you. + When using the Traefik [Helm Chart](../getting-started/install-traefik.md#use-the-helm-chart), the CRDs (Custom Resource Definitions) and RBAC (Role-Based Access Control) are automatically managed for you. The only remaining task is to enable the `kubernetesGateway` in the chart [values](https://github.com/traefik/traefik-helm-chart/blob/master/traefik/values.yaml#L130). 1. Install/update the Kubernetes Gateway API CRDs. @@ -38,7 +38,7 @@ For more details, check out the conformance [report](https://github.com/kubernet ``` 3. Deploy Traefik and enable the `kubernetesGateway` provider in the static configuration as detailed below: - + ```yaml tab="File (YAML)" providers: kubernetesGateway: {} @@ -54,9 +54,9 @@ For more details, check out the conformance [report](https://github.com/kubernet ## Routing Configuration -When using the Kubernetes Gateway API provider, Traefik uses the Gateway API CRDs to retrieve its routing configuration. -Check out the Gateway API concepts [documentation](https://gateway-api.sigs.k8s.io/concepts/api-overview/), -and the dedicated [routing section](../routing/providers/kubernetes-gateway.md) in the Traefik documentation. +When using the Kubernetes Gateway API provider, Traefik uses the Gateway API CRDs to retrieve its routing configuration. +Check out the Gateway API concepts [documentation](https://gateway-api.sigs.k8s.io/concepts/api-overview/), +and the dedicated [routing section](../routing/providers/kubernetes-gateway.md) in the Traefik documentation. ## Provider Configuration diff --git a/docs/content/providers/swarm.md b/docs/content/providers/swarm.md index 746f44513..db01f4d72 100644 --- a/docs/content/providers/swarm.md +++ b/docs/content/providers/swarm.md @@ -247,7 +247,7 @@ See the [Docker Swarm API Access](#docker-api-access) section for more informati ```yaml tab="File (YAML)" providers: - docker: + swarm: endpoint: "ssh://traefik@192.168.2.5:2022" # ... ``` diff --git a/docs/content/reference/dynamic-configuration/swarm.yml b/docs/content/reference/dynamic-configuration/swarm.yml index 6f9e1c62f..1b40b4483 100644 --- a/docs/content/reference/dynamic-configuration/swarm.yml +++ b/docs/content/reference/dynamic-configuration/swarm.yml @@ -1,3 +1,3 @@ - "traefik.enable=true" -- "traefik.docker.network=foobar" -- "traefik.docker.lbswarm=true" +- "traefik.swarm.network=foobar" +- "traefik.swarm.lbswarm=true" diff --git a/docs/content/reference/install-configuration/api-dashboard.md b/docs/content/reference/install-configuration/api-dashboard.md new file mode 100644 index 000000000..ed485d499 --- /dev/null +++ b/docs/content/reference/install-configuration/api-dashboard.md @@ -0,0 +1,235 @@ +--- +title: "Traefik API & Dashboard Documentation" +description: "Traefik Proxy exposes information through API handlers and showcase them on the Dashboard. Learn about the security, configuration, and endpoints of the APIs and Dashboard. Read the technical documentation." +--- + +The dashboard is the central place that shows you the current active routes handled by Traefik. + +
+ Dashboard - Providers +
The dashboard in action
+
+ +## Configuration Example + +Enable the dashboard: + +```yaml tab="File(YAML)" +api: {} +``` + +```toml tab="File(TOML)" +[api] +``` + +```cli tab="CLI" +--api=true +``` + +Expose the dashboard: + +```yaml tab="Kubernetes CRD" +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: traefik-dashboard +spec: + routes: + - match: Host(`traefik.example.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`)) + kind: Rule + services: + - name: api@internal + kind: TraefikService + middlewares: + - name: auth +--- +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: auth +spec: + basicAuth: + secret: secretName # Kubernetes secret named "secretName" +``` + +```yaml tab="Helm Chart Values (values.yaml)" +# Create an IngressRoute for the dashboard +ingressRoute: + dashboard: + enabled: true + # Custom match rule with host domain + matchRule: Host(`traefik.example.com`) + entryPoints: ["websecure"] + # Add custom middlewares : authentication and redirection + middlewares: + - name: traefik-dashboard-auth + +# Create the custom middlewares used by the IngressRoute dashboard (can also be created in another way). +# /!\ Yes, you need to replace "changeme" password with a better one. /!\ +extraObjects: + - apiVersion: v1 + kind: Secret + metadata: + name: traefik-dashboard-auth-secret + type: kubernetes.io/basic-auth + stringData: + username: admin + password: changeme + + - apiVersion: traefik.io/v1alpha1 + kind: Middleware + metadata: + name: traefik-dashboard-auth + spec: + basicAuth: + secret: traefik-dashboard-auth-secret +``` + +```yaml tab="Docker" +# 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="Swarm" +# Dynamic Configuration +deploy: + 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" + # Dummy service for Swarm port detection. The port can be any valid integer value. + - "traefik.http.services.dummy-svc.loadbalancer.server.port=9999" +``` + +```yaml tab="Consul Catalog" +# Dynamic Configuration +- "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: + routers: + dashboard: + rule: Host(`traefik.example.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`)) + service: api@internal + middlewares: + - auth + middlewares: + auth: + basicAuth: + users: + - "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" + - "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" +``` + +```toml tab="File (TOML)" +# Dynamic Configuration +[http.routers.my-api] + rule = "Host(`traefik.example.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))" + service = "api@internal" + middlewares = ["auth"] + +[http.middlewares.auth.basicAuth] + users = [ + "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", + "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", + ] +``` + +## Configuration Options + +The API and the dashboard can be configured: + +- In the Helm Chart: You can find the options to customize the Traefik installation +enabing the dashboard [here](https://github.com/traefik/traefik-helm-chart/blob/master/traefik/values.yaml#L155). +- In the Traefik Static Configuration as described below. + +| Field | Description | Default | Required | +|:-----------|:---------------------------------|:--------|:---------| +| `api` | Enable api/dashboard. When set to `true`, its sub option `api.dashboard` is also set to true.| false | No | +| `api.dashboard` | Enable dashboard. | false | No | +| `api.debug` | Enable additional endpoints for debugging and profiling. | false | No | +| `api.disabledashboardad` | Disable the advertisement from the dashboard. | false | No | +| `api.insecure` | Enable the API and the dashboard on the entryPoint named traefik.| false | No | + +## Endpoints + +All the following endpoints must be accessed with a `GET` HTTP request. + +| Path | Description | +|--------------------------------|---------------------------------------------------------------------------------------------| +| `/api/http/routers` | Lists all the HTTP routers information. | +| `/api/http/routers/{name}` | Returns the information of the HTTP router specified by `name`. | +| `/api/http/services` | Lists all the HTTP services information. | +| `/api/http/services/{name}` | Returns the information of the HTTP service specified by `name`. | +| `/api/http/middlewares` | Lists all the HTTP middlewares information. | +| `/api/http/middlewares/{name}` | Returns the information of the HTTP middleware specified by `name`. | +| `/api/tcp/routers` | Lists all the TCP routers information. | +| `/api/tcp/routers/{name}` | Returns the information of the TCP router specified by `name`. | +| `/api/tcp/services` | Lists all the TCP services information. | +| `/api/tcp/services/{name}` | Returns the information of the TCP service specified by `name`. | +| `/api/tcp/middlewares` | Lists all the TCP middlewares information. | +| `/api/tcp/middlewares/{name}` | Returns the information of the TCP middleware specified by `name`. | +| `/api/udp/routers` | Lists all the UDP routers information. | +| `/api/udp/routers/{name}` | Returns the information of the UDP router specified by `name`. | +| `/api/udp/services` | Lists all the UDP services information. | +| `/api/udp/services/{name}` | Returns the information of the UDP service specified by `name`. | +| `/api/entrypoints` | Lists all the entry points information. | +| `/api/entrypoints/{name}` | Returns the information of the entry point specified by `name`. | +| `/api/overview` | Returns statistic information about HTTP, TCP and about enabled features and providers. | +| `/api/rawdata` | Returns information about dynamic configurations, errors, status and dependency relations. | +| `/api/version` | Returns information about Traefik version. | +| `/debug/vars` | See the [expvar](https://golang.org/pkg/expvar/) Go documentation. | +| `/debug/pprof/` | See the [pprof Index](https://golang.org/pkg/net/http/pprof/#Index) Go documentation. | +| `/debug/pprof/cmdline` | See the [pprof Cmdline](https://golang.org/pkg/net/http/pprof/#Cmdline) Go documentation. | +| `/debug/pprof/profile` | See the [pprof Profile](https://golang.org/pkg/net/http/pprof/#Profile) Go documentation. | +| `/debug/pprof/symbol` | See the [pprof Symbol](https://golang.org/pkg/net/http/pprof/#Symbol) Go documentation. | +| `/debug/pprof/trace` | See the [pprof Trace](https://golang.org/pkg/net/http/pprof/#Trace) Go documentation. | + +## Dashboard + +The dashboard is available at the same location as the [API](../../operations/api.md), but by default on the path `/dashboard/`. + +!!! note + + - The trailing slash `/` in `/dashboard/` is mandatory. This limitation can be mitigated using the the [RedirectRegex Middleware](../../middlewares/http/redirectregex.md). + - There is also a redirect from the path `/` to `/dashboard/`, but you should not rely on this behavior, as it is subject to change and may complicate routing rules. + +To securely access the dashboard, you need to define a routing configuration within Traefik. This involves setting up a router attached to the service `api@internal`, which allows you to: + +- Implement security features using [middlewares](../../middlewares/overview.md), such as authentication ([basicAuth](../../middlewares/http/basicauth.md), [digestAuth](../../middlewares/http/digestauth.md), + [forwardAuth](../../middlewares/http/forwardauth.md)) or [allowlisting](../../middlewares/http/ipallowlist.md). + +- Define a [router rule](#dashboard-router-rule) for accessing the dashboard through Traefik. + +### Dashboard Router Rule + +To ensure proper access to the dashboard, the [router rule](../../routing/routers/index.md#rule) you define must match requests intended for the `/api` and `/dashboard` paths. +We recommend using either a *Host-based rule* to match all requests on the desired domain or explicitly defining a rule that includes both path prefixes. +Here are some examples: + +```bash tab="Host Rule" +# The dashboard can be accessed on http://traefik.example.com/dashboard/ +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`) || 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`) || PathPrefix(`/dashboard`))" +``` + +{!traefik-for-business-applications.md!} diff --git a/docs/content/reference/install-configuration/boot-environment.md b/docs/content/reference/install-configuration/boot-environment.md new file mode 100644 index 000000000..223977752 --- /dev/null +++ b/docs/content/reference/install-configuration/boot-environment.md @@ -0,0 +1,134 @@ +--- +title: "Traefik Configuration Overview" +description: "Read the official Traefik documentation to get started with configuring the Traefik Proxy." +--- + +# Boot Environment + +Traefik Proxy’s configuration is divided into two main categories: + +- **Static Configuration**: Defines parameters that require Traefik to restart when changed. This includes entry points, providers, API/dashboard settings, and logging levels. +- **Dynamic Configuration**: Involves elements that can be updated without restarting Traefik, such as routers, services, and middlewares. + +This section focuses on setting up the static configuration, which is essential for Traefik’s initial boot. + +## Configuration Methods + +Traefik offers multiple methods to define static configuration. + +!!! warning "Note" + It’s crucial to choose one method and stick to it, as mixing different configuration options is not supported and can lead to unexpected behavior. + +Here are the methods available for configuring the Traefik proxy: + +- [File](#file) +- [CLI](#cli) +- [Environment Variables](#environment-variables) +- [Helm](#helm) + +## File + +You can define the static configuration in a file using formats like YAML or TOML. + +### Configuration Example + +```yaml tab="traefik.yml (YAML)" +entryPoints: + web: + address: ":80" + websecure: + address: ":443" + +providers: + docker: {} + +api: + dashboard: true + +log: + level: INFO +``` + +```toml tab="traefik.toml (TOML)" +[entryPoints] + [entryPoints.web] + address = ":80" + + [entryPoints.websecure] + address = ":443" + +[providers] + [providers.docker] + +[api] + dashboard = true + +[log] + level = "INFO" +``` + +### Configuration File + +At startup, Traefik searches for static configuration in a file named `traefik.yml` (or `traefik.yaml` or `traefik.toml`) in the following directories: + +- `/etc/traefik/` +- `$XDG_CONFIG_HOME/` +- `$HOME/.config/` +- `.` (the current working directory). + +You can override this behavior using the `configFile` argument like this: + +```bash +traefik --configFile=foo/bar/myconfigfile.yml +``` + +## CLI + +Using the CLI, you can pass static configuration directly as command-line arguments when starting Traefik. + +### Configuration Example + +```sh tab="CLI" +traefik \ + --entryPoints.web.address=":80" \ + --entryPoints.websecure.address=":443" \ + --providers.docker \ + --api.dashboard \ + --log.level=INFO +``` + +## Environment Variables + +You can also set the static configuration using environment variables. Each option corresponds to an environment variable prefixed with `TRAEFIK_`. + +### Configuration Example + +```sh tab="ENV" +TRAEFIK_ENTRYPOINTS_WEB_ADDRESS=":80" TRAEFIK_ENTRYPOINTS_WEBSECURE_ADDRESS=":443" TRAEFIK_PROVIDERS_DOCKER=true TRAEFIK_API_DASHBOARD=true TRAEFIK_LOG_LEVEL="INFO" traefik +``` + +## Helm + +When deploying Traefik Proxy using Helm in a Kubernetes cluster, the static configuration is defined in a `values.yaml` file. + +You can find the official Traefik Helm chart on [GitHub](https://github.com/traefik/traefik-helm-chart/blob/master/traefik/VALUES.md) + +### Configuration Example + +```yaml tab="values.yaml" +ports: + web: + exposedPort: 80 + websecure: + exposedPort: 443 + +additionalArguments: + - "--providers.kubernetescrd.ingressClass" + - "--log.level=INFO" +``` + +```sh tab="Helm Commands" +helm repo add traefik https://traefik.github.io/charts +helm repo update +helm install traefik traefik/traefik -f values.yaml +``` diff --git a/docs/content/reference/install-configuration/cli-options-list.md b/docs/content/reference/install-configuration/cli-options-list.md new file mode 100644 index 000000000..e69de29bb diff --git a/docs/content/reference/install-configuration/entrypoints.md b/docs/content/reference/install-configuration/entrypoints.md new file mode 100644 index 000000000..43e212c35 --- /dev/null +++ b/docs/content/reference/install-configuration/entrypoints.md @@ -0,0 +1,213 @@ +--- +title: "Traefik EntryPoints Documentation" +description: "For routing and load balancing in Traefik Proxy, EntryPoints define which port will receive packets and whether they are TCP or UDP. Read the technical documentation." +--- + +Listening for Incoming Connections/Requests +{: .subtitle } + +### Configuration Example + +```yaml tab="File (YAML)" +entryPoints: + web: + address: :80 + http: + redirections: + entryPoint: + to: websecure + scheme: https + permanent: true + + websecure: + address: :443 + tls: {} + middlewares: + - auth@kubernetescrd + - strip@kubernetescrd +``` + +```yaml tab="Helm Chart Values" +## Values file +ports: + web: + port: :80 + websecure: + port: :443 + tls: + enabled: true + middlewares: + - auth@kubernetescrd + - strip@kubernetescrd +additionalArguments: + - --entryPoints.web.http.redirections.to=websecure + - --entryPoints.web.http.redirections.scheme=https + - --entryPoints.web.http.redirections.permanent=true +``` + +!!! tip + + In the Helm Chart, the entryPoints `web` (port 80), `websecure` (port 443), `traefik` (port 9000) and `metrics` (port 9100) are created by default. + The entryPoints `web`, `websecure` are exposed by default using a Service. + + The default behaviors can be overridden in the Helm Chart. + +## Configuration Options + +| Field | Description | Default | Required | +|:------|:------------|:--------|:---------| +| `address` | Define the port, and optionally the hostname, on which to listen for incoming connections and packets.
It also defines the protocol to use (TCP or UDP).
If no protocol is specified, the default is TCP. The format is:`[host]:port[/tcp\|/udp]`. | - | Yes | +| `asDefault` | Mark the `entryPoint` to be in the list of default `entryPoints`.
`entryPoints`in this list are used (by default) on HTTP and TCP routers that do not define their own `entryPoints` option.
More information [here](#asdefault). | false | No | +| `forwardedHeaders.trustedIPs` | Set the IPs or CIDR from where Traefik trusts the forwarded headers information (`X-Forwarded-*`). | - | No | +| `forwardedHeaders.insecure` | Set the insecure mode to always trust the forwarded headers information (`X-Forwarded-*`).
We recommend to use this option only for tests purposes, not in production. | false | No | +| `http.redirections.`
`entryPoint.to` | The target element to enable (permanent) redirecting of all incoming requests on an entry point to another one.
The target element can be an entry point name (ex: `websecure`), or a port (`:443`). | - | Yes | +| `http.redirections.`
`entryPoint.scheme` | The target scheme to use for (permanent) redirection of all incoming requests. | https | No | +| `http.redirections.`
`entryPoint.permanent` | Enable permanent redirecting of all incoming requests on an entry point to another one changing the scheme.
The target element, it can be an entry point name (ex: `websecure`), or a port (`:443`). | false | No | +| `http.redirections.`
`entryPoint.priority` | Default priority applied to the routers attached to the `entryPoint`. | MaxInt32-1 (2147483646) | No | +| `http.encodeQuerySemicolons` | Enable query semicolons encoding.
Use this option to avoid non-encoded semicolons to be interpreted as query parameter separators by Traefik.
When using this option, the non-encoded semicolons characters in query will be transmitted encoded to the backend.
More information [here](#encodequerysemicolons). | false | No | +| `http.middlewares` | Set the list of middlewares that are prepended by default to the list of middlewares of each router associated to the named entry point.
More information [here](#httpmiddlewares). | - | No | +| `http.tls` | Enable TLS on every router attached to the `entryPoint`.
If no certificate are set, a default self-signed certificate is generates by Traefik.
We recommend to not use self signed certificates in production. | - | No | +| `http.tls.options` | Apply TLS options on every router attached to the `entryPoint`.
The TLS options can be overidden per router.
More information in the [dedicated section](../../routing/providers/kubernetes-crd.md#kind-tlsoption). | - | No | +| `http.tls.certResolver` | Apply a certificate resolver on every router attached to the `entryPoint`.
The TLS options can be overidden per router.
More information in the [dedicated section](../install-configuration/tls/certificate-resolvers/overview.md). | - | No | +| `http2.maxConcurrentStreams` | Set the number of concurrent streams per connection that each client is allowed to initiate.
The value must be greater than zero. | 250 | No | +| `http3` | Enable HTTP/3 protocol on the `entryPoint`.
HTTP/3 requires a TCP `entryPoint`. as HTTP/3 always starts as a TCP connection that then gets upgraded to UDP. In most scenarios, this `entryPoint` is the same as the one used for TLS traffic.
More information [here](#http3. | - | No | +| `http3.advertisedPort` | Set the UDP port to advertise as the HTTP/3 authority.
It defaults to the entryPoint's address port.
It can be used to override the authority in the `alt-svc` header, for example if the public facing port is different from where Traefik is listening. | - | No | +| `proxyProtocol.trustedIPs` | Enable PROXY protocol with Trusted IPs.
Traefik supports [PROXY protocol](https://www.haproxy.org/download/2.0/doc/proxy-protocol.txt) version 1 and 2.
If PROXY protocol header parsing is enabled for the entry point, this entry point can accept connections with or without PROXY protocol headers.
If the PROXY protocol header is passed, then the version is determined automatically.
More information [here](#proxyprotocol-and-load-balancers).| - | No | +| `proxyProtocol.insecure` | Enable PROXY protocol trusting every incoming connection.
Every remote client address will be replaced (`trustedIPs`) won't have any effect).
Traefik supports [PROXY protocol](https://www.haproxy.org/download/2.0/doc/proxy-protocol.txt) version 1 and 2.
If PROXY protocol header parsing is enabled for the entry point, this entry point can accept connections with or without PROXY protocol headers.
If the PROXY protocol header is passed, then the version is determined automatically.
We recommend to use this option only for tests purposes, not in production.
More information [here](#proxyprotocol-and-load-balancers). | - | No | +| `reusePort` | Enable `entryPoints` from the same or different processes listening on the same TCP/UDP port by utilizing the `SO_REUSEPORT` socket option.
It also allows the kernel to act like a load balancer to distribute incoming connections between entry points..
More information [here](#reuseport). | false | No | +| `transport.`
`respondingTimeouts.`
`readTimeout` | Set the timeouts for incoming requests to the Traefik instance. This is the maximum duration for reading the entire request, including the body. Setting them has no effect for UDP `entryPoints`.
If zero, no timeout exists.
Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits).
If no units are provided, the value is parsed assuming seconds. | 60s (seconds) | No | +| `transport.`
`respondingTimeouts.`
`writeTimeout` | Maximum duration before timing out writes of the response.
It covers the time from the end of the request header read to the end of the response write.
If zero, no timeout exists.
Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits).
If no units are provided, the value is parsed assuming seconds. | 0s (seconds) | No | +| `transport.`
`respondingTimeouts.`
`idleTimeout` | Maximum duration an idle (keep-alive) connection will remain idle before closing itself.
If zero, no timeout exists
Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits).
If no units are provided, the value is parsed assuming seconds| 180s (seconds) | No | +| `transport.`
`lifeCycle.`
`graceTimeOut` | Set the duration to give active requests a chance to finish before Traefik stops.
Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits).
If no units are provided, the value is parsed assuming seconds
In this time frame no new requests are accepted.| 10s (seconds) | No | +| `transport.`
`lifeCycle.`
`requestAcceptGraceTimeout` | Set the duration to keep accepting requests prior to initiating the graceful termination period (as defined by the `transportlifeCycle.graceTimeOut` option).
This option is meant to give downstream load-balancers sufficient time to take Traefik out of rotation.
Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits).
If no units are provided, the value is parsed assuming seconds| 0s (seconds) | No | +| `transport.`
`keepAliveMaxRequests` | Set the maximum number of requests Traefik can handle before sending a `Connection: Close` header to the client (for HTTP2, Traefik sends a GOAWAY).
Zero means no limit. | 0 | No | +| `transport.`
`keepAliveMaxTime` | Set the maximum duration Traefik can handle requests before sending a `Connection: Close` header to the client (for HTTP2, Traefik sends a GOAWAY). Zero means no limit. | 0s (seconds) | No | +| `udp.timeout` | Define how long to wait on an idle session before releasing the related resources.
The Timeout value must be greater than zero.| 3s (seconds)| No | + +### asDefault + +If there is no entryPoint with the `asDefault` option set to `true`, then the +list of default entryPoints includes all HTTP/TCP entryPoints. + +If at least one entryPoint has the `asDefault` option set to `true`, +then the list of default entryPoints includes only entryPoints that have the +`asDefault` option set to `true`. + +Some built-in entryPoints are always excluded from the list, namely: `traefik`. + +The `asDefault` option has no effect on UDP entryPoints. +When a UDP router does not define the entryPoints option, it is attached to all +available UDP entryPoints. + +### http.middlewares + +- You can attach a list of [middlewares](../../middlewares/http/overview.md) +to each entryPoint. +- The middlewares will take effect only if the rule matches, and before forwarding +the request to the service. +- Middlewares are applied in the same order as their declaration. +- Middlewares are applied by default to every router exposed through the EntryPoint +(the Middlewares declared on the [IngressRoute](../../routing/routers/index.md#middlewares) +or the [Ingress](../../routing/providers/kubernetes-ingress.md#on-ingress) +are applied after the ones declared on the Entrypoint) +- The option allows attaching a list of middleware using the format +`middlewarename@providername` as described in the example below: + +```yaml tab="File (YAML)" +entryPoints: + web: + address: :80 + middlewares: + - auth@kubernetescrd + - strip@file +``` + +```yaml tab="Helm Chart Values" +ports: + web: + port: :80 + middlewares: + - auth@kubernetescrd + - strip@file +``` + +### encodeQuerySemicolons + +Behavior examples: + +| EncodeQuerySemicolons | Request Query | Resulting Request Query | +|-----------------------|---------------------|-------------------------| +| false | foo=bar;baz=bar | foo=bar&baz=bar | +| true | foo=bar;baz=bar | foo=bar%3Bbaz=bar | +| false | foo=bar&baz=bar;foo | foo=bar&baz=bar&foo | +| true | foo=bar&baz=bar;foo | foo=bar&baz=bar%3Bfoo | + +### HTTP3 + +As HTTP/3 actually uses UDP, when Traefik is configured with a TCP `entryPoint` +on port N with HTTP/3 enabled, the underlying HTTP/3 server that is started +automatically listens on UDP port N too. As a consequence, +it means port N cannot be used by another UDP `entryPoint`. +Since HTTP/3 requires the use of TLS, +only routers with TLS enabled will be usable with HTTP/3. + +### ProxyProtocol and Load-Balancers + +The replacement of the remote client address will occur only for IP addresses listed in `trustedIPs`. This is where yoåu specify your load balancer IPs or CIDR ranges. + +When queuing Traefik behind another load-balancer, make sure to configure +PROXY protocol on both sides. +Not doing so could introduce a security risk in your system (enabling request forgery). + +### reusePort + +#### Examples + +Many processes on the same EntryPoint: + +```yaml tab="File (YAML)" + entryPoints: + web: + address: ":80" + reusePort: true +``` + +```yaml tab="Helm Chart Values" + ## Values file + additionalArguments: + - --entryPoints.web.reusePort=true +``` + +Many processes on the same EntryPoint on another host: + +```yaml tab="File (YAML)" +entryPoints: + web: + address: ":80" + reusePort: true + privateWeb: + address: "192.168.1.2:80" + reusePort: true +``` + +```yaml tab="Helm Chart Values" +additionalArguments: + - --entryPoints.web.reusePort=true + - --entryPoints.privateWeb.address=192.168.1.2:80 + - --entryPoints.privateWeb.reusePort=true +``` + +#### Supported platforms + +The `reusePort` option currently works only on Linux, FreeBSD, OpenBSD and Darwin. +It will be ignored on other platforms. + +There is a known bug in the Linux kernel that may cause unintended TCP connection +failures when using the `reusePort` option. For more details, see [here](https://lwn.net/Articles/853637/). + +#### Canary deployment + +Use the `reusePort` option with the other option `transport.lifeCycle.gracetimeout` +to do +canary deployments against Traefik itself. Like upgrading Traefik version +or reloading the static configuration without any service downtime. diff --git a/docs/content/reference/install-configuration/observability/healthcheck.md b/docs/content/reference/install-configuration/observability/healthcheck.md new file mode 100644 index 000000000..742480286 --- /dev/null +++ b/docs/content/reference/install-configuration/observability/healthcheck.md @@ -0,0 +1,87 @@ +--- +title: "Traefik Health Check Documentation" +description: "In Traefik Proxy, CLI & Ping lets you check the health of your Traefik instances. Read the technical documentation for configuration examples and options." +--- + +# CLI & Ping + +Checking the Health of your Traefik Instances +{: .subtitle } + +## CLI + +The CLI can be used to make a request to the `/ping` endpoint to check the health of Traefik. Its exit status is `0` if Traefik is healthy and `1` otherwise. + +This can be used with [HEALTHCHECK](https://docs.docker.com/engine/reference/builder/#healthcheck) instruction or any other health check orchestration mechanism. + +### Usage + +```sh +traefik healthcheck [command] [flags] [arguments] +``` + +Example: + +```sh +$ traefik healthcheck +OK: http://:8082/ping +``` + +## Ping + +The `/ping` health-check URL is enabled with the command-line `--ping` or config file option `[ping]`. + +The entryPoint where the `/ping` is active can be customized with the `entryPoint` option, +whose default value is `traefik` (port `8080`). + +| Path | Method | Description | +|---------|---------------|-----------------------------------------------------------------------------------------------------| +| `/ping` | `GET`, `HEAD` | An endpoint to check for Traefik process liveness. Return a code `200` with the content: `OK` | + +### Configuration Example + +To enable the API handler: + +```yaml tab="File (YAML)" +ping: {} +``` + +```toml tab="File (TOML)" +[ping] +``` + +```bash tab="CLI" +--ping=true +``` + +### Configuration Options + +| Field | Description | Default | Required | +|:------|:----------------------------------------------------------|:---------------------|:---------| +| `ping.entryPoint` | Enables `/ping` on a dedicated EntryPoint. | traefik | No | +| `ping.manualRouting` | Disables the default internal router in order to allow one to create a custom router for the `ping@internal` service when set to `true`. | false | No | +| `ping.terminatingStatusCode` | Defines the status code for the ping handler during a graceful shut down. See more information [here](#terminatingstatuscode) | 503 | No | + +#### `terminatingStatusCode` + +During the period in which Traefik is gracefully shutting down, the ping handler +returns a `503` status code by default. +If Traefik is behind, for example a load-balancer +doing health checks (such as the Kubernetes LivenessProbe), another code might +be expected as the signal for graceful termination. +In that case, the terminatingStatusCode can be used to set the code returned by the ping +handler during termination. + +```yaml tab="File (YAML)" +ping: + terminatingStatusCode: 204 +``` + +```toml tab="File (TOML)" +[ping] + terminatingStatusCode = 204 +``` + +```bash tab="CLI" +--ping.terminatingStatusCode=204 +``` diff --git a/docs/content/reference/install-configuration/observability/logs-and-accesslogs.md b/docs/content/reference/install-configuration/observability/logs-and-accesslogs.md new file mode 100644 index 000000000..5137f146e --- /dev/null +++ b/docs/content/reference/install-configuration/observability/logs-and-accesslogs.md @@ -0,0 +1,218 @@ +--- +title: "Traefik Logs Documentation" +description: "Logs are a key part of observability in Traefik Proxy. Read the technical documentation to learn their configurations, rotations, and time zones." +--- + +## Logs + +Logs concern everything that happens to Traefik itself (startup, configuration, events, shutdown, and so on). + +### Configuration Example + +```yaml tab="File (YAML)" +log: + filePath: "/path/to/log-file.log" + format: json + level: INFO +``` + +```toml tab="File (TOML)" +[log] + filePath = "/path/to/log-file.log" + format = "json" + level = "INFO" +``` + +```sh tab="CLI" +--log.filePath=/path/to/log-file.log +--log.format=json +--log.level=INFO +``` + +### Configuration Options + +The section below describe how to configure Traefik logs using the static configuration. + +| Field | Description | Default | Required | +|:-----------|:----------------------------|:--------|:---------| +| `log.filePath` | By default, the logs are written to the standard output.
You can configure a file path instead using the `filePath` option.| - | No | +| `log.format` | Log format (`common`or `json`).
The fields displayed with the format `common` cannot be customized. | "common" | No | +| `log.level` | Log level (`TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL`, and `PANIC`)| ERROR | No | +| `log.noColor` | When using the format `common`, disables the colorized output. | false | No | +| `log.maxSize` | Maximum size in megabytes of the log file before it gets rotated. | 100MB | No | +| `log.maxAge` | Maximum number of days to retain old log files based on the timestamp encoded in their filename.
A day is defined as 24 hours and may not exactly correspond to calendar days due to daylight savings, leap seconds, etc.
By default files are not removed based on their age. | 0 | No | +| `log.maxBackups` | Maximum number of old log files to retain.
The default is to retain all old log files. | 0 | No | +| `log.compress` | Compress log files in gzip after rotation. | false | No | + +## AccessLogs + +### Configuration Example + +```yaml tab="File (YAML)" +accessLog: + # JSON format + format: json + # Filter on status codes, retry attempts and minimal duration + filters: + statusCodes: + - "200" + - "300-302" + retryAttempts: true + minDuration: "10ms" + fields: + # Keep all the fields by default + defaultMode: keep + names: + # Drop the Field ClientUserName + ClientUsername: drop + headers: + # Keep all the headers by default + defaultMode: keep + names: + # Redact the User-Agent header value + User-Agent: redact + # Drop the Authorization header value + Authorization: drop +``` + +```toml tab="File (TOML)" +[accessLog] + format = "json" + + [accessLog.filters] + statusCodes = [ "200", "300-302" ] + retryAttempts = true + minDuration = "10ms" + + [accessLog.fields] + defaultMode = "keep" + + [accessLog.fields.names] + ClientUsername = "drop" + + [accessLog.fields.headers] + defaultMode = "keep" + + [accessLog.fields.headers.names] + User-Agent = "redact" + Authorization = "drop" +``` + +```sh tab="CLI" +--accesslog=true +--accesslog.format=json +--accesslog.filters.statuscodes=200,300-302 +--accesslog.filters.retryattempts +--accesslog.filters.minduration=10ms +--accesslog.fields.defaultmode=keep +--accesslog.fields.names.ClientUsername=drop +--accesslog.fields.headers.defaultmode=keep +--accesslog.fields.headers.names.User-Agent=redact +--accesslog.fields.headers.names.Authorization=drop +``` + +### Configuration Options + +The section below describes how to configure Traefik access logs using the static configuration. + +| Field | Description | Default | Required | +|:-----------|:--------------------------|:--------|:---------| +| `accesslog.filePath` | By default, the access logs are written to the standard output.
You can configure a file path instead using the `filePath` option.| | No | +| `accesslog.format` | By default, logs are written using the Common Log Format (CLF).
To write logs in JSON, use `json` in the `format` option.
If the given format is unsupported, the default (CLF) is used instead.
More information about CLF fields [here](#clf-format-fields). | "common" | No | +| `accesslog.bufferingSize` | To write the logs in an asynchronous fashion, specify a `bufferingSize` option.
This option represents the number of log lines Traefik will keep in memory before writing them to the selected output.
In some cases, this option can greatly help performances.| 0 | No | +| `accesslog.addInternals` | Enables access logs for internal resources (e.g.: `ping@internal`). | false | No | +| `accesslog.filters.statusCodes` | Limit the access logs to requests with a status codes in the specified range. | false | No | +| `accesslog.filters.retryAttempts` | Keep the access logs when at least one retry has happened. | false | No | +| `accesslog.filters.minDuration` | Keep access logs when requests take longer than the specified duration (provided in seconds or as a valid duration format, see [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration)). | 0 | No | +| `accesslog.fields.defaultMode` | Mode to apply by default to the access logs fields (`keep`, `redact` or `drop`). | keep | No | +| `accesslog.fields.names` | Set the fields list to display in the access logs (format `name:mode`).
Available fields list [here](#available-fields). | - | No | +| `accesslog.headers.defaultMode` | Mode to apply by default to the access logs headers (`keep`, `redact` or `drop`). | drop | No | +| `accesslog.headers.names` | Set the headers list to display in the access logs (format `name:mode`). | - | No | + +#### CLF format fields + +Below the fields displayed with the CLF format: + +```html + - [] +" " +"" "" +"" "" ms +``` + +#### Available Fields + +| Field | Description | +|-------------------------|------------------| +| `StartUTC` | The time at which request processing started. | +| `StartLocal` | The local time at which request processing started. | +| `Duration` | The total time taken (in nanoseconds) by processing the response, including the origin server's time but not the log writing time. | +| `RouterName` | The name of the Traefik router. | +| `ServiceName` | The name of the Traefik backend. | +| `ServiceURL` | The URL of the Traefik backend. | +| `ServiceAddr` | The IP:port of the Traefik backend (extracted from `ServiceURL`). | +| `ClientAddr` | The remote address in its original form (usually IP:port). | +| `ClientHost` | The remote IP address from which the client request was received. | +| `ClientPort` | The remote TCP port from which the client request was received. | +| `ClientUsername` | The username provided in the URL, if present. | +| `RequestAddr` | The HTTP Host header (usually IP:port). This is treated as not a header by the Go API. | +| `RequestHost` | The HTTP Host server name (not including port). | +| `RequestPort` | The TCP port from the HTTP Host. | +| `RequestMethod` | The HTTP method. | +| `RequestPath` | The HTTP request URI, not including the scheme, host or port. | +| `RequestProtocol` | The version of HTTP requested. | +| `RequestScheme` | The HTTP scheme requested `http` or `https`. | +| `RequestLine` | The `RequestMethod`, + `RequestPath` and `RequestProtocol`. | +| `RequestContentSize` | The number of bytes in the request entity (a.k.a. body) sent by the client. | +| `OriginDuration` | The time taken (in nanoseconds) by the origin server ('upstream') to return its response. | +| `OriginContentSize` | The content length specified by the origin server, or 0 if unspecified. | +| `OriginStatus` | The HTTP status code returned by the origin server. If the request was handled by this Traefik instance (e.g. with a redirect), then this value will be absent (0). | +| `OriginStatusLine` | `OriginStatus` + Status code explanation | +| `DownstreamStatus` | The HTTP status code returned to the client. | +| `DownstreamStatusLine` | The `DownstreamStatus` and status code explanation. | +| `DownstreamContentSize` | The number of bytes in the response entity returned to the client. This is in addition to the "Content-Length" header, which may be present in the origin response. | +| `RequestCount` | The number of requests received since the Traefik instance started. | +| `GzipRatio` | The response body compression ratio achieved. | +| `Overhead` | The processing time overhead (in nanoseconds) caused by Traefik. | +| `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 + +Traefik 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`. + +!!! warning + This does not work on Windows due to the lack of USR signals. + +#### Time Zones + +Traefik will timestamp each log line in UTC time by default. + +It is possible to configure the Traefik to timestamp in a specific timezone by ensuring the following configuration has been made in your environment: + +1. Provide time zone data to `/etc/localtime` or `/usr/share/zoneinfo` (based on your distribution) or set the environment variable TZ to the desired timezone. +2. Specify the field `StartLocal` by dropping the field named `StartUTC` (available on the default Common Log Format (CLF) as well as JSON): `accesslog.fields.names.StartUTC=drop`. + +Example utilizing Docker Compose: + +```yaml +version: "3.7" + +services: + traefik: + image: traefik:v3.2 + environment: + - TZ=US/Alaska + command: + - --accesslog.fields.names.StartUTC=drop + - --providers.docker + ports: + - 80:80 + volumes: + - /var/run/docker.sock:/var/run/docker.sock +``` + +{!traefik-for-business-applications.md!} diff --git a/docs/content/reference/install-configuration/observability/metrics.md b/docs/content/reference/install-configuration/observability/metrics.md new file mode 100644 index 000000000..c2c6f4bd0 --- /dev/null +++ b/docs/content/reference/install-configuration/observability/metrics.md @@ -0,0 +1,601 @@ +--- +title: "Traefik Metrics Overview" +description: "Traefik Proxy supports these metrics backend systems: OpenTelemetry, Datadog, InfluxDB 2.X, Prometheus, and StatsD. Read the full documentation to get started." +--- + +# Metrics + +Traefik provides metrics in the [OpenTelemetry](#open-telemetry) format as well as the following vendor specific backends: + +- [Datadog](#datadog) +- [InfluxDB2](#influxdb-v2) +- [Prometheus](#prometheus) +- [StatsD](#statsd) + +Traefik Proxy has an official Grafana dashboard for both [on-premises](https://grafana.com/grafana/dashboards/17346) +and [Kubernetes](https://grafana.com/grafana/dashboards/17347) deployments. + +--- + +## Open Telemetry + +!!! info "Default protocol" + + The OpenTelemetry exporter will export metrics to the collector using HTTP by default to https://localhost:4318/v1/metrics. + +### Configuration Example + +To enable the OpenTelemetry metrics: + +```yaml tab="File (YAML)" +metrics: + otlp: {} +``` + +```toml tab="File (TOML)" +[metrics] + [metrics.otlp] +``` + +```bash tab="CLI" +--metrics.otlp=true +``` + +```yaml tab="Helm Chart Values" +# values.yaml +metrics: + # Disable Prometheus (enabled by default) + prometheus: null + # Enable providing OTel metrics + otlp: + enabled: true + http: + enabled: true +``` + +!!! tip "Helm Chart Configuration" + + Traefik can be configured to provide metrics in the OpenTelemetry format using the Helm Chart values. + To know more about the Helm Chart options, refer to the [Helm Chart](https://github.com/traefik/traefik-helm-chart/blob/master/traefik/VALUES.md) (Find options `metrics.otlp`). + +### Configuration Options + +| Field | Description | Default | Required | +|:-----------|---------------|:--------|:---------| +| `metrics.addInternals` | Enables metrics for internal resources (e.g.: `ping@internal`). | false | No | +| `metrics.otlp.addEntryPointsLabels` | Enable metrics on entry points. | true | No | +| `metrics.otlp.addRoutersLabels` | Enable metrics on routers. | false | No | +| `metrics.otlp.addServicesLabels` | Enable metrics on services.| true | No | +| `metrics.otlp.explicitBoundaries` | Explicit boundaries for Histogram data points. | ".005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10" | No | +| `metrics.otlp.pushInterval` | Interval at which metrics are sent to the OpenTelemetry Collector. | 10s | No | +| `metrics.otlp.http` | This instructs the exporter to send the metrics to the OpenTelemetry Collector using HTTP.
Setting the sub-options with their default values. | null/false | No | +| `metrics.otlp.http.endpoint` | URL of the OpenTelemetry Collector to send metrics to.
Format="`://:`" | "http://localhost:4318/v1/metrics" | Yes | +| `metrics.otlp.http.headers` | Additional headers sent with metrics by the exporter to the OpenTelemetry Collector. | - | No | +| `metrics.otlp.http.tls.ca` | Path to the certificate authority used for the secure connection to the OpenTelemetry Collector,
it defaults to the system bundle. | "" | No | +| `metrics.otlp.http.tls.cert` | Path to the public certificate used for the secure connection to the OpenTelemetry Collector.
When using this option, setting the `key` option is required. | "" | No | +| `metrics.otlp.http.tls.key` | This instructs the exporter to send the metrics to the OpenTelemetry Collector using HTTP.
Setting the sub-options with their default values. | null/false | No | +| `metrics.otlp.http.tls.insecureskipverify` | Allow the TLS connection to the OpenTelemetry Collector accepts any certificate presented by the server regardless of the hostnames it covers. | false | Yes | +| `metrics.otlp.grpc` | This instructs the exporter to send metrics to the OpenTelemetry Collector using gRPC. | null/false | No | +| `metrics.otlp.grpc.endpoint` | Address of the OpenTelemetry Collector to send metrics to.
Format="`:`" | "localhost:4317" | Yes | +| `metrics.otlp.grpc.headers` | Additional headers sent with metrics by the exporter to the OpenTelemetry Collector. | - | No | +| `metrics.otlp.http.grpc.insecure` |Allows exporter to send metrics to the OpenTelemetry Collector without using a secured protocol. | false | Yes | +| `metrics.otlp.grpc.tls.ca` | Path to the certificate authority used for the secure connection to the OpenTelemetry Collector,
it defaults to the system bundle. | - | No | +| `metrics.otlp.grpc.tls.cert` | Path to the public certificate used for the secure connection to the OpenTelemetry Collector.
When using this option, setting the `key` option is required. | - | No | +| `metrics.otlp.grpc.tls.key` | This instructs the exporter to send the metrics to the OpenTelemetry Collector using HTTP.
Setting the sub-options with their default values. | null/false | No | +| `metrics.otlp.grpc.tls.insecureskipverify` | Allow the TLS connection to the OpenTelemetry Collector accepts any certificate presented by the server regardless of the hostnames it covers. | false | Yes | + +## Vendors + +### Datadog + +#### Configuration Example + +To enable the Datadog: + +```yaml tab="File (YAML)" +metrics: + datadog: {} +``` + +```toml tab="File (TOML)" +[metrics] + [metrics.datadog] +``` + +```bash tab="CLI" +--metrics.datadog=true +``` + +#### Configuration Options + +| Field | Description | Default | Required | +|:------|:-------------------------------|:---------------------|:---------| +| `metrics.addInternals` | Enables metrics for internal resources (e.g.: `ping@internal`). | false | No | +| `datadog.address` | Defines the address for the exporter to send metrics to datadog-agent. More information [here](#address)| `127.0.0.1:8125` | Yes | +| `datadog.addEntryPointsLabels` | Enable metrics on entry points. | true | No | +| `datadog.addRoutersLabels` | Enable metrics on routers. | false | No | +| `datadog.addServicesLabels` | Enable metrics on services. | true | No | +| `datadog.pushInterval` | Defines the interval used by the exporter to push metrics to datadog-agent. | 10s | No | +| `datadog.prefix` | Defines the prefix to use for metrics collection. | "traefik" | No | + +##### `address` + +Address instructs exporter to send metrics to datadog-agent at this address. + +This address can be a Unix Domain Socket (UDS) in the following format: `unix:///path/to/datadog.socket`. +When the prefix is set to `unix`, the socket type will be automatically determined. +To explicitly define the socket type and avoid automatic detection, you can use the prefixes `unixgram` for `SOCK_DGRAM` (datagram sockets) and `unixstream` for `SOCK_STREAM` (stream sockets), respectively. + +```yaml tab="File (YAML)" +metrics: + datadog: + address: 127.0.0.1:8125 +``` + +```toml tab="File (TOML)" +[metrics] + [metrics.datadog] + address = "127.0.0.1:8125" +``` + +```bash tab="CLI" +--metrics.datadog.address=127.0.0.1:8125 +``` + +### InfluxDB v2 + +#### Configuration Example + +To enable the InfluxDB2: + +```yaml tab="File (YAML)" +metrics: + influxDB2: + address: http://localhost:8086 +``` + +```toml tab="File (TOML)" +[metrics] + [metrics.influxDB2] + address: http://localhost:8086 +``` + +```bash tab="CLI" +--metrics.influxdb2=true +``` + +#### Configuration Options + +| Field | Description | Default | Required | +|:-----------|-------------------------|:--------|:---------| +| `metrics.addInternal` | Enables metrics for internal resources (e.g.: `ping@internal`). | false | No | +| `metrics.influxDB2.addEntryPointsLabels` | Enable metrics on entry points. | true | No | +| `metrics.influxDB2.addRoutersLabels` | Enable metrics on routers. | false | No | +| `metrics.influxDB2.addServicesLabels` | Enable metrics on services.| true | No | +| `metrics.influxDB2.additionalLabels` | Additional labels (InfluxDB tags) on all metrics. | - | No | +| `metrics.influxDB2.pushInterval` | The interval used by the exporter to push metrics to InfluxDB server. | 10s | No | +| `metrics.influxDB2.address` | Address of the InfluxDB v2 instance. | "http://localhost:8086" | Yes | +| `metrics.influxDB2.token` | Token with which to connect to InfluxDB v2. | - | Yes | +| `metrics.influxDB2.org` | Organisation where metrics will be stored. | - | Yes | +| `metrics.influxDB2.bucket` | Bucket where metrics will be stored. | - | Yes | + +### Prometheus + +#### Configuration Example + +To enable the Prometheus: + +```yaml tab="File (YAML)" +metrics: + prometheus: + buckets: + - 0.1 + - 0.3 + - 1.2 + - 5.0 +``` + +```toml tab="File (TOML)" +[metrics] + [metrics.prometheus] + [metrics.prometheus.buckets] + - 0.1 + - 0.3 + - 1.2 + - 5.0 +``` + +```bash tab="CLI" +--metrics.prometheus=true +``` + +#### Configuration Options + +| Field | Description | Default | Required | +|:-----------|---------------------|:--------|:---------| +| `metrics.prometheus.addInternals` | Enables metrics for internal resources (e.g.: `ping@internals`). | false | No | +| `metrics.prometheus.addEntryPointsLabels` | Enable metrics on entry points. | true | No | +| `metrics.prometheus.addRoutersLabels` | Enable metrics on routers. | false | No | +| `metrics.prometheus.addServicesLabels` | Enable metrics on services.| true | No | +| `metrics.prometheus.buckets` | Buckets for latency metrics. |"0.100000, 0.300000, 1.200000, 5.000000" | No | +| `metrics.prometheus.manualRouting` | Set to _true_, it disables the default internal router in order to allow creating a custom router for the `prometheus@internal` service. | false | No | +| `metrics.prometheus.entryPoint` | Traefik Entrypoint name used to expose metrics. | "traefik" | No | +| `metrics.prometheus.headerLabels` | Defines extra labels extracted from request headers for the `requests_total` metrics.
More information [here](#headerlabels). | | Yes | + +##### headerLabels + +Defines the extra labels for the `requests_total` metrics, and for each of them, the request header containing the value for this label. +If the header is not present in the request it will be added nonetheless with an empty value. +The label must be a valid label name for Prometheus metrics, otherwise, the Prometheus metrics provider will fail to serve any Traefik-related metric. + +!!! note "How to provide the `Host` header value" + The `Host` header is never present in the Header map of a request, as per go documentation says: + + ```Golang + // For incoming requests, the Host header is promoted to the + // Request.Host field and removed from the Header map. + ``` + + As a workaround, to obtain the Host of a request as a label, use instead the `X-Forwarded-Host` header. + +###### Configuration Example + +Here is an example of the entryPoint `requests_total` metric with an additional "useragent" label. + +When configuring the label in Static Configuration: + +```yaml tab="Configuration" +# static_configuration.yaml +metrics: + prometheus: + headerLabels: + useragent: User-Agent +``` + +```bash tab="Request" +curl -H "User-Agent: foobar" http://localhost +``` + +```bash tab="Metric" +traefik_entrypoint_requests_total\{code="200",entrypoint="web",method="GET",protocol="http",useragent="foobar"\} 1 +``` + +### StatsD + +#### Configuration Example + +To enable the Statsd: + +```yaml tab="File (YAML)" +metrics: + statsD: + address: localhost:8125 +``` + +```toml tab="File (TOML)" +[metrics] + [metrics.statsD] + address: localhost:8125 +``` + +```bash tab="CLI" +--metrics.statsd=true +``` + +#### Configuration Options + +| Field | Description | Default | Required | +|:-----------|:-------------------------|:--------|:---------| +| `metrics.addInternals` | Enables metrics for internal resources (e.g.: `ping@internals`). | false | No | +| `metrics.statsD.addEntryPointsLabels` | Enable metrics on entry points. | true | No | +| `metrics.statsD.addRoutersLabels` | Enable metrics on routers. | false | No | +| `metrics.statsD.addServicesLabels` | Enable metrics on services.| true | No | +| `metrics.statsD.pushInterval` | The interval used by the exporter to push metrics to DataDog server. | 10s | No | +| `metrics.statsD.address` | Address instructs exporter to send metrics to statsd at this address. | "127.0.0.1:8125" | Yes | +| `metrics.statsD.prefix` | The prefix to use for metrics collection. | "traefik" | No | + +## Metrics Provided + +### Global Metrics + +=== "OpenTelemetry" + | Metric | Type | [Labels](#labels) | Description | + |----------------------------|-------|--------------------------|--------------------------------------------------------------------| + | `traefik_config_reloads_total` | Count | | The total count of configuration reloads. | + | `traefik_config_last_reload_success` | Gauge | | The timestamp of the last configuration reload success. | + | `traefik_open_connections` | Gauge | `entrypoint`, `protocol` | The current count of open connections, by entrypoint and protocol. | + | `traefik_tls_certs_not_after` | Gauge | | The expiration date of certificates. | + +=== "Prometheus" + | Metric | Type | [Labels](#labels) | Description | + |----------------------------|-------|--------------------------|--------------------------------------------------------------------| + | `traefik_config_reloads_total` | Count | | The total count of configuration reloads. | + | `traefik_config_last_reload_success` | Gauge | | The timestamp of the last configuration reload success. | + | `traefik_open_connections` | Gauge | `entrypoint`, `protocol` | The current count of open connections, by entrypoint and protocol. | + | `traefik_tls_certs_not_after` | Gauge | | The expiration date of certificates. | + +=== "Datadog" + | Metric | Type | [Labels](#labels) | Description | + |----------------------------|-------|--------------------------|--------------------------------------------------------------------| + | `config.reload.total` | Count | | The total count of configuration reloads. | + | `config.reload.lastSuccessTimestamp` | 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.certs.notAfterTimestamp` | Gauge | | The expiration date of certificates. | + +=== "InfluxDB2" + | Metric | Type | [Labels](#labels) | Description | + |----------------------------|-------|--------------------------|--------------------------------------------------------------------| + | `traefik.config.reload.total` | Count | | The total count of configuration reloads. | + | `traefik.config.reload.lastSuccessTimestamp` | Gauge | | The timestamp of the last configuration reload success. | + | `traefik.open.connections` | Gauge | `entrypoint`, `protocol` | The current count of open connections, by entrypoint and protocol. | + | `traefik.tls.certs.notAfterTimestamp` | Gauge | | The expiration date of certificates. | + +=== "StatsD" + | Metric | Type | [Labels](#labels) | Description | + |----------------------------|-------|--------------------------|--------------------------------------------------------------------| + | `{prefix}.config.reload.total` | Count | | The total count of configuration reloads. | + | `{prefix}.config.reload.lastSuccessTimestamp` | Gauge | | The timestamp of the last configuration reload success. | + | `{prefix}.open.connections` | Gauge | `entrypoint`, `protocol` | The current count of open connections, by entrypoint and protocol. | + | `{prefix}.tls.certs.notAfterTimestamp` | Gauge | | The expiration date of certificates. | + +!!! note "\{prefix\} Default Value" + By default, \{prefix\} value is `traefik`. + +#### 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" | + +### OpenTelemetry Semantic Conventions + +Traefik Proxy follows [official OpenTelemetry semantic conventions v1.23.1](https://github.com/open-telemetry/semantic-conventions/blob/v1.23.1/docs/http/http-metrics.md). + +#### HTTP Server + +| Metric | Type | [Labels](#labels) | Description | +|----------|-----------|-------------------------|------------------| +| `http.server.request.duration` | Histogram | `error.type`, `http.request.method`, `http.response.status_code`, `network.protocol.name`, `server.address`, `server.port`, `url.scheme` | Duration of HTTP server requests | + +##### Labels + +Here is a comprehensive list of labels that are provided by the metrics: + +| Label | Description | example | +|-----------------------------|--------|---------------| +| `error.type` | Describes a class of error the operation ended with | "500" | +| `http.request.method` | HTTP request method | "GET" | +| `http.response.status_code` | HTTP response status code | "200" | +| `network.protocol.name` | OSI application layer or non-OSI equivalent | "http/1.1" | +| `network.protocol.version` | Version of the protocol specified in `network.protocol.name` | "1.1" | +| `server.address` | Name of the local HTTP server that received the request | "example.com" | +| `server.port` | Port of the local HTTP server that received the request | "80" | +| `url.scheme` | The URI scheme component identifying the used protocol | "http" | + +#### HTTP Client + +| Metric | Type | [Labels](#labels) | Description | +|-------------------------------|-----------|-----------------|--------| +| `http.client.request.duration` | Histogram | `error.type`, `http.request.method`, `http.response.status_code`, `network.protocol.name`, `server.address`, `server.port`, `url.scheme` | Duration of HTTP client requests | + +##### Labels + +Here is a comprehensive list of labels that are provided by the metrics: + +| Label | Description | example | +|------ -----|------------|---------------| +| `error.type` | Describes a class of error the operation ended with | "500" | +| `http.request.method` | HTTP request method | "GET" | +| `http.response.status_code` | HTTP response status code | "200" | +| `network.protocol.name` | OSI application layer or non-OSI equivalent | "http/1.1" | +| `network.protocol.version` | Version of the protocol specified in `network.protocol.name` | "1.1" | +| `server.address` | Name of the local HTTP server that received the request | "example.com" | +| `server.port` | Port of the local HTTP server that received the request | "80" | +| `url.scheme` | The URI scheme component identifying the used protocol | "http" | + +### HTTP Metrics + +On top of the official OpenTelemetry semantic conventions, Traefik provides its own metrics to monitor the incoming traffic. + +#### EntryPoint Metrics + +=== "OpenTelemetry" + + | Metric | Type | [Labels](#labels) | Description | + |-----------------------|-----------|--------------------|--------------------------| + | `traefik_entrypoint_requests_total` | Count | `code`, `method`, `protocol`, `entrypoint` | The total count of HTTP requests received by an entrypoint. | + | `traefik_entrypoint_requests_tls_total` | Count | `tls_version`, `tls_cipher`, `entrypoint` | The total count of HTTPS requests received by an entrypoint. | + | `traefik_entrypoint_request_duration_seconds` | Histogram | `code`, `method`, `protocol`, `entrypoint` | Request processing duration histogram on an entrypoint. | + | `traefik_entrypoint_requests_bytes_total` | Count | `code`, `method`, `protocol`, `entrypoint` | The total size of HTTP requests in bytes handled by an entrypoint. | + | `traefik_entrypoint_responses_bytes_total` | Count | `code`, `method`, `protocol`, `entrypoint` | The total size of HTTP responses in bytes handled by an entrypoint. | + +=== "Prometheus" + + | Metric | Type | [Labels](#labels) | Description | + |-----------------------|-----------|------------------------|-------------------------| + | `traefik_entrypoint_requests_total` | Count | `code`, `method`, `protocol`, `entrypoint` | The total count of HTTP requests received by an entrypoint. | + | `traefik_entrypoint_requests_tls_total` | Count | `tls_version`, `tls_cipher`, `entrypoint` | The total count of HTTPS requests received by an entrypoint. | + | `traefik_entrypoint_request_duration_seconds` | Histogram | `code`, `method`, `protocol`, `entrypoint` | Request processing duration histogram on an entrypoint. | + | `traefik_entrypoint_requests_bytes_total` | Count | `code`, `method`, `protocol`, `entrypoint` | The total size of HTTP requests in bytes handled by an entrypoint. | + | `traefik_entrypoint_responses_bytes_total` | Count | `code`, `method`, `protocol`, `entrypoint` | The total size of HTTP responses in bytes handled by an entrypoint. | + +=== "Datadog" + + | Metric | Type | [Labels](#labels) | Description | + |-----------------------|-----------|------------------|---------------------------| + | `entrypoint.requests.total` | Count | `code`, `method`, `protocol`, `entrypoint` | The total count of HTTP requests received by an entrypoint. | + | `entrypoint.requests.tls.total` | Count | `tls_version`, `tls_cipher`, `entrypoint` | The total count of HTTPS requests received by an entrypoint. | + | `entrypoint.request.duration.seconds` | Histogram | `code`, `method`, `protocol`, `entrypoint` | Request processing duration histogram on an entrypoint. | + | `entrypoint.requests.bytes.total` | Count | `code`, `method`, `protocol`, `entrypoint` | The total size of HTTP requests in bytes handled by an entrypoint. | + | `entrypoint.responses.bytes.total` | Count | `code`, `method`, `protocol`, `entrypoint` | The total size of HTTP responses in bytes handled by an entrypoint. | + +=== "InfluxDB2" + + | Metric | Type | [Labels](#labels) | Description | + |------------|-----------|-------------------|-----------------| + | `traefik.entrypoint.requests.total` | Count | `code`, `method`, `protocol`, `entrypoint` | The total count of HTTP requests received by an entrypoint. | + | `traefik.entrypoint.requests.tls.total` | Count | `tls_version`, `tls_cipher`, `entrypoint` | The total count of HTTPS requests received by an entrypoint. | + | `traefik.entrypoint.request.duration.seconds` | Histogram | `code`, `method`, `protocol`, `entrypoint` | Request processing duration histogram on an entrypoint. | + | `traefik.entrypoint.requests.bytes.total` | Count | `code`, `method`, `protocol`, `entrypoint` | The total size of HTTP requests in bytes handled by an entrypoint. | + | `traefik.entrypoint.responses.bytes.total` | Count | `code`, `method`, `protocol`, `entrypoint` | The total size of HTTP responses in bytes handled by an entrypoint. | + +=== "StatsD" + + | Metric | Type | [Labels](#labels) | Description | + |----------------------------|-------|--------------------------|--------------------------------------------------------------------| + | `{prefix}.entrypoint.requests.total` | Count | `code`, `method`, `protocol`, `entrypoint` | The total count of HTTP requests received by an entrypoint. | + | `{prefix}.entrypoint.requests.tls.total` | Count | `tls_version`, `tls_cipher`, `entrypoint` | The total count of HTTPS requests received by an entrypoint. | + | `{prefix}.entrypoint.request.duration.seconds` | Histogram | `code`, `method`, `protocol`, `entrypoint` | Request processing duration histogram on an entrypoint. | + | `{prefix}.entrypoint.requests.bytes.total` | Count | `code`, `method`, `protocol`, `entrypoint` | The total size of HTTP requests in bytes handled by an entrypoint. | + | `{prefix}.entrypoint.responses.bytes.total` | Count | `code`, `method`, `protocol`, `entrypoint` | The total size of HTTP responses in bytes handled by an entrypoint. | + +!!! note "\{prefix\} Default Value" + By default, \{prefix\} value is `traefik`. + +#### Router Metrics + +=== "OpenTelemetry" + + | Metric | Type | [Labels](#labels) | Description | + |-----------------------|-----------|----------------------|--------------------------------| + | `traefik_router_requests_total` | Count | `code`, `method`, `protocol`, `router`, `service` | The total count of HTTP requests handled by a router. | + | `traefik_router_requests_tls_total` | Count | `tls_version`, `tls_cipher`, `router`, `service` | The total count of HTTPS requests handled by a router. | + | `traefik_router_request_duration_seconds` | Histogram | `code`, `method`, `protocol`, `router`, `service` | Request processing duration histogram on a router. | + | `traefik_router_requests_bytes_total` | Count | `code`, `method`, `protocol`, `router`, `service` | The total size of HTTP requests in bytes handled by a router. | + | `traefik_router_responses_bytes_total` | Count | `code`, `method`, `protocol`, `router`, `service` | The total size of HTTP responses in bytes handled by a router. | + +=== "Prometheus" + + | Metric | Type | [Labels](#labels) | Description | + |-----------------------|-----------|---------------------------------------------------|----------------------------------------------------------------| + | `traefik_router_requests_total` | Count | `code`, `method`, `protocol`, `router`, `service` | The total count of HTTP requests handled by a router. | + | `traefik_router_requests_tls_total` | Count | `tls_version`, `tls_cipher`, `router`, `service` | The total count of HTTPS requests handled by a router. | + | `traefik_router_request_duration_seconds` | Histogram | `code`, `method`, `protocol`, `router`, `service` | Request processing duration histogram on a router. | + | `traefik_router_requests_bytes_total` | Count | `code`, `method`, `protocol`, `router`, `service` | The total size of HTTP requests in bytes handled by a router. | + | `traefik_router_responses_bytes_total` | Count | `code`, `method`, `protocol`, `router`, `service` | The total size of HTTP responses in bytes handled by a router. | + +=== "Datadog" + + | Metric | Type | [Labels](#labels) | Description | + |-------------|-----------|---------------|---------------------| + | `router.requests.total` | Count | `code`, `method`, `protocol`, `router`, `service` | The total count of HTTP requests handled by a router. | + | `router.requests.tls.total` | Count | `tls_version`, `tls_cipher`, `router`, `service` | The total count of HTTPS requests handled by a router. | + | `router.request.duration.seconds` | Histogram | `code`, `method`, `protocol`, `router`, `service` | Request processing duration histogram on a router. | + | `router.requests.bytes.total` | Count | `code`, `method`, `protocol`, `router`, `service` | The total size of HTTP requests in bytes handled by a router. | + | `router.responses.bytes.total` | Count | `code`, `method`, `protocol`, `router`, `service` | The total size of HTTP responses in bytes handled by a router. | + +=== "InfluxDB2" + + | Metric | Type | [Labels](#labels) | Description | + |-----------------------|-----------|---------------------------------------------------|----------------------------------------------------------------| + | `traefik.router.requests.total` | Count | `code`, `method`, `protocol`, `router`, `service` | The total count of HTTP requests handled by a router. | + | `traefik.router.requests.tls.total` | Count | `tls_version`, `tls_cipher`, `router`, `service` | The total count of HTTPS requests handled by a router. | + | `traefik.router.request.duration.seconds` | Histogram | `code`, `method`, `protocol`, `router`, `service` | Request processing duration histogram on a router. | + | `traefik.router.requests.bytes.total` | Count | `code`, `method`, `protocol`, `router`, `service` | The total size of HTTP requests in bytes handled by a router. | + | `traefik.router.responses.bytes.total` | Count | `code`, `method`, `protocol`, `router`, `service` | The total size of HTTP responses in bytes handled by a router. | + +=== "StatsD" + + | Metric | Type | [Labels](#labels) | Description | + |-----------------------|-----------|---------------|-------------| + | `{prefix}.router.requests.total` | Count | `code`, `method`, `protocol`, `router`, `service` | The total count of HTTP requests handled by a router. | + | `{prefix}.router.requests.tls.total` | Count | `tls_version`, `tls_cipher`, `router`, `service` | The total count of HTTPS requests handled by a router. | + | `{prefix}.router.request.duration.seconds` | Histogram | `code`, `method`, `protocol`, `router`, `service` | Request processing duration histogram on a router. | + | `{prefix}.router.requests.bytes.total` | Count | `code`, `method`, `protocol`, `router`, `service` | The total size of HTTP requests in bytes handled by a router. | + | `{prefix}.router.responses.bytes.total` | Count | `code`, `method`, `protocol`, `router`, `service` | The total size of HTTP responses in bytes handled by a router. | + +!!! note "\{prefix\} Default Value" + By default, \{prefix\} value is `traefik`. + +#### Service Metrics + +=== "OpenTelemetry" + + | Metric | Type | Labels | Description | + |-----------------------|-----------|------------|------------| + | `traefik_service_requests_total` | Count | `code`, `method`, `protocol`, `service` | The total count of HTTP requests processed on a service. | + | `traefik_service_requests_tls_total` | Count | `tls_version`, `tls_cipher`, `service` | The total count of HTTPS requests processed on a service. | + | `traefik_service_request_duration_seconds` | Histogram | `code`, `method`, `protocol`, `service` | Request processing duration histogram on a service. | + | `traefik_service_retries_total` | Count | `service` | The count of requests retries on a service. | + | `traefik_service_server_up` | Gauge | `service`, `url` | Current service's server status, 0 for a down or 1 for up. | + | `traefik_service_requests_bytes_total` | Count | `code`, `method`, `protocol`, `service` | The total size of requests in bytes received by a service. | + | `traefik_service_responses_bytes_total` | Count | `code`, `method`, `protocol`, `service` | The total size of responses in bytes returned by a service. | + +=== "Prometheus" + + | Metric | Type | Labels | Description | + |-----------------------|-----------|-------|------------| + | `traefik_service_requests_total` | Count | `code`, `method`, `protocol`, `service` | The total count of HTTP requests processed on a service. | + | `traefik_service_requests_tls_total` | Count | `tls_version`, `tls_cipher`, `service` | The total count of HTTPS requests processed on a service. | + | `traefik_service_request_duration_seconds` | Histogram | `code`, `method`, `protocol`, `service` | Request processing duration histogram on a service. | + | `traefik_service_retries_total` | Count | `service` | The count of requests retries on a service. | + | `traefik_service_server_up` | Gauge | `service`, `url` | Current service's server status, 0 for a down or 1 for up. | + | `traefik_service_requests_bytes_total` | Count | `code`, `method`, `protocol`, `service` | The total size of requests in bytes received by a service. | + | `traefik_service_responses_bytes_total` | Count | `code`, `method`, `protocol`, `service` | The total size of responses in bytes returned by a service. | + +=== "Datadog" + + | Metric | Type | Labels | Description | + |-----------------------|-----------|--------|------------------| + | `service.requests.total` | Count | `code`, `method`, `protocol`, `service` | The total count of HTTP requests processed on a service. | + | `router.service.tls.total` | Count | `tls_version`, `tls_cipher`, `service` | The total count of HTTPS requests processed on a service. | + | `service.request.duration.seconds` | Histogram | `code`, `method`, `protocol`, `service` | Request processing duration histogram on a service. | + | `service.retries.total` | Count | `service` | The count of requests retries on a service. | + | `service.server.up` | Gauge | `service`, `url` | Current service's server status, 0 for a down or 1 for up. | + | `service.requests.bytes.total` | Count | `code`, `method`, `protocol`, `service` | The total size of requests in bytes received by a service. | + | `service.responses.bytes.total` | Count | `code`, `method`, `protocol`, `service` | The total size of responses in bytes returned by a service. | + +=== "InfluxDB2" + + | Metric | Type | Labels | Description | + |-----------------------|-----------|-----------------------------------------|-------------------------------------------------------------| + | `traefik.service.requests.total` | Count | `code`, `method`, `protocol`, `service` | The total count of HTTP requests processed on a service. | + | `traefik.service.requests.tls.total` | Count | `tls_version`, `tls_cipher`, `service` | The total count of HTTPS requests processed on a service. | + | `traefik.service.request.duration.seconds` | Histogram | `code`, `method`, `protocol`, `service` | Request processing duration histogram on a service. | + | `traefik.service.retries.total` | Count | `service` | The count of requests retries on a service. | + | `traefik.service.server.up` | Gauge | `service`, `url` | Current service's server status, 0 for a down or 1 for up. | + | `traefik.service.requests.bytes.total` | Count | `code`, `method`, `protocol`, `service` | The total size of requests in bytes received by a service. | + | `traefik.service.responses.bytes.total` | Count | `code`, `method`, `protocol`, `service` | The total size of responses in bytes returned by a service. | + +=== "StatsD" + + | Metric | Type | Labels | Description | + |-----------------------|-----------|-----|---------| + | `{prefix}.service.requests.total` | Count | `code`, `method`, `protocol`, `service` | The total count of HTTP requests processed on a service. | + | `{prefix}.service.requests.tls.total` | Count | `tls_version`, `tls_cipher`, `service` | The total count of HTTPS requests processed on a service. | + | `{prefix}.service.request.duration.seconds` | Histogram | `code`, `method`, `protocol`, `service` | Request processing duration histogram on a service. | + | `{prefix}.service.retries.total` | Count | `service` | The count of requests retries on a service. | + | `{prefix}.service.server.up` | Gauge | `service`, `url` | Current service's server status, 0 for a down or 1 for up. | + | `{prefix}.service.requests.bytes.total` | Count | `code`, `method`, `protocol`, `service` | The total size of requests in bytes received by a service. | + | `{prefix}.service.responses.bytes.total` | Count | `code`, `method`, `protocol`, `service` | The total size of responses in bytes returned by a service. | + +!!! note "\{prefix\} Default Value" + By default, \{prefix\} value is `traefik`. + +##### Labels + +Here is a comprehensive list of labels that are provided by the metrics: + +| Label | Description | example | +|---------------|-------------------|----------------------------| +| `cn` | Certificate Common Name | "example.com" | +| `code` | Request code | "200" | +| `entrypoint` | Entrypoint that handled the request | "example_entrypoint" | +| `method` | Request Method | "GET" | +| `protocol` | Request protocol | "http" | +| `router` | Router that handled the request | "example_router" | +| `sans` | Certificate Subject Alternative NameS | "example.com" | +| `serial` | Certificate Serial Number | "123..." | +| `service` | Service that handled the request | "example_service@provider" | +| `tls_cipher` | TLS cipher used for the request | "TLS_FALLBACK_SCSV" | +| `tls_version` | TLS version used for the request | "1.0" | +| `url` | Service server url | "http://example.com" | + +!!! info "`method` label value" + + If the HTTP method verb on a request is not one defined in the set of common methods for [`HTTP/1.1`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) + or the [`PRI`](https://datatracker.ietf.org/doc/html/rfc7540#section-11.6) verb (for `HTTP/2`), + then the value for the method label becomes `EXTENSION_METHOD`. diff --git a/docs/content/reference/install-configuration/observability/options-list.md b/docs/content/reference/install-configuration/observability/options-list.md new file mode 100644 index 000000000..e69de29bb diff --git a/docs/content/reference/install-configuration/observability/tracing.md b/docs/content/reference/install-configuration/observability/tracing.md new file mode 100644 index 000000000..11d8f5814 --- /dev/null +++ b/docs/content/reference/install-configuration/observability/tracing.md @@ -0,0 +1,62 @@ +--- +title: "Traefik Tracing Overview" +description: "The Traefik Proxy tracing system allows developers to visualize call flows in their infrastructure. Read the full documentation." +--- + +# Tracing + +Visualize the Requests Flow +{: .subtitle } + +The tracing system allows developers to visualize call flows in their infrastructure. + +Traefik uses [OpenTelemetry](https://opentelemetry.io/ "Link to website of OTel"), an open standard designed for distributed tracing. + +## Configuration Example + +To enable the tracing: + +```yaml tab="File (YAML)" +tracing: {} +``` + +```toml tab="File (TOML)" +[tracing] +``` + +```bash tab="CLI" +--tracing=true +``` + +```yaml tab="Helm Chart Values" + tracing: + otlp: + enabled: true +``` + +## Configuration Options + +| Field | Description | Default | Required | +|:-----------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------|:---------| +| `tracing.addInternals` | Enables tracing for internal resources (e.g.: `ping@internal`). | false | No | +| `tracing.serviceName` | Service name used in selected backend. | "traefik" | No | +| `tracing.sampleRate` | The proportion of requests to trace, specified between 0.0 and 1.0. | 1.0 | No | +| `tracing.globalAttributes` | Applies a list of shared key:value attributes on all spans. | {} | No | +| `tracing.capturedRequestHeaders` | Defines the list of request headers to add as attributes.
It applies to client and server kind spans.| {} | No | +| `tracing.capturedResponseHeaders` | Defines the list of response headers to add as attributes.
It applies to client and server kind spans.| {} |False | +| `tracing.safeQueryParams` | By default, all query parameters are redacted.
Defines the list of query parameters to not redact. | {} | No | +| `tracing.otlp.http` | This instructs the exporter to send the tracing to the OpenTelemetry Collector using HTTP.
Setting the sub-options with their default values. | null/false | No | +| `tracing.otlp.http.endpoint` | URL of the OpenTelemetry Collector to send tracing to.
Format="`://:`" | "http://localhost:4318/v1/tracing" | Yes | +| `tracing.otlp.http.headers` | Additional headers sent with tracing by the exporter to the OpenTelemetry Collector. | | No | +| `tracing.otlp.http.tls.ca` | Path to the certificate authority used for the secure connection to the OpenTelemetry Collector, it defaults to the system bundle. | "" | No | +| `tracing.otlp.http.tls.cert` | Path to the public certificate used for the secure connection to the OpenTelemetry Collector. When using this option, setting the `key` option is required. | "" | No | +| `tracing.otlp.http.tls.key` | This instructs the exporter to send the tracing to the OpenTelemetry Collector using HTTP.
Setting the sub-options with their default values. | ""null/false "" | No | +| `tracing.otlp.http.tls.insecureskipverify` |If `insecureSkipVerify` is `true`, the TLS connection to the OpenTelemetry Collector accepts any certificate presented by the server regardless of the hostnames it covers. | false | Yes | +| `tracing.otlp.grpc` | This instructs the exporter to send tracing to the OpenTelemetry Collector using gRPC. | false | No | +| `tracing.otlp.grpc.endpoint` | Address of the OpenTelemetry Collector to send tracing to.
Format="`:`" | "localhost:4317" | Yes | +| `tracing.otlp.grpc.headers` | Additional headers sent with tracing by the exporter to the OpenTelemetry Collector. | {} | No | +| `tracing.otlp.grpc.insecure` |Allows exporter to send tracing to the OpenTelemetry Collector without using a secured protocol. | false | Yes | +| `tracing.otlp.grpc.tls.ca` | Path to the certificate authority used for the secure connection to the OpenTelemetry Collector, it defaults to the system bundle. | "" | No | +| `tracing.otlp.grpc.tls.cert` | Path to the public certificate used for the secure connection to the OpenTelemetry Collector. When using this option, setting the `key` option is required. | "" | No | +| `tracing.otlp.grpc.tls.key` | This instructs the exporter to send the tracing to the OpenTelemetry Collector using HTTP.
Setting the sub-options with their default values. | ""null/false "" | No | +| `tracing.otlp.grpc.tls.insecureskipverify` |If `insecureSkipVerify` is `true`, the TLS connection to the OpenTelemetry Collector accepts any certificate presented by the server regardless of the hostnames it covers. | false | Yes | diff --git a/docs/content/reference/install-configuration/providers/docker.md b/docs/content/reference/install-configuration/providers/docker.md new file mode 100644 index 000000000..74e250ae0 --- /dev/null +++ b/docs/content/reference/install-configuration/providers/docker.md @@ -0,0 +1,429 @@ +--- +title: "Traefik Docker Documentation" +description: "Learn how to achieve configuration discovery in Traefik through Docker. Read the technical documentation." +--- + +# Traefik & Docker + +!!! 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 Example + +You can enable the Docker provider as detailed below: + +```yaml tab="File (YAML)" +providers: + docker: {} +``` + +```toml tab="File (TOML)" +[providers.docker] +``` + +```bash tab="CLI" +--providers.docker=true +``` + +Attach labels to containers (in your Docker compose file) + +```yaml +version: "3" +services: + my-container: + # ... + labels: + - traefik.http.routers.my-container.rule=Host(`example.com`) +``` + +## Configuration Options + +| Field | Description | Default | Required | +|:------|:----------------------------------------------------------|:---------------------|:---------| +| `providers.providersThrottleDuration` | Minimum amount of time to wait for, after a configuration reload, before taking into account any new configuration refresh event.
If multiple events occur within this time, only the most recent one is taken into account, and all others are discarded.
**This option cannot be set per provider, but the throttling algorithm applies to each of them independently.** | 2s | No | +| `providers.docker.endpoint` | Specifies the Docker API endpoint. See [here](#endpoint) for more information| "unix:///var/run/docker.sock" | Yes | +| `providers.docker.username` | Defines the username for Basic HTTP authentication. This should be used when the Docker daemon socket is exposed through an HTTP proxy that requires Basic HTTP authentication.| "" | No | +| `providers.docker.password` | Defines the password for Basic HTTP authentication. This should be used when the Docker daemon socket is exposed through an HTTP proxy that requires Basic HTTP authentication.| "" | No | +| `providers.docker.useBindPortIP` | Instructs Traefik to use the IP/Port attached to the container's binding instead of its inner network IP/Port. See [here](#usebindportip) for more information | false | No | +| `providers.docker.exposedByDefault` | Expose containers by default through Traefik. See [here](./overview.md#restrict-the-scope-of-service-discovery) for additional information | true | No | +| `providers.docker.network` | 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.| "" | No | +| `providers.docker.defaultRule` | Defines what routing rule to apply to a container if no rule is defined by a label. See [here](#defaultrule) for more information. | ```"Host(`{{ normalize .Name }}`)"``` | No | +| `providers.docker.httpClientTimeout` | Defines the client timeout (in seconds) for HTTP connections. If its value is 0, no timeout is set. | 0 | No | +| `providers.docker.watch` | Instructs Traefik to watch Docker events or not. | True | No | +| `providers.docker.constraints` | Defines an expression that Traefik matches against the container labels to determine whether to create any route for that container. See [here](#constraints) for more information. | "" | No | +| `providers.docker.allowEmptyServices` | Instructs the provider to create any [servers load balancer](../../../routing/services/index.md#servers-load-balancer) defined for Docker containers regardless of the [healthiness](https://docs.docker.com/engine/reference/builder/#healthcheck) of the corresponding containers. | false | No | +| `providers.docker.tls.ca` | Defines the path to the certificate authority used for the secure connection to Docker, it defaults to the system bundle. | "" | No | +| `providers.docker.tls.cert` | Defines the path to the public certificate used for the secure connection to Docker. When using this option, setting the `key` option is required. | "" | Yes | +| `providers.docker.tls.key` | Defines the path to the private key used for the secure connection to Docker. When using this option, setting the `cert` option is required. | "" | Yes | +| `providers.docker.tls.insecureSkipVerify` | Instructs the provider to accept any certificate presented by the Docker server when establishing a TLS connection, regardless of the hostnames the certificate covers. | false | No | + +### `endpoint` + +See the [Docker 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.1 # The official v3 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: + docker: + endpoint: "unix:///var/run/docker.sock" + # ... + ``` + + ```toml tab="File (TOML)" + [providers.docker] + endpoint = "unix:///var/run/docker.sock" + # ... + ``` + + ```bash tab="CLI" + --providers.docker.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 if the server requires public keys for authentication, you must have them accessible for the user running Traefik. + + ```yaml tab="File (YAML)" + providers: + docker: + endpoint: "ssh://traefik@192.168.2.5:2022" + # ... + ``` + + ```toml tab="File (TOML)" + [providers.docker] + endpoint = "ssh://traefik@192.168.2.5:2022" + # ... + ``` + + ```bash tab="CLI" + --providers.docker.endpoint=ssh://traefik@192.168.2.5:2022 + # ... + ``` + +??? example "Using HTTP" + + Using Docker Engine API you can connect Traefik to remote daemon using HTTP. + + ```yaml tab="File (YAML)" + providers: + docker: + endpoint: "http://127.0.0.1:2375" + # ... + ``` + + ```toml tab="File (TOML)" + [providers.docker] + endpoint = "http://127.0.0.1:2375" + # ... + ``` + + ```bash tab="CLI" + --providers.docker.endpoint=http://127.0.0.1:2375 + # ... + ``` + +??? example "Using TCP" + + Using Docker Engine API you can connect Traefik to remote daemon using TCP. + + ```yaml tab="File (YAML)" + providers: + docker: + endpoint: "tcp://127.0.0.1:2375" + # ... + ``` + + ```toml tab="File (TOML)" + [providers.docker] + endpoint = "tcp://127.0.0.1:2375" + # ... + ``` + + ```bash tab="CLI" + --providers.docker.endpoint=tcp://127.0.0.1:2375 + # ... + ``` + +```yaml tab="File (YAML)" +providers: + docker: + endpoint: "unix:///var/run/docker.sock" +``` + +```toml tab="File (TOML)" +[providers.docker] + endpoint = "unix:///var/run/docker.sock" +``` + +```bash tab="CLI" +--providers.docker.endpoint=unix:///var/run/docker.sock +``` + +### `useBindPortIP` + +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..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..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..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: + docker: + useBindPortIP: true + # ... +``` + +```toml tab="File (TOML)" +[providers.docker] + useBindPortIP = true + # ... +``` + +```bash tab="CLI" +--providers.docker.useBindPortIP=true +# ... +``` + +### `defaultRule` + +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 name can be accessed with the `ContainerName` identifier. +The service name can be accessed with the `Name` identifier. +The template has access to all the labels defined on this container with the `Labels` identifier. + +```yaml tab="File (YAML)" +providers: + docker: + defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" + # ... +``` + +```toml tab="File (TOML)" +[providers.docker] + defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" + # ... +``` + +```bash tab="CLI" +--providers.docker.defaultRule='Host(`{{ .Name }}.{{ index .Labels "customLabel"}}`)' +# ... +``` + +??? info "Default rule and Traefik service" + + The exposure of the Traefik container, combined with the default rule mechanism, + can lead to create a router targeting itself in a loop. + In this case, to prevent an infinite loop, + Traefik adds an internal middleware to refuse the request if it comes from the same router. + +### `constraints` + +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: + docker: + constraints: "Label(`a.label.name`,`foo`)" + # ... +``` + +```toml tab="File (TOML)" +[providers.docker] + constraints = "Label(`a.label.name`,`foo`)" + # ... +``` + +```bash tab="CLI" +--providers.docker.constraints=Label(`a.label.name`,`foo`) +# ... +``` + +## 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 Docker provider. + +### Port Detection + +Traefik retrieves the private IP and port of containers from the Docker API. + +Port detection for private communication works as follows: + +- If a container [exposes](https://docs.docker.com/engine/reference/builder/#expose) a single port, + then Traefik uses this port. +- If a container [exposes](https://docs.docker.com/engine/reference/builder/#expose) multiple ports, + then Traefik uses the lowest port. E.g. if `80` and `8080` are exposed, Traefik will use `80`. +- If a container does not expose any port, or the selection from multiple ports does not fit, + then you must manually specify which port Traefik should use for communication + by using the label `traefik.http.services..loadbalancer.server.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: + +- 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. + - 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) + - Authentication using HTTP Basic authentication through an HTTP proxy that exposes the Docker daemon socket. + + ??? 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) + +{!traefik-for-business-applications.md!} diff --git a/docs/content/reference/install-configuration/providers/hashicorp/consul-catalog.md b/docs/content/reference/install-configuration/providers/hashicorp/consul-catalog.md new file mode 100644 index 000000000..975c0685d --- /dev/null +++ b/docs/content/reference/install-configuration/providers/hashicorp/consul-catalog.md @@ -0,0 +1,205 @@ +--- +title: "Traefik Consul Catalog Documentation" +description: "Learn how to use Consul Catalog as a provider for configuration discovery in Traefik Proxy. Read the technical documentation." +--- + +# Traefik & Consul Catalog + +## Configuration Example + +You can enable the Consul Catalog provider as detailed below: + +```yaml tab="File (YAML)" +providers: + consulCatalog: {} +``` + +```toml tab="File (TOML)" +[providers.consulCatalog] +``` + +```bash tab="CLI" +--providers.consulcatalog=true +``` + +Attaching tags to services: + +```yaml +- traefik.http.routers.my-router.rule=Host(`example.com`) +``` + +## Configuration Options + +| Field | Description | Default | Required | +|:------|:----------------------------------------------------------|:---------------------|:---------| +| `providers.providersThrottleDuration` | Minimum amount of time to wait for, after a configuration reload, before taking into account any new configuration refresh event.
If multiple events occur within this time, only the most recent one is taken into account, and all others are discarded.
**This option cannot be set per provider, but the throttling algorithm applies to each of them independently.** | 2s | No | +| `providers.consulCatalog.refreshInterval` | Defines the polling interval.| 15s | No | +| `providers.consulCatalog.prefix` | Defines the prefix for Consul Catalog tags defining Traefik labels.| traefik | yes | +| `providers.consulCatalog.requireConsistent` | Forces the read to be fully consistent. See [here](#requireconsistent) for more information.| false | yes | +| `providers.consulCatalog.exposedByDefault` | Expose Consul Catalog services by default in Traefik. If set to `false`, services that do not have a `traefik.enable=true` tag will be ignored from the resulting routing configuration. See [here](../overview.md#restrict-the-scope-of-service-discovery). | true | no | +| `providers.consulCatalog.defaultRule` | The Default Host rule for all services. See [here](#defaultrule) for more information. | ```"Host(`{{ normalize .Name }}`)"``` | No | +| `providers.consulCatalog.connectAware` | Enable Consul Connect support. If set to `true`, Traefik will be enabled to communicate with Connect services. | false | No | +| `providers.consulCatalog.connectByDefault` | Consider every service as Connect capable by default. If set to true, Traefik will consider every Consul Catalog service to be Connect capable by default. The option can be overridden on an instance basis with the traefik.consulcatalog.connect tag. | false | No | +| `providers.consulCatalog.serviceName` | Defines the name of the Traefik service in Consul Catalog. | "traefik" | No | +| `providers.consulCatalog.constraints` | Defines an expression that Traefik matches against the container labels to determine whether to create any route for that container. See [here](#constraints) for more information. | "" | No | +| `providers.consulCatalog.namespaces` | Defines the namespaces to query. See [here](#namespaces) for more information. | "" | no | +| `providers.consulCatalog.stale` | Instruct Traefik to use stale consistency for catalog reads. | false | no | +| `providers.consulCatalog.cache` | Instruct Traefik to use local agent caching for catalog reads. | false | no | +| `providers.consulCatalog.endpoint` | Defines the Consul server endpoint. | - | yes | +| `providers.consulCatalog.endpoint.address` | Defines the address of the Consul server. | 127.0.0.1:8500 | no | +| `providers.consulCatalog.endpoint.scheme` | Defines the URI scheme for the Consul server. | "" | no | +| `providers.consulCatalog.endpoint.datacenter` | Defines the datacenter to use. If not provided in Traefik, Consul uses the default agent datacenter. | "" | no | +| `providers.consulCatalog.endpoint.token` | Defines a per-request ACL token which overwrites the agent's default token. | "" | no | +| `providers.consulCatalog.endpoint.endpointWaitTime` | Defines a duration for which a `watch` can block. If not provided, the agent default values will be used. | "" | no | +| `providers.consulCatalog.endpoint.httpAuth` | Defines authentication settings for the HTTP client using HTTP Basic Authentication. | N/A | no | +| `providers.consulCatalog.endpoint.httpAuth.username` | Defines the username to use for HTTP Basic Authentication. | "" | no | +| `providers.consulCatalog.endpoint.httpAuth.password` | Defines the password to use for HTTP Basic Authentication. | "" | no | +| `providers.consulCatalog.strictChecks` | Define which [Consul Service health checks](https://developer.hashicorp.com/consul/docs/services/usage/checks#define-initial-health-check-status) are allowed to take on traffic. | "passing,warning" | no | +| `providers.consulCatalog.tls.ca` | Defines the path to the certificate authority used for the secure connection to Consul Calatog, it defaults to the system bundle. | "" | No | +| `providers.consulCatalog.tls.cert` | Defines the path to the public certificate used for the secure connection to Consul Calatog. When using this option, setting the `key` option is required. | "" | Yes | +| `providers.consulCatalog.tls.key` | Defines the path to the private key used for the secure connection to Consul Catalog. When using this option, setting the `cert` option is required. | "" | Yes | +| `providers.consulCatalog.tls.insecureSkipVerify` | Instructs the provider to accept any certificate presented by Consul Catalog when establishing a TLS connection, regardless of the hostnames the certificate covers. | false | No | +| `providers.consulCatalog.watch` | When set to `true`, watches for Consul changes ([Consul watches checks](https://www.consul.io/docs/dynamic-app-config/watches#checks)). | false | No | + +### `requireConsistent` + +Forces the read to be fully consistent. Setting this option can be expensive due to an extra round-trip but prevents ever performing a stale read. + +For more information, see the Consul [documentation on consistency](https://www.consul.io/api-docs/features/consistency). + +### `defaultRule` + +The default host rule for all services. + +For a given service, if no routing rule was defined by a tag, it is defined by this `defaultRule` instead. +The `defaultRule` must be set to a valid [Go template](https://pkg.go.dev/text/template/), +and can include [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 (i.e. tags beginning with the `prefix`) defined on this service. + +The option can be overridden on an instance basis with the `traefik.http.routers.{name-of-your-choice}.rule` tag. + +```yaml tab="File (YAML)" +providers: + consulCatalog: + defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" + # ... +``` + +```toml tab="File (TOML)" +[providers.consulCatalog] + defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" + # ... +``` + +```bash tab="CLI" +--providers.consulcatalog.defaultRule="Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" +``` + +??? info "Default rule and Traefik service" + + The exposure of the Traefik container, combined with the default rule mechanism, + can lead to create a router targeting itself in a loop. + In this case, to prevent an infinite loop, + Traefik adds an internal middleware to refuse the request if it comes from the same router. + +### `constraints` + +The `constraints` option can be set to an expression that Traefik matches against the service tags to determine whether +to create any route for that service. If none of the service tags match the expression, no route for that service is +created. If the expression is empty, all detected services are included. + +The expression syntax is based on the ```Tag(`tag`)```, and ```TagRegex(`tag`)``` functions, +as well as the usual boolean logic, as shown in examples below. + +??? example "Constraints Expression Examples" + + ```toml + # Includes only services having the tag `a.tag.name=foo` + constraints = "Tag(`a.tag.name=foo`)" + ``` + + ```toml + # Excludes services having any tag `a.tag.name=foo` + constraints = "!Tag(`a.tag.name=foo`)" + ``` + + ```toml + # With logical AND. + constraints = "Tag(`a.tag.name`) && Tag(`another.tag.name`)" + ``` + + ```toml + # With logical OR. + constraints = "Tag(`a.tag.name`) || Tag(`another.tag.name`)" + ``` + + ```toml + # With logical AND and OR, with precedence set by parentheses. + constraints = "Tag(`a.tag.name`) && (Tag(`another.tag.name`) || Tag(`yet.another.tag.name`))" + ``` + + ```toml + # Includes only services having a tag matching the `a\.tag\.t.+` regular expression. + constraints = "TagRegex(`a\.tag\.t.+`)" + ``` + +```yaml tab="File (YAML)" +providers: + consulCatalog: + constraints: "Tag(`a.tag.name`)" + # ... +``` + +```toml tab="File (TOML)" +[providers.consulCatalog] + constraints = "Tag(`a.tag.name`)" + # ... +``` + +```bash tab="CLI" +--providers.consulcatalog.constraints="Tag(`a.tag.name`)" +# ... +``` + +For additional information, refer to [Restrict the Scope of Service Discovery](../overview.md#restrict-the-scope-of-service-discovery). + +### `namespaces` + +The `namespaces` option defines the namespaces in which the consul catalog services will be discovered. +When using the `namespaces` option, the discovered configuration object names will be suffixed as shown below: + +```text +@consulcatalog- +``` + +!!! warning + + - The namespaces option only works with [Consul Enterprise](https://www.consul.io/docs/enterprise), + which provides the [Namespaces](https://www.consul.io/docs/enterprise/namespaces) feature. + + - One should only define either the `namespaces` option or the `namespace` option. + +```yaml tab="File (YAML)" +providers: + consulCatalog: + namespaces: + - "ns1" + - "ns2" + # ... +``` + +```toml tab="File (TOML)" +[providers.consulCatalog] + namespaces = ["ns1", "ns2"] + # ... +``` + +```bash tab="CLI" +--providers.consulcatalog.namespaces=ns1,ns2 +# ... +``` + +## Routing Configuration + +See the dedicated section in [routing](../../../../routing/providers/consul-catalog.md). diff --git a/docs/content/reference/install-configuration/providers/hashicorp/consul.md b/docs/content/reference/install-configuration/providers/hashicorp/consul.md new file mode 100644 index 000000000..01c29796f --- /dev/null +++ b/docs/content/reference/install-configuration/providers/hashicorp/consul.md @@ -0,0 +1,82 @@ +--- +title: "Traefik Consul Documentation" +description: "Use Consul as a provider for configuration discovery in Traefik Proxy. Automate and store your configurations with Consul. Read the technical documentation." +--- + +# Traefik & Consul + +## Configuration Example + +You can enable the Consul provider as detailed below: + +```yaml tab="File (YAML)" +providers: + consul: {} +``` + +```toml tab="File (TOML)" +[providers.consul] +``` + +```bash tab="CLI" +--providers.consul=true +``` + +## Configuration Options + +| Field | Description | Default | Required | +|:------|:----------------------------------------------------------|:---------------------|:---------| +| `providers.providersThrottleDuration` | Minimum amount of time to wait for, after a configuration reload, before taking into account any new configuration refresh event.
If multiple events occur within this time, only the most recent one is taken into account, and all others are discarded.
**This option cannot be set per provider, but the throttling algorithm applies to each of them independently.** | 2s | No | +| `providers.consul.endpoints` | Defines the endpoint to access Consul. | "127.0.0.1:8500" | yes | +| `providers.consul.rootKey` | Defines the root key of the configuration. | "traefik" | yes | +| `providers.consul.namespaces` | Defines the namespaces to query. See [here](#namespaces) for more information | "" | no | +| `providers.consul.username` | Defines a username to connect to Consul with. | "" | no | +| `providers.consul.password` | Defines a password with which to connect to Consul. | "" | no | +| `providers.consul.token` | Defines a token with which to connect to Consul. | "" | no | +| `providers.consul.tls` | Defines the TLS configuration used for the secure connection to Consul | - | No | +| `providers.consul.tls.ca` | Defines the path to the certificate authority used for the secure connection to Consul, it defaults to the system bundle. | - | Yes | +| `providers.consul.tls.cert` | Defines the path to the public certificate used for the secure connection to Consul. When using this option, setting the `key` option is required. | - | Yes | +| `providers.consul.tls.key` | Defines the path to the private key used for the secure connection to Consul. When using this option, setting the `cert` option is required. | - | Yes | +| `providers.consul.tls.insecureSkipVerify` | Instructs the provider to accept any certificate presented by Consul when establishing a TLS connection, regardless of the hostnames the certificate covers. | false | No | + +### `namespaces` + +The `namespaces` option defines the namespaces to query. +When using the `namespaces` option, the discovered configuration object names will be suffixed as shown below: + +```text +@consul- +``` + +!!! warning + + The namespaces 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: + namespaces: + - "ns1" + - "ns2" + # ... +``` + +```toml tab="File (TOML)" +[providers.consul] + namespaces = ["ns1", "ns2"] + # ... +``` + +```bash tab="CLI" +--providers.consul.namespaces=ns1,ns2 +# ... +``` + +## Routing Configuration + +See the dedicated section in [routing](../../../../routing/providers/kv.md). diff --git a/docs/content/reference/install-configuration/providers/hashicorp/nomad.md b/docs/content/reference/install-configuration/providers/hashicorp/nomad.md new file mode 100644 index 000000000..19608cd94 --- /dev/null +++ b/docs/content/reference/install-configuration/providers/hashicorp/nomad.md @@ -0,0 +1,248 @@ +--- +title: "Nomad Service Discovery" +description: "Learn how to use Nomad as a provider for configuration discovery in Traefik Proxy. Read the technical documentation." +--- + +# Traefik & Nomad Service Discovery + +## Configuration Example + +You can enable the Nomad provider with as detailed below: + +```yaml tab="File (YAML)" +providers: + nomad: {} +``` + +```toml tab="File (TOML)" +[providers.nomad] +``` + +```bash tab="CLI" +--providers.nomad=true +``` + +Attaching tags to services: + +```json +... +service { + name = "myService" + tags = [ + "traefik.http.routers.my-router.rule=Host(`example.com`)", + ] +} +... +``` + +## Configuration Options + +| Field | Description | Default | Required | +|:------|:----------------------------------------------------------|:---------------------|:---------| +| `providers.providersThrottleDuration` | Minimum amount of time to wait for, after a configuration reload, before taking into account any new configuration refresh event.
If multiple events occur within this time, only the most recent one is taken into account, and all others are discarded.
**This option cannot be set per provider, but the throttling algorithm applies to each of them independently.** | 2s | No | +| `providers.nomad.namespaces` | Defines the namespaces in which the nomad services will be discovered.| "" | No | +| `providers.nomad.refreshInterval` | Defines the polling interval. This option is ignored when the `watch` option is enabled | 15s | No | +| `providers.nomad.watch` | Enables the watch mode to refresh the configuration on a per-event basis. | false | No | +| `providers.nomad.throttleDuration` | Defines how often the provider is allowed to handle service events from Nomad. This option is only compatible when the `watch` option is enabled | 0s | No | +| `providers.nomad.defaultRule` | The Default Host rule for all services. See [here](#defaultrule) for more information | ```"Host(`{{ normalize .Name }}`)"``` | No | +| `providers.nomad.constraints` | Defines an expression that Traefik matches against the container labels to determine whether to create any route for that container. See [here](#constraints) for more information. | "" | No | +| `providers.nomad.exposedByDefault` | Expose Nomad services by default in Traefik. If set to `false`, services that do not have a `traefik.enable=true` tag will be ignored from the resulting routing configuration. See [here](../overview.md#restrict-the-scope-of-service-discovery) for additional information | true | No | +| `providers.nomad.allowEmptyServices` | Instructs the provider to create any [servers load balancer](../../../../routing/services/index.md#servers-load-balancer) defined for Docker containers regardless of the [healthiness](https://docs.docker.com/engine/reference/builder/#healthcheck) of the corresponding containers. | false | No | +| `providers.nomad.prefix` | Defines the prefix for Nomad service tags defining Traefik labels. | `traefik` | yes | +| `providers.nomad.stale` | Instructs Traefik to use stale consistency for Nomad service API reads. See [here](#stale) for more information | false | No | +| `providers.nomad.endpoint.address` | Defines the Address of the Nomad server. | `http://127.0.0.1:4646` | No | +| `providers.nomad.endpoint.token` | Defines a per-request ACL token if Nomad ACLs are enabled. See [here](#token) for more information | "" | No | +| `providers.nomad.endpoint.endpointWaitTime` | Defines a duration for which a `watch` can block. If not provided, the agent default values will be used. | "" | No | +| `providers.nomad.endpoint.tls` | Defines the TLS configuration used for the secure connection to the Nomad APi. | - | No | +| `providers.nomad.endpoint.tls.ca` | Defines the path to the certificate authority used for the secure connection to the Nomad API, it defaults to the system bundle. | "" | No | +| `providers.nomad.endpoint.tls.cert` | Defines the path to the public certificate used for the secure connection to the Nomad API. When using this option, setting the `key` option is required. | '" | Yes | +| `providers.nomad.endpoint.tls.key` | Defines the path to the private key used for the secure connection to the Nomad API. When using this option, setting the `cert` option is required. | "" | Yes | +| `providers.nomad.endpoint.tls.insecureSkipVerify` | Instructs the provider to accept any certificate presented by Nomad when establishing a TLS connection, regardless of the hostnames the certificate covers. | false | No | + +### `namespaces` + +The `namespaces` option defines the namespaces in which the nomad services will be discovered. +When using the `namespaces` option, the discovered object names will be suffixed as shown below: + +```text +@nomad- +``` + +!!! warning + + One should only define either the `namespaces` option or the `namespace` option. + +```yaml tab="File (YAML)" +providers: + nomad: + namespaces: + - "ns1" + - "ns2" + # ... +``` + +```toml tab="File (TOML)" +[providers.nomad] + namespaces = ["ns1", "ns2"] + # ... +``` + +```bash tab="CLI" +--providers.nomad.namespaces=ns1,ns2 +# ... +``` + +### `stale` + +Use stale consistency for Nomad service API reads. + +!!! note "" + + This makes reads very fast and scalable at the cost of a higher likelihood of stale values. + + For more information, see the Nomad [documentation on consistency](https://www.nomadproject.io/api-docs#consistency-modes). + +```yaml tab="File (YAML)" +providers: + nomad: + stale: true + # ... +``` + +```toml tab="File (TOML)" +[providers.nomad] + stale = true + # ... +``` + +```bash tab="CLI" +--providers.nomad.stale=true +# ... +``` + +### `token` + +Token is used to provide a per-request ACL token, if Nomad ACLs are enabled. +The appropriate ACL privilege for this token is 'read-job', as outlined in the [Nomad documentation on ACL](https://developer.hashicorp.com/nomad/tutorials/access-control/access-control-policies). + +```yaml tab="File (YAML)" +providers: + nomad: + endpoint: + token: test + # ... +``` + +```toml tab="File (TOML)" +[providers.nomad] + [providers.nomad.endpoint] + token = "test" + # ... +``` + +```bash tab="CLI" +--providers.nomad.endpoint.token=test +# ... +``` + +### `defaultRule` + +The default host rule for all services. + +For a given service, if no routing rule was defined by a tag, it is defined by this `defaultRule` instead. +The `defaultRule` must be set to a valid [Go template](https://pkg.go.dev/text/template/), +and can include [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 (i.e. tags beginning with the `prefix`) defined on this service. + +The option can be overridden on an instance basis with the `traefik.http.routers.{name-of-your-choice}.rule` tag. + +```yaml tab="File (YAML)" +providers: + nomad: + defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" + # ... +``` + +```toml tab="File (TOML)" +[providers.nomad] + defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" + # ... +``` + +```bash tab="CLI" +--providers.nomad.defaultRule='Host(`{{ .Name }}.{{ index .Labels "customLabel"}}`)' +# ... +``` + +??? info "Default rule and Traefik service" + + The exposure of the Traefik container, combined with the default rule mechanism, + can lead to create a router targeting itself in a loop. + In this case, to prevent an infinite loop, + Traefik adds an internal middleware to refuse the request if it comes from the same router. + +### `constraints` + +The `constraints` option can be set to an expression that Traefik matches against the service tags to determine whether +to create any route for that service. If none of the service tags match the expression, no route for that service is +created. If the expression is empty, all detected services are included. + +The expression syntax is based on the ```Tag(`tag`)```, and ```TagRegex(`tag`)``` functions, +as well as the usual boolean logic, as shown in examples below. + +??? example "Constraints Expression Examples" + + ```toml + # Includes only services having the tag `a.tag.name=foo` + constraints = "Tag(`a.tag.name=foo`)" + ``` + + ```toml + # Excludes services having any tag `a.tag.name=foo` + constraints = "!Tag(`a.tag.name=foo`)" + ``` + + ```toml + # With logical AND. + constraints = "Tag(`a.tag.name`) && Tag(`another.tag.name`)" + ``` + + ```toml + # With logical OR. + constraints = "Tag(`a.tag.name`) || Tag(`another.tag.name`)" + ``` + + ```toml + # With logical AND and OR, with precedence set by parentheses. + constraints = "Tag(`a.tag.name`) && (Tag(`another.tag.name`) || Tag(`yet.another.tag.name`))" + ``` + + ```toml + # Includes only services having a tag matching the `a\.tag\.t.+` regular expression. + constraints = "TagRegex(`a\.tag\.t.+`)" + ``` + +```yaml tab="File (YAML)" +providers: + nomad: + constraints: "Tag(`a.tag.name`)" + # ... +``` + +```toml tab="File (TOML)" +[providers.nomad] + constraints = "Tag(`a.tag.name`)" + # ... +``` + +```bash tab="CLI" +--providers.nomad.constraints="Tag(`a.tag.name`)" +# ... +``` + +For additional information, refer to [Restrict the Scope of Service Discovery](../overview.md#restrict-the-scope-of-service-discovery). + +## Routing Configuration + +See the dedicated section in [routing](../../../../routing/providers/nomad.md). diff --git a/docs/content/reference/install-configuration/providers/kubernetes/kubernetes-crd.md b/docs/content/reference/install-configuration/providers/kubernetes/kubernetes-crd.md new file mode 100644 index 000000000..7d29e5507 --- /dev/null +++ b/docs/content/reference/install-configuration/providers/kubernetes/kubernetes-crd.md @@ -0,0 +1,133 @@ +--- +title: 'Kubernetes Custom Resources' +description: 'Configure the Kubernetes CRD provider that allows managing Traefik custom resources.' +--- + +Traefik provides some Kubernetes Custom Resources, such as `IngressRoute`, `Middleware`, etc. + +When using KubernetesCRD as a provider, +Traefik uses [Custom Resource Definition](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) to retrieve its routing configuration. +Traefik Custom Resource Definitions are [listed below](#list-of-resources). + +When Traefik is installed using the Helm Chart, by default, the provider `kubernetesCRD` is enabled. + +## Requirements + +When you install Traefik without using the Helm Chart, or when you are upgrading the stack using Helm, ensure that you satisfy the following requirements: + +- Add/update **all** the Traefik resources definitions +- Add/update the [RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) for the Traefik custom resources + +```bash +# Install Traefik Resource Definitions: +kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.2/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml + +# Install RBAC for Traefik: +kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.2/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml +``` + +## Configuration Example + +You can enable the `kubernetesCRD` provider as detailed below: + +```yaml tab="File (YAML)" +providers: + kubernetesCRD: {} +``` + +```toml tab="File (TOML)" +[providers.kubernetesCRD] +``` + +```bash tab="CLI" +--providers.kubernetescrd=true +``` + +```yaml tab="Helm Chart Values" +## Values file +providers: + kubernetesCRD: + enabled: true +``` + +## Configuration Options + +| Field | Description | Default | Required | +|:------|:----------------------------------------------------------|:---------------------|:---------| +| `providers.providersThrottleDuration` | Minimum amount of time to wait for, after a configuration reload, before taking into account any new configuration refresh event.
If multiple events occur within this time, only the most recent one is taken into account, and all others are discarded.
**This option cannot be set per provider, but the throttling algorithm applies to each of them independently.** | 2s | No | +| `providers.kubernetesCRD.endpoint` | Server endpoint URL.
More information [here](#endpoint). | "" | No | +| `providers.kubernetesCRD.token` | Bearer token used for the Kubernetes client configuration. | "" | No | +| `providers.kubernetesCRD.certAuthFilePath` | Path to the certificate authority file.
Used for the Kubernetes client configuration. | "" | No | +| `providers.kubernetesCRD.namespaces` | Array of namespaces to watch.
If left empty, watch all namespaces. | {} | No | +| `providers.kubernetesCRD.labelselector` | Allow filtering on specific resource objects only using label selectors.
Only to Traefik [Custom Resources](#list-of-resources) (they all must match the filter).
No effect on Kubernetes `Secrets`, `EndpointSlices` and `Services`.
See [label-selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors) for details. | "" | No | +| `providers.kubernetesCRD.ingressClass` | Value of `kubernetes.io/ingress.class` annotation that identifies resource objects to be processed.
If empty, resources missing the annotation, having an empty value, or the value `traefik` are processed. | "" | No | +| `providers.kubernetesCRD.throttleDuration` | Minimum amount of time to wait between two Kubernetes events before producing a new configuration.
This prevents a Kubernetes cluster that updates many times per second from continuously changing your Traefik configuration.
If empty, every event is caught. | 0s | No | +| `providers.kubernetesCRD.allowEmptyServices` | Allows creating a route to reach a service that has no endpoint available.
It allows Traefik to handle the requests and responses targeting this service (applying middleware or observability operations) before returning a `503` HTTP Status. | false | No | +| `providers.kubernetesCRD.allowCrossNamespace` | Allows the `IngressRoutes` to reference resources in namespaces other than theirs. | false | No | +| `providers.kubernetesCRD.allowExternalNameServices` | Allows the `IngressRoutes` to reference ExternalName services. | false | No | +| `providers.kubernetesCRD.nativeLBByDefault` | Allow using the Kubernetes Service load balancing between the pods instead of the one provided by Traefik for every `IngressRoute` by default.
It can br overridden in the [`ServerTransport`](../../../../routing/services/index.md#serverstransport). | false | No | +| `providers.kubernetesCRD.disableClusterScopeResources` | Prevent from discovering cluster scope resources (`IngressClass` and `Nodes`).
By doing so, it alleviates the requirement of giving Traefik the rights to look up for cluster resources.
Furthermore, Traefik will not handle IngressRoutes with IngressClass references, therefore such Ingresses will be ignored (please note that annotations are not affected by this option).
This will also prevent from using the `NodePortLB` options on services. | false | No | + +### endpoint + +The Kubernetes server endpoint URL. + +When deployed into Kubernetes, Traefik reads the environment variables `KUBERNETES_SERVICE_HOST` and `KUBERNETES_SERVICE_PORT` or `KUBECONFIG` to construct the endpoint. + +The access token is looked up in `/var/run/secrets/kubernetes.io/serviceaccount/token` and the SSL CA certificate in `/var/run/secrets/kubernetes.io/serviceaccount/ca.crt`. +Both are mounted automatically when deployed inside Kubernetes. + +The endpoint may be specified to override the environment variable values inside a cluster. + +When the environment variables are not found, Traefik tries to connect to the Kubernetes API server with an external-cluster client. +In this case, the endpoint is required. +Specifically, it may be set to the URL used by `kubectl proxy` to connect to a Kubernetes cluster using the granted authentication and authorization of the associated kubeconfig. + +```yaml tab="File (YAML)" +providers: + kubernetesCRD: + endpoint: "http://localhost:8080" + # ... +``` + +```toml tab="File (TOML)" +[providers.kubernetesCRD] + endpoint = "http://localhost:8080" + # ... +``` + +```bash tab="CLI" +--providers.kubernetesCRD.endpoint=http://localhost:8080 +``` + +## Routing Configuration + +See the dedicated section in [routing](../../../../routing/providers/kubernetes-crd.md). + +## List of Resources + + + +| Resource | Purpose | +|--------------------------------------------------|--------------------------------------------------------------------| +| [IngressRoute](../../../../routing/providers/kubernetes-crd.md#kind-ingressroute) | HTTP Routing | +| [Middleware](../../../../middlewares/http/overview.md) | Tweaks the HTTP requests before they are sent to your service | +| [TraefikService](../../../../routing/providers/kubernetes-crd.md#kind-traefikservice) | Abstraction for HTTP loadbalancing/mirroring | +| [TLSOptions](../../../../routing/providers/kubernetes-crd.md#kind-tlsoption) | Allows configuring some parameters of the TLS connection | +| [TLSStores](../../../../routing/providers/kubernetes-crd.md#kind-tlsstore) | Allows configuring the default TLS store | +| [ServersTransport](../../../../routing/providers/kubernetes-crd.md#kind-serverstransport) | Allows configuring the transport between Traefik and the backends | +| [IngressRouteTCP](../../../../routing/providers/kubernetes-crd.md#kind-ingressroutetcp) | TCP Routing | +| [MiddlewareTCP](../../../../routing/providers/kubernetes-crd.md#kind-middlewaretcp) | Tweaks the TCP requests before they are sent to your service | +| [ServersTransportTCP](../../../../routing/providers/kubernetes-crd.md#kind-serverstransporttc) | Allows configuring the transport between Traefik and the backends | +| [IngressRouteUDP](../../../../routing/providers/kubernetes-crd.md#kind-ingressrouteudp) | UDP Routing | + +## Particularities + +- The usage of `name` **and** `namespace` to refer to another Kubernetes resource. +- The usage of [secret](https://kubernetes.io/docs/concepts/configuration/secret/) for sensitive data (TLS certificates and credentials). + +## Full Example + +For additional information, refer to the [full example](../../../../user-guides/crd-acme/index.md) with Let's Encrypt. + +{!traefik-for-business-applications.md!} diff --git a/docs/content/reference/install-configuration/providers/kubernetes/kubernetes-gateway.md b/docs/content/reference/install-configuration/providers/kubernetes/kubernetes-gateway.md new file mode 100644 index 000000000..f009d99ba --- /dev/null +++ b/docs/content/reference/install-configuration/providers/kubernetes/kubernetes-gateway.md @@ -0,0 +1,139 @@ +--- +title: "Traefik Kubernetes Gateway API Documentation" +description: "Learn how to use the Kubernetes Gateway API as a provider for configuration discovery in Traefik Proxy. Read the technical documentation." +--- + +# Traefik & Kubernetes with Gateway API + +The Kubernetes Gateway provider is a Traefik implementation of the [Gateway API](https://gateway-api.sigs.k8s.io/) +specification from the Kubernetes Special Interest Groups (SIGs). + +This provider supports Standard version [v1.2.0](https://github.com/kubernetes-sigs/gateway-api/releases/tag/v1.2.0) of the Gateway API specification. + +It fully supports all HTTP core and some extended features, as well as the `TCPRoute` and `TLSRoute` resources from the [Experimental channel](https://gateway-api.sigs.k8s.io/concepts/versioning/?h=#release-channels). + +For more details, check out the conformance [report](https://github.com/kubernetes-sigs/gateway-api/tree/main/conformance/reports/v1.2.0/traefik-traefik). + +!!! info "Using The Helm Chart" + + When using the Traefik [Helm Chart](../../../../getting-started/install-traefik.md#use-the-helm-chart), the CRDs (Custom Resource Definitions) and RBAC (Role-Based Access Control) are automatically managed for you. + The only remaining task is to enable the `kubernetesGateway` in the chart [values](https://github.com/traefik/traefik-helm-chart/blob/master/traefik/values.yaml#L130). + +## Requirements + +{!kubernetes-requirements.md!} + +1. Install/update the Kubernetes Gateway API CRDs. + + ```bash + # Install Gateway API CRDs from the Standard channel. + kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml + ``` + +2. Install/update the Traefik [RBAC](../../../dynamic-configuration/kubernetes-gateway-rbac.yml). + + ```bash + # Install Traefik RBACs. + kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.2/docs/content/reference/dynamic-configuration/kubernetes-gateway-rbac.yml + ``` + +## Configuration Example + +You can enable the `kubernetesGateway` provider as detailed below: + +```yaml tab="File (YAML)" +providers: + kubernetesGateway: {} + # ... +``` + +```toml tab="File (TOML)" +[providers.kubernetesGateway] +# ... +``` + +```bash tab="CLI" +--providers.kubernetesgateway=true +``` + +```yaml tab="Helm Chart Values" +## Values file +providers: + kubernetesGateway: + enabled: true +``` + +## Configuration Options + + + +| Field | Description | Default | Required | +|:------|:----------------------------------------------------------|:---------------------|:---------| +| `providers.providersThrottleDuration` | Minimum amount of time to wait for, after a configuration reload, before taking into account any new configuration refresh event.
If multiple events occur within this time, only the most recent one is taken into account, and all others are discarded.
**This option cannot be set per provider, but the throttling algorithm applies to each of them independently.** | 2s | No | +| `providers.kubernetesGateway.endpoint` | Server endpoint URL.
More information [here](#endpoint). | "" | No | +| `providers.kubernetesGateway.experimentalChannel` | Toggles support for the Experimental Channel resources ([Gateway API release channels documentation](https://gateway-api.sigs.k8s.io/concepts/versioning/#release-channels)).
(ex: `TCPRoute` and `TLSRoute`)| false | No | +| `providers.kubernetesGateway.token` | Bearer token used for the Kubernetes client configuration. | "" | No | +| `providers.kubernetesGateway.certAuthFilePath` | Path to the certificate authority file.
Used for the Kubernetes client configuration. | "" | No | +| `providers.kubernetesGateway.namespaces` | Array of namespaces to watch.
If left empty, watch all namespaces. | {} | No | +| `providers.kubernetesGateway.labelselector` | Allow filtering on specific resource objects only using label selectors.
Only to Traefik [Custom Resources](./kubernetes-crd.md#list-of-resources) (they all must match the filter).
No effect on Kubernetes `Secrets`, `EndpointSlices` and `Services`.
See [label-selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors) for details. | "" | No | +| `providers.kubernetesGateway.throttleDuration` | Minimum amount of time to wait between two Kubernetes events before producing a new configuration.
This prevents a Kubernetes cluster that updates many times per second from continuously changing your Traefik configuration.
If empty, every event is caught. | 0s | No | +| `providers.kubernetesGateway.nativeLBByDefault` | Defines whether to use Native Kubernetes load-balancing mode by default. For more information, please check out the `traefik.io/service.nativelb` service annotation documentation. | false | No | +| `providers.kubernetesGateway.`
`statusAddress.hostname` | Hostname copied to the Gateway `status.addresses`. | "" | No | +| `providers.kubernetesGateway.`
`statusAddress.ip` | IP address copied to the Gateway `status.addresses`, and currently only supports one IP value (IPv4 or IPv6). | "" | No | +| `providers.kubernetesGateway.`
`statusAddress.publishedService` | The Kubernetes service to copy status addresses from.
When using third parties tools like External-DNS, this option can be used to copy the service `loadbalancer.status` (containing the service's endpoints IPs) to the gateways. | "" | No | + + + +### `endpoint` + +The Kubernetes server endpoint URL. + +When deployed into Kubernetes, Traefik reads the environment variables +`KUBERNETES_SERVICE_HOST` and `KUBERNETES_SERVICE_PORT` or `KUBECONFIG` to +construct the endpoint. + +The access token is looked up +in `/var/run/secrets/kubernetes.io/serviceaccount/token` +and the SSL CA certificate in `/var/run/secrets/kubernetes.io/serviceaccount/ca.crt`. +Both are mounted automatically when deployed inside Kubernetes. + +The endpoint may be specified to override the environment variable values +inside a cluster. + +When the environment variables are not found, Traefik tries to connect to +the Kubernetes API server with an external-cluster client. +In this case, the endpoint is required. +Specifically, it may be set to the URL used by `kubectl proxy` to connect to a +Kubernetes cluster using the granted authentication +and authorization of the associated kubeconfig. + +```yaml tab="File (YAML)" +providers: + kubernetesGateway: + endpoint: "http://localhost:8080" + # ... +``` + +```toml tab="File (TOML)" +[providers.kubernetesGateway] + endpoint = "http://localhost:8080" + # ... +``` + +```bash tab="CLI" +--providers.kubernetesgateway.endpoint=http://localhost:8080 +``` + +## Routing Configuration + +See the dedicated section in [routing](../../../../routing/providers/kubernetes-gateway.md). + +!!! tip "Routing Configuration" + + When using the Kubernetes Gateway API provider, Traefik uses the Gateway API + CRDs to retrieve its routing configuration. + Check out the Gateway API concepts [documentation](https://gateway-api.sigs.k8s.io/concepts/api-overview/), + and the dedicated [routing section](../../../../routing/providers/kubernetes-gateway.md) + in the Traefik documentation. + +{!traefik-for-business-applications.md!} diff --git a/docs/content/reference/install-configuration/providers/kubernetes/kubernetes-ingress.md b/docs/content/reference/install-configuration/providers/kubernetes/kubernetes-ingress.md new file mode 100644 index 000000000..7f7ec3455 --- /dev/null +++ b/docs/content/reference/install-configuration/providers/kubernetes/kubernetes-ingress.md @@ -0,0 +1,114 @@ +--- +title: "Traefik Kubernetes Ingress Documentation" +description: "Understand the requirements, routing configuration, and how to set up Traefik Proxy as your Kubernetes Ingress Controller. Read the technical documentation." +--- + +# Traefik & Kubernetes + +The Traefik Kubernetes Ingress provider is a Kubernetes Ingress controller; i.e, +it manages access to cluster services by supporting the [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) specification. + +## Configuration Example + +You can enable the `kubernetesIngress` provider as detailed below: + +```yaml tab="File (YAML)" +providers: + kubernetesIngress: {} +``` + +```toml tab="File (TOML)" +[providers.kubernetesIngress] +``` + +```bash tab="CLI" +--providers.kubernetesingress=true +``` + +```yaml tab="Helm Chart Values" +## Values file +providers: + kubernetesIngress: + enabled: true +``` + +The provider then watches for incoming ingresses events, such as the example below, +and derives the corresponding dynamic configuration from it, +which in turn creates the resulting routers, services, handlers, etc. + +## Configuration Options + + +| Field | Description | Default | Required | +|:------|:----------------------------------------------------------|:---------------------|:---------| +| `providers.providersThrottleDuration` | Minimum amount of time to wait for, after a configuration reload, before taking into account any new configuration refresh event.
If multiple events occur within this time, only the most recent one is taken into account, and all others are discarded.
**This option cannot be set per provider, but the throttling algorithm applies to each of them independently.** | 2s | No | +| `providers.kubernetesIngress.endpoint` | Server endpoint URL.
More information [here](#endpoint). | "" | No | +| `providers.kubernetesIngress.token` | Bearer token used for the Kubernetes client configuration. | "" | No | +| `providers.kubernetesIngress.certAuthFilePath` | Path to the certificate authority file.
Used for the Kubernetes client configuration. | "" | No | +| `providers.kubernetesCRD.namespaces` | Array of namespaces to watch.
If left empty, watch all namespaces. | | No | +| `providers.kubernetesIngress.labelselector` | Allow filtering on Ingress objects using label selectors.
No effect on Kubernetes `Secrets`, `EndpointSlices` and `Services`.
See [label-selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors) for details. | "" | No | +| `providers.kubernetesIngress.ingressClass` | The `IngressClass` resource name or the `kubernetes.io/ingress.class` annotation value that identifies resource objects to be processed.
If empty, resources missing the annotation, having an empty value, or the value `traefik` are processed. | "" | No | +| `providers.kubernetesIngress.disableIngressClassLookup` | Prevent to discover IngressClasses in the cluster.
It alleviates the requirement of giving Traefik the rights to look IngressClasses up.
Ignore Ingresses with IngressClass.
Annotations are not affected by this option. | false | No | +| `providers.kubernetesIngress.`
`ingressEndpoint.hostname` | Hostname used for Kubernetes Ingress endpoints. | "" | No | +| `providers.kubernetesIngress.`
`ingressEndpoint.ip` | This IP will get copied to the Ingress `status.loadbalancer.ip`, and currently only supports one IP value (IPv4 or IPv6). | "" | No | +| `providers.kubernetesIngress.`
`ingressEndpoint.publishedService` | The Kubernetes service to copy status from.
When using third parties tools like External-DNS, this option can be used to copy the service `loadbalancer.status` (containing the service's endpoints IPs) to the ingresses. | "" | No | +| `providers.kubernetesIngress.throttleDuration` | Minimum amount of time to wait between two Kubernetes events before producing a new configuration.
This prevents a Kubernetes cluster that updates many times per second from continuously changing your Traefik configuration.
If empty, every event is caught. | 0s | No | +| `providers.kubernetesIngress.allowEmptyServices` | Allows creating a route to reach a service that has no endpoint available.
It allows Traefik to handle the requests and responses targeting this service (applying middleware or observability operations) before returning a `503` HTTP Status. | false | No | +| `providers.kubernetesIngress.allowCrossNamespace` | Allows the `Ingress` to reference resources in namespaces other than theirs. | false | No | +| `providers.kubernetesIngress.allowExternalNameServices` | Allows the `Ingress` to reference ExternalName services. | false | No | +| `providers.kubernetesIngress.nativeLBByDefault` | Allow using the Kubernetes Service load balancing between the pods instead of the one provided by Traefik for every `Ingress` by default.
It can br overridden in the [`ServerTransport`](../../../../routing/services/index.md#serverstransport). | false | No | +| `providers.kubernetesIngress.disableClusterScopeResources` | Prevent from discovering cluster scope resources (`IngressClass` and `Nodes`).
By doing so, it alleviates the requirement of giving Traefik the rights to look up for cluster resources.
Furthermore, Traefik will not handle Ingresses with IngressClass references, therefore such Ingresses will be ignored (please note that annotations are not affected by this option).
This will also prevent from using the `NodePortLB` options on services. | false | No | + + + +### `endpoint` + +The Kubernetes server endpoint URL. + +When deployed into Kubernetes, Traefik reads the environment variables `KUBERNETES_SERVICE_HOST` +and `KUBERNETES_SERVICE_PORT` or `KUBECONFIG` to construct the endpoint. + +The access token is looked up in `/var/run/secrets/kubernetes.io/serviceaccount/token` +and the SSL CA certificate in `/var/run/secrets/kubernetes.io/serviceaccount/ca.crt`. +Both are mounted automatically when deployed inside Kubernetes. + +The endpoint may be specified to override the environment variable values inside +a cluster. + +When the environment variables are not found, Traefik tries to connect to the +Kubernetes API server with an external-cluster client. + +In this case, the endpoint is required. +Specifically, it may be set to the URL used by `kubectl proxy` to connect to a Kubernetes +cluster using the granted authentication and authorization of the associated kubeconfig. + +```yaml tab="File (YAML)" +providers: + kubernetesIngress: + endpoint: "http://localhost:8080" + # ... +``` + +```toml tab="File (TOML)" +[providers.kubernetesIngress] + endpoint = "http://localhost:8080" + # ... +``` + +```bash tab="CLI" +--providers.kubernetesingress.endpoint=http://localhost:8080 +``` + +## Routing Configuration + +See the dedicated section in [routing](../../../../routing/providers/kubernetes-ingress.md). + +## 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/v3.1/pkg/provider/kubernetes/ingress/fixtures) +of the Traefik repository. + +{!traefik-for-business-applications.md!} diff --git a/docs/content/reference/install-configuration/providers/kv/consul.md b/docs/content/reference/install-configuration/providers/kv/consul.md new file mode 100644 index 000000000..9eeca6977 --- /dev/null +++ b/docs/content/reference/install-configuration/providers/kv/consul.md @@ -0,0 +1,6 @@ +--- +title: "Traefik Consul Documentation" +description: "Use Consul as a provider for configuration discovery in Traefik Proxy. Automate and store your configurations with Consul. Read the technical documentation." +--- + +--8<-- "content/reference/install-configuration/providers/hashicorp/consul.md" diff --git a/docs/content/reference/install-configuration/providers/kv/etcd.md b/docs/content/reference/install-configuration/providers/kv/etcd.md new file mode 100644 index 000000000..b5e80e6b6 --- /dev/null +++ b/docs/content/reference/install-configuration/providers/kv/etcd.md @@ -0,0 +1,42 @@ +--- +title: "Traefik Etcd Documentation" +description: "Use etcd as a provider for configuration discovery in Traefik Proxy. Automate and store your configurations with Etcd. Read the technical documentation." +--- + +# Traefik & etcd + +## Configuration Example + +You can enable the etcd provider as detailed below: + +```yaml tab="File (YAML)" +providers: + etcd: {} +``` + +```toml tab="File (TOML)" +[providers.etcd] +``` + +```bash tab="CLI" +--providers.etcd=true +``` + +## Configuration Options + +| Field | Description | Default | Required | +|:------|:----------------------------------------------------------|:---------------------|:---------| +| `providers.providersThrottleDuration` | Minimum amount of time to wait for, after a configuration reload, before taking into account any new configuration refresh event.
If multiple events occur within this time, only the most recent one is taken into account, and all others are discarded.
**This option cannot be set per provider, but the throttling algorithm applies to each of them independently.** | 2s | No | +| `providers.etcd.endpoints` | Defines the endpoint to access etcd. | "127.0.0.1:2379" | Yes | +| `providers.etcd.rootKey` | Defines the root key for the configuration. | "traefik" | Yes | +| `providers.etcd.username` | Defines a username with which to connect to etcd. | "" | No | +| `providers.etcd.password` | Defines a password for connecting to etcd. | "" | No | +| `providers.etcd.tls` | Defines the TLS configuration used for the secure connection to etcd. | - | No | +| `providers.etcd.tls.ca` | Defines the path to the certificate authority used for the secure connection to etcd, it defaults to the system bundle. | "" | No | +| `providers.etcd.tls.cert` | Defines the path to the public certificate used for the secure connection to etcd. When using this option, setting the `key` option is required. | "" | Yes | +| `providers.etcd.tls.key` | Defines the path to the private key used for the secure connection to etcd. When using this option, setting the `cert` option is required. | "" | Yes | +| `providers.etcd.tls.insecureSkipVerify` | Instructs the provider to accept any certificate presented by etcd when establishing a TLS connection, regardless of the hostnames the certificate covers. | false | No | + +## Routing Configuration + +See the dedicated section in [routing](../../../../routing/providers/kv.md). diff --git a/docs/content/reference/install-configuration/providers/kv/redis.md b/docs/content/reference/install-configuration/providers/kv/redis.md new file mode 100644 index 000000000..40c91bfbc --- /dev/null +++ b/docs/content/reference/install-configuration/providers/kv/redis.md @@ -0,0 +1,51 @@ +--- +title: "Traefik Redis Documentation" +description: "For configuration discovery in Traefik Proxy, you can store your configurations in Redis. Read the technical documentation." +--- + +# Traefik & Redis + +## Configuration Example + +You can enable the Redis provider as detailed below: + +```yaml tab="File (YAML)" +providers: + redis: {} +``` + +```toml tab="File (TOML)" +[providers.redis] +``` + +```bash tab="CLI" +--providers.redis.endpoints=true +``` + +## Configuration Options + +| Field | Description | Default | Required | +|:------|:----------------------------------------------------------|:---------------------|:---------| +| `providers.providersThrottleDuration` | Minimum amount of time to wait for, after a configuration reload, before taking into account any new configuration refresh event.
If multiple events occur within this time, only the most recent one is taken into account, and all others are discarded.
**This option cannot be set per provider, but the throttling algorithm applies to each of them independently.** | 2s | No | +| `providers.redis.endpoints` | Defines the endpoint to access Redis. | "127.0.0.1:6379" | Yes | +| `providers.redis.rootKey` | Defines the root key for the configuration. | "traefik" | Yes | +| `providers.redis.username` | Defines a username for connecting to Redis. | "" | No | +| `providers.redis.password` | Defines a password for connecting to Redis. | "" | No | +| `providers.redis.db` | Defines the database to be selected after connecting to the Redis. | 0 | No | +| `providers.redis.tls` | Defines the TLS configuration used for the secure connection to Redis. | - | No | +| `providers.redis.tls.ca` | Defines the path to the certificate authority used for the secure connection to Redis, it defaults to the system bundle. | "" | No | +| `providers.redis.tls.cert` | Defines the path to the public certificate used for the secure connection to Redis. When using this option, setting the `key` option is required. | "" | Yes | +| `providers.redis.tls.key` | Defines the path to the private key used for the secure connection to Redis. When using this option, setting the `cert` option is required. | "" | Yes | +| `providers.redis.tls.insecureSkipVerify` | Instructs the provider to accept any certificate presented by Redis when establishing a TLS connection, regardless of the hostnames the certificate covers. | false | No | +| `providers.redis.sentinel` | Defines the Sentinel configuration used to interact with Redis Sentinel. | - | No | +| `providers.redis.sentinel.masterName` | Defines the name of the Sentinel master. | "" | Yes | +| `providers.redis.sentinel.username` | Defines the username for Sentinel authentication. | "" | No | +| `providers.redis.sentinel.password` | Defines the password for Sentinel authentication. | "" | No | +| `providers.redis.sentinel.latencyStrategy` | Defines whether to route commands to the closest master or replica nodes (mutually exclusive with RandomStrategy and ReplicaStrategy). | false | No | +| `providers.redis.sentinel.randomStrategy` | Defines whether to route commands randomly to master or replica nodes (mutually exclusive with LatencyStrategy and ReplicaStrategy). | false | No | +| `providers.redis.sentinel.replicaStrategy` | Defines whether to route commands randomly to master or replica nodes (mutually exclusive with LatencyStrategy and ReplicaStrategy). | false | No | +| `providers.redis.sentinel.useDisconnectedReplicas` | Defines whether to use replicas disconnected with master when cannot get connected replicas. | false | false | + +## Routing Configuration + +See the dedicated section in [routing](../../../../routing/providers/kv.md). diff --git a/docs/content/reference/install-configuration/providers/kv/zk.md b/docs/content/reference/install-configuration/providers/kv/zk.md new file mode 100644 index 000000000..38042a1a9 --- /dev/null +++ b/docs/content/reference/install-configuration/providers/kv/zk.md @@ -0,0 +1,42 @@ +--- +title: "Traefik ZooKeeper Documentation" +description: "For configuration discovery in Traefik Proxy, you can store your configurations in ZooKeeper. Read the technical documentation." +--- + +# Traefik & ZooKeeper + +## Configuration Example + +You can enable the ZooKeeper provider as detailed below: + +```yaml tab="File (YAML)" +providers: + zooKeeper: {} +``` + +```toml tab="File (TOML)" +[providers.zooKeeper] +``` + +```bash tab="CLI" +--providers.zookeeper=true +``` + +## Configuration Options + +| Field | Description | Default | Required | +|:------|:----------------------------------------------------------|:---------------------|:---------| +| `providers.providersThrottleDuration` | Minimum amount of time to wait for, after a configuration reload, before taking into account any new configuration refresh event.
If multiple events occur within this time, only the most recent one is taken into account, and all others are discarded.
**This option cannot be set per provider, but the throttling algorithm applies to each of them independently.** | 2s | No | +| `providers.zooKeeper.endpoints` | Defines the endpoint to access ZooKeeper. | "127.0.0.1:2181" | Yes | +| `providers.zooKeeper.rootKey` | Defines the root key for the configuration. | "traefik" | Yes | +| `providers.zooKeeper.username` | Defines a username with which to connect to zooKeeper. | "" | No | +| `providers.zooKeeper.password` | Defines a password for connecting to zooKeeper. | "" | No | +| `providers.zooKeeper.tls` | Defines the TLS configuration used for the secure connection to zooKeeper. | - | No | +| `providers.zooKeeper.tls.ca` | Defines the path to the certificate authority used for the secure connection to zooKeeper, it defaults to the system bundle. | "" | No | +| `providers.zooKeeper.tls.cert` | Defines the path to the public certificate used for the secure connection to zooKeeper. When using this option, setting the `key` option is required. | "" | Yes | +| `providers.zooKeeper.tls.key` | Defines the path to the private key used for the secure connection to zooKeeper. When using this option, setting the `cert` option is required. | "" | Yes | +| `providers.zooKeeper.tls.insecureSkipVerify` | Instructs the provider to accept any certificate presented by etcd when establishing a TLS connection, regardless of the hostnames the certificate covers. | false | No | + +## Routing Configuration + +See the dedicated section in [routing](../../../../routing/providers/kv.md). diff --git a/docs/content/reference/install-configuration/providers/others/ecs.md b/docs/content/reference/install-configuration/providers/others/ecs.md new file mode 100644 index 000000000..f6aeb2731 --- /dev/null +++ b/docs/content/reference/install-configuration/providers/others/ecs.md @@ -0,0 +1,205 @@ +--- +title: "Traefik AWS ECS Documentation" +description: "Configuration discovery in Traefik is achieved through Providers. Read the technical documentation for leveraging AWS ECS in Traefik." +--- + +# Traefik & AWS ECS + +## Configuration Example + +You can enable the ECS provider with as detailed below: + +```yaml tab="File (YAML)" +providers: + ecs: {} +``` + +```toml tab="File (TOML)" +[providers.ecs] +``` + +```bash tab="CLI" +--providers.ecs=true +``` + +## Configuration Options + +| Field | Description | Default | Required | +|:------|:----------------------------------------------------------|:---------------------|:---------| +| `providers.providersThrottleDuration` | Minimum amount of time to wait for, after a configuration reload, before taking into account any new configuration refresh event.
If multiple events occur within this time, only the most recent one is taken into account, and all others are discarded.
**This option cannot be set per provider, but the throttling algorithm applies to each of them independently.** | 2s | No | +| `providers.ecs.autoDiscoverClusters` | Search for services in cluster list. If set to `true` service discovery is enabled for all clusters. | false | No | +| `providers.ecs.ecsAnywhere` | Enable ECS Anywhere support. | false | No | +| `providers.ecs.clusters` | Search for services in cluster list. This option is ignored if `autoDiscoverClusters` is set to `true`. | `["default"]` | No | +| `providers.ecs.exposedByDefault` | Expose ECS services by default in Traefik. | true | No | +| `providers.ecs.constraints` | Defines an expression that Traefik matches against the container labels to determine whether to create any route for that container. See [here](#constraints) for more information. | true | No | +| `providers.ecs.healthyTasksOnly` | Defines whether Traefik discovers only healthy tasks (`HEALTHY` healthStatus). | false | No | +| `providers.ecs.defaultRule` | The Default Host rule for all services. See [here](#defaultrule) for more information. | ```"Host(`{{ normalize .Name }}`)"``` | No | +| `providers.ecs.refreshSeconds` | Defines the polling interval (in seconds). | 15 | No | +| `providers.ecs.region` | Defines the region of the ECS instance. See [here](#credentials) for more information. | "" | No | +| `providers.ecs.accessKeyID` | Defines the Access Key ID for the ECS instance. See [here](#credentials) for more information. | "" | No | +| `providers.ecs.secretAccessKey` | Defines the Secret Access Key for the ECS instance. See [here](#credentials) for more information. | "" | No | + +### `constraints` + +The `constraints` option can be set to an expression that Traefik matches against the container labels (task), +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.+`)" + ``` + +```yaml tab="File (YAML)" +providers: + ecs: + constraints: "Label(`a.label.name`,`foo`)" + # ... +``` + +```toml tab="File (TOML)" +[providers.ecs] + constraints = "Label(`a.label.name`,`foo`)" + # ... +``` + +```bash tab="CLI" +--providers.ecs.constraints="Label(`a.label.name`,`foo`)" +# ... +``` + +For additional information, refer to [Restrict the Scope of Service Discovery](../overview.md#restrict-the-scope-of-service-discovery). + +### `defaultRule` + +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: + ecs: + defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" + # ... +``` + +```toml tab="File (TOML)" +[providers.ecs] + defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" + # ... +``` + +```bash tab="CLI" +--providers.ecs.defaultRule='Host(`{{ .Name }}.{{ index .Labels "customLabel"}}`)' +# ... +``` + +??? info "Default rule and Traefik service" + + The exposure of the Traefik container, combined with the default rule mechanism, + can lead to create a router targeting itself in a loop. + In this case, to prevent an infinite loop, + Traefik adds an internal middleware to refuse the request if it comes from the same router. + +### Credentials + +This defines the credentials for the ECS instance + +If `region` is not provided, it is resolved from the EC2 metadata endpoint for EC2 tasks. +In a FARGATE context it is resolved from the `AWS_REGION` environment variable. + +If `accessKeyID` and `secretAccessKey` are not provided, credentials are resolved in the following order: + +- Using the environment variables `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN`. +- Using shared credentials, determined by `AWS_PROFILE` and `AWS_SHARED_CREDENTIALS_FILE`, defaults to `default` and `~/.aws/credentials`. +- Using EC2 instance role or ECS task role + +```yaml tab="File (YAML)" +providers: + ecs: + region: us-east-1 + accessKeyID: "abc" + secretAccessKey: "123" + # ... +``` + +```toml tab="File (TOML)" +[providers.ecs] + region = "us-east-1" + accessKeyID = "abc" + secretAccessKey = "123" +``` + +```bash tab="CLI" +--providers.ecs.region="us-east-1" +--providers.ecs.accessKeyID="abc" +--providers.ecs.secretAccessKey="123" +# ... +``` + +## Policy + +Traefik needs the following policy to read ECS information: + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "TraefikECSReadAccess", + "Effect": "Allow", + "Action": [ + "ecs:ListClusters", + "ecs:DescribeClusters", + "ecs:ListTasks", + "ecs:DescribeTasks", + "ecs:DescribeContainerInstances", + "ecs:DescribeTaskDefinition", + "ec2:DescribeInstances", + "ssm:DescribeInstanceInformation" + ], + "Resource": [ + "*" + ] + } + ] +} +``` + +!!! info "ECS Anywhere" + + Please note that the `ssm:DescribeInstanceInformation` action is required for ECS anywhere instances discovery. diff --git a/docs/content/reference/install-configuration/providers/others/file.md b/docs/content/reference/install-configuration/providers/others/file.md new file mode 100644 index 000000000..6d4fad6d2 --- /dev/null +++ b/docs/content/reference/install-configuration/providers/others/file.md @@ -0,0 +1,124 @@ +--- +title: "Traefik File Documentation" +description: "The file provider in Traefik Proxy lets you define the dynamic configuration in a YAML or TOML file. Read the technical documentation." +--- + +# File + +The file provider lets you define the [install configuration](../overview.md) in a YAML or TOML file. + +It supports providing configuration through a single configuration file or multiple separate files. + +!!! info + + The file provider is the default format used throughout the documentation to show samples of the configuration for many features. + +!!! tip + + The file provider can be a good solution for reusing common elements from other providers (e.g. declaring allowlist middlewares, basic authentication, ...) + +## Configuration Example + +You can enable the file provider as detailed below: + +```yaml tab="File (YAML)" +providers: + file: + directory: "/path/to/dynamic/conf" +``` + +```toml tab="File (TOML)" +[providers.file] + directory = "/path/to/dynamic/conf" +``` + +```bash tab="CLI" +--providers.file.directory=/path/to/dynamic/conf +``` + +Declaring the Routers, Middlewares & Services: + +```yaml tab="YAML" +http: + # Add the router + routers: + router0: + entryPoints: + - web + middlewares: + - my-basic-auth + service: service-foo + rule: Path(`/foo`) + + # Add the middleware + middlewares: + my-basic-auth: + basicAuth: + users: + - test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/ + - test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0 + usersFile: etc/traefik/.htpasswd + + # Add the service + services: + service-foo: + loadBalancer: + servers: + - url: http://foo/ + - url: http://bar/ + passHostHeader: false +``` + +```toml tab="TOML" +[http] + # Add the router + [http.routers] + [http.routers.router0] + entryPoints = ["web"] + middlewares = ["my-basic-auth"] + service = "service-foo" + rule = "Path(`/foo`)" + + # Add the middleware + [http.middlewares] + [http.middlewares.my-basic-auth.basicAuth] + users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", + "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"] + usersFile = "etc/traefik/.htpasswd" + + # Add the service + [http.services] + [http.services.service-foo] + [http.services.service-foo.loadBalancer] + [[http.services.service-foo.loadBalancer.servers]] + url = "http://foo/" + [[http.services.service-foo.loadBalancer.servers]] + url = "http://bar/" +``` + +## Configuration Options + +| Field | Description | Default | Required | +|:------|:----------------------------------------------------------|:---------------------|:---------| +| `providers.providersThrottleDuration` | Minimum amount of time to wait for, after a configuration reload, before taking into account any new configuration refresh event.
If multiple events occur within this time, only the most recent one is taken into account, and all others are discarded.
**This option cannot be set per provider, but the throttling algorithm applies to each of them independently.** | 2s | No | +| `providers.file.filename` | Defines the path to the configuration file. | "" | Yes | +| `providers.file.directory` | Defines the path to the directory that contains the configuration files. The `filename` and `directory` options are mutually exclusive. It is recommended to use `directory`. | "" | Yes | +| `providers.file.watch` | Set the `watch` option to `true` to allow Traefik to automatically watch for file changes. It works with both the `filename` and the `directory` options. | true | No | + +!!! warning "Limitations" + + With the file provider, Traefik listens for file system notifications to update the dynamic configuration. + + If you use a mounted/bound file system in your orchestrator (like docker or kubernetes), the way the files are linked may be a source of errors. + If the link between the file systems is broken, when a source file/directory is changed/renamed, nothing will be reported to the linked file/directory, so the file system notifications will be neither triggered nor caught. + + For example, in Docker, if the host file is renamed, the link to the mounted file is broken and the container's file is no longer updated. + To avoid this kind of issue, it is recommended to: + + * set the Traefik [**directory**](#directory) configuration with the parent directory + * mount/bind the parent directory + + As it is very difficult to listen to all file system notifications, Traefik uses [fsnotify](https://github.com/fsnotify/fsnotify). + If using a directory with a mounted directory does not fix your issue, please check your file system compatibility with fsnotify. + +{!traefik-for-business-applications.md!} diff --git a/docs/content/reference/install-configuration/providers/others/http.md b/docs/content/reference/install-configuration/providers/others/http.md new file mode 100644 index 000000000..4ac29b6fe --- /dev/null +++ b/docs/content/reference/install-configuration/providers/others/http.md @@ -0,0 +1,66 @@ +--- +title: "Traefik HTTP Documentation" +description: "Provide your dynamic configuration via an HTTP(S) endpoint and let Traefik Proxy do the rest. Read the technical documentation." +--- + +# Traefik & HTTP + +Provide your [install configuration](../overview.md) via an HTTP(S) endpoint and let Traefik do the rest! + +## Configuration Example + +You can enable the HTTP provider as detailed below: + +```yaml tab="File (YAML)" +providers: + http: + endpoint: "http://127.0.0.1:9000/api" +``` + +```toml tab="File (TOML)" +[providers.http] + endpoint = "http://127.0.0.1:9000/api" +``` + +```bash tab="CLI" +--providers.http.endpoint=http://127.0.0.1:9000/api +``` + +## Configuration Options + +| Field | Description | Default | Required | +|:------|:----------------------------------------------------------|:---------------------|:---------| +| `providers.providersThrottleDuration` | Minimum amount of time to wait for, after a configuration reload, before taking into account any new configuration refresh event.
If multiple events occur within this time, only the most recent one is taken into account, and all others are discarded.
**This option cannot be set per provider, but the throttling algorithm applies to each of them independently.** | 2s | No | +| `providers.http.endpoint` | Defines the HTTP(S) endpoint to poll. | "" | Yes | +| `providers.http.pollInterval` | Defines the polling interval. | 5s | No | +| `providers.http.pollTimeout` | Defines the polling timeout when connecting to the endpoint. | 5s | No | +| `providers.http.headers` | Defines custom headers to be sent to the endpoint. | "" | No | +| `providers.http.tls.ca` | Defines the path to the certificate authority used for the secure connection to the endpoint, it defaults to the system bundle. | "" | No | +| `providers.http.tls.cert` | Defines the path to the public certificate used for the secure connection to the endpoint. When using this option, setting the `key` option is required. | "" | Yes | +| `providers.http.tls.key` | Defines the path to the private key used for the secure connection to the endpoint. When using this option, setting the `cert` option is required. | "" | Yes | +| `providers.http.tls.insecureSkipVerify` | Instructs the provider to accept any certificate presented by endpoint when establishing a TLS connection, regardless of the hostnames the certificate covers. | false | No | + +### headers + +Defines custom headers to be sent to the endpoint. + +```yaml tab="File (YAML)" +providers: + http: + headers: + name: value +``` + +```toml tab="File (TOML)" +[providers.http.headers] + name = "value" +``` + +```bash tab="CLI" +[providers.http.headers] +--providers.http.headers.name=value +``` + +## Routing Configuration + +The HTTP provider uses the same configuration as the [File Provider](./file.md) in YAML or JSON format. diff --git a/docs/content/reference/install-configuration/providers/overview.md b/docs/content/reference/install-configuration/providers/overview.md new file mode 100644 index 000000000..3edc93471 --- /dev/null +++ b/docs/content/reference/install-configuration/providers/overview.md @@ -0,0 +1,163 @@ +--- +title: "Traefik Providers Documentation" +description: "Learn about Providers in Traefik Proxy." +--- + +# Overview + +_Providers_ are infrastructure components, whether orchestrators, container engines, cloud providers, or key-value stores. +The idea is that Traefik queries the provider APIs in order to find relevant information about routing, +and when Traefik detects a change, it dynamically updates the routes. + +## Provider Categories + +While each provider is different, you can think of each as belonging to one of four categories: + +- Label-based: each deployed container has a set of labels attached to it +- Key-Value-based: each deployed container updates a key-value store with relevant information +- Annotation-based: a separate object, with annotations, defines the characteristics of the container +- File-based: uses files to define configuration + +## Provider Namespace + +When you declare certain objects in the Traefik dynamic configuration, +such as middleware, services, TLS options or server transports, they reside in their provider's namespace. +For example, if you declare a middleware using a Docker label, it resides in the Docker provider namespace. + +If you use multiple providers and wish to reference such an object declared in another provider +(e.g. referencing a cross-provider object like middleware), then the object name should be suffixed by the `@` +separator, and the provider name. + +For the list of the providers names, see the [supported providers](#supported-providers) table below. + +```text +@ +``` + +!!! important "Kubernetes Namespace vs Traefik Namespace" + + As Kubernetes also has its own notion of namespace, + one should not confuse the _provider namespace_ with the _Kubernetes Namespace_ of a resource when in the context of cross-provider usage. + + In this case, since the definition of a Traefik dynamic configuration object is not in Kubernetes, + specifying a Kubernetes Namespace when referring to the resource does not make any sense. + + On the other hand, if you were to declare a middleware as a Custom Resource in Kubernetes and use the non-CRD Ingress objects, + you would have to add the Kubernetes Namespace of the middleware to the annotation like this `-@kubernetescrd`. + +## Supported Providers + +Below is the list of the currently supported providers in Traefik. + +| Provider | Type | Configuration Type | Provider Name | +|--------------------------------------------------------------|--------------|----------------------|---------------------| +| [Docker](./docker.md) | Orchestrator | Label | `docker` | +| [Docker Swarm](./swarm.md) | Orchestrator | Label | `swarm` | +| [Kubernetes IngressRoute](./kubernetes/kubernetes-crd.md) | Orchestrator | Custom Resource | `kubernetescrd` | +| [Kubernetes Ingress](./kubernetes/kubernetes-ingress.md) | Orchestrator | Ingress | `kubernetes` | +| [Kubernetes Gateway API](./kubernetes/kubernetes-gateway.md) | Orchestrator | Gateway API Resource | `kubernetesgateway` | +| [Consul Catalog](./hashicorp/consul-catalog.md) | Orchestrator | Label | `consulcatalog` | +| [Nomad](./hashicorp/nomad.md) | Orchestrator | Label | `nomad` | +| [ECS](./others/ecs.md) | Orchestrator | Label | `ecs` | +| [File](./others/file.md) | Manual | YAML/TOML format | `file` | +| [Consul](./hashicorp/consul.md) | KV | KV | `consul` | +| [Etcd](./kv/etcd.md) | KV | KV | `etcd` | +| [ZooKeeper](./kv/zk.md) | KV | KV | `zookeeper` | +| [Redis](./kv/redis.md) | KV | KV | `redis` | +| [HTTP](./others/http.md) | Manual | JSON/YAML format | `http` | + +!!! info "More Providers" + + The current version of Traefik does not yet support every provider that Traefik v2.11 did. + See the [previous version (v2.11)](https://doc.traefik.io/traefik/v2.11/) for more information. + +## Referencing a Traefik Dynamic Configuration Object from Another Provider + +Declaring the add-foo-prefix in the file provider. + +```yaml tab="File (YAML)" +http: + middlewares: + add-foo-prefix: + addPrefix: + prefix: "/foo" +``` + +```toml tab="File (TOML)" +[http.middlewares] + [http.middlewares.add-foo-prefix.addPrefix] + prefix = "/foo" +``` + +Using the add-foo-prefix middleware from other providers: + +```yaml tab="Docker & Swarm" +your-container: + image: your-docker-image + + labels: + # Attach add-foo-prefix@file middleware (declared in file) + - "traefik.http.routers.my-container.middlewares=add-foo-prefix@file" +``` + +```yaml tab="IngressRoute" +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: ingressroutestripprefix + +spec: + entryPoints: + - web + routes: + - match: Host(`example.com`) + kind: Rule + services: + - name: whoami + port: 80 + middlewares: + - name: add-foo-prefix@file + # namespace: bar + # A namespace specification such as above is ignored + # when the cross-provider syntax is used. +``` + +```yaml tab="Ingress" +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress + namespace: appspace + annotations: + "traefik.ingress.kubernetes.io/router.middlewares": add-foo-prefix@file +spec: +``` + +By default, Traefik creates routes for all detected containers. + +If you want to limit the scope of the Traefik service discovery, +i.e. disallow route creation for some containers, +you can do so in two different ways: + +- the generic configuration option `exposedByDefault`, +- a finer granularity mechanism based on constraints. + +### `exposedByDefault` and `traefik.enable` + +List of providers that support these features: + +- [Docker](./docker.md#configuration-options) +- [ECS](./others/ecs.md#configuration-options) +- [Consul Catalog](./hashicorp/consul-catalog.md#configuration-options) +- [Nomad](./hashicorp/nomad.md#configuration-options) + +### Constraints + +List of providers that support constraints: + +- [Docker](./docker.md#constraints) +- [ECS](./others/ecs.md#constraints) +- [Consul Catalog](./hashicorp/consul-catalog.md#constraints) +- [Nomad](./hashicorp/nomad.md#constraints) + +{!traefik-for-business-applications.md!} diff --git a/docs/content/reference/install-configuration/providers/swarm.md b/docs/content/reference/install-configuration/providers/swarm.md new file mode 100644 index 000000000..becfdd577 --- /dev/null +++ b/docs/content/reference/install-configuration/providers/swarm.md @@ -0,0 +1,468 @@ +--- +title: "Traefik Docker Swarm Documentation" +description: "Learn how to achieve configuration discovery in Traefik through Docker Swarm. Read the technical documentation." +--- + +# Traefik & Docker Swarm + +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 Example + +You can enable the Swarm provider as detailed below: + +```yaml tab="File (YAML)" +providers: + swarm: {} +``` + +```toml tab="File (TOML)" +[providers.swarm] +``` + +```bash tab="CLI" +--providers.swarm=true +``` + +Attach labels to a single service (not containers) while in Swarm mode (in your Docker compose file). +When there is only one service, and the router does not specify a service, +then that service is automatically assigned to the router. + +```yaml tab="Labels" +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 +``` + +## Configuration Options + +| Field | Description | Default | Required | +|:------|:----------------------------------------------------------|:---------------------|:---------| +| `providers.providersThrottleDuration` | Minimum amount of time to wait for, after a configuration reload, before taking into account any new configuration refresh event.
If multiple events occur within this time, only the most recent one is taken into account, and all others are discarded.
**This option cannot be set per provider, but the throttling algorithm applies to each of them independently.** | 2s | No | +| `providers.swarm.endpoint` | Specifies the Docker API endpoint. See [here](#endpoint) for more information| `unix:///var/run/docker.sock` | Yes | +| `providers.swarm.username` | Defines the username for Basic HTTP authentication. This should be used when the Docker daemon socket is exposed through an HTTP proxy that requires Basic HTTP authentication.| "" | No | +| `providers.swarm.password` | Defines the password for Basic HTTP authentication. This should be used when the Docker daemon socket is exposed through an HTTP proxy that requires Basic HTTP authentication.| "" | No | +| `providers.swarm.useBindPortIP` | Instructs Traefik to use the IP/Port attached to the container's binding instead of its inner network IP/Port. See [here](#usebindportip) for more information | false | No | +| `providers.swarm.exposedByDefault` | Expose containers by default through Traefik. See [here](./overview.md#restrict-the-scope-of-service-discovery) for additional information | true | No | +| `providers.swarm.network` | 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.| "" | No | +| `providers.swarm.defaultRule` | Defines what routing rule to apply to a container if no rule is defined by a label. See [here](#defaultrule) for more information | ```"Host(`{{ normalize .Name }}`)"``` | No | +| `providers.swarm.refreshSeconds` | Defines the polling interval for Swarm Mode. | "15s" | No | +| `providers.swarm.httpClientTimeout` | Defines the client timeout (in seconds) for HTTP connections. If its value is 0, no timeout is set. | 0 | No | +| `providers.swarm.watch` | Instructs Traefik to watch Docker events or not. | True | No | +| `providers.swarm.constraints` | Defines an expression that Traefik matches against the container labels to determine whether to create any route for that container. See [here](#constraints) for more information. | "" | No | +| `providers.swarm.allowEmptyServices` | Instructs the provider to create any [servers load balancer](../../../routing/services/index.md#servers-load-balancer) defined for Docker containers regardless of the [healthiness](https://docs.docker.com/engine/reference/builder/#healthcheck) of the corresponding containers. | false | No | +| `providers.swarm.tls.ca` | Defines the path to the certificate authority used for the secure connection to Docker, it defaults to the system bundle. | "" | No | +| `providers.swarm.tls.cert` | Defines the path to the public certificate used for the secure connection to Docker. When using this option, setting the `key` option is required. | "" | Yes | +| `providers.swarm.tls.key` | Defines the path to the private key used for the secure connection to Docker. When using this option, setting the `cert` option is required. | "" | Yes | +| `providers.swarm.tls.insecureSkipVerify` | Instructs the provider to accept any certificate presented by the Docker server when establishing a TLS connection, regardless of the hostnames the certificate covers. | false | No | + +### `endpoint` + +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.1 # The official v3 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.docker.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 if the server requires public keys for authentication, you must have them accessible for the user running Traefik. + + ```yaml tab="File (YAML)" + providers: + swarm: + 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 + # ... + ``` + +??? example "Using HTTP" + + Using Docker Engine API you can connect Traefik to remote daemon using HTTP. + + ```yaml tab="File (YAML)" + providers: + swarm: + endpoint: "http://127.0.0.1:2375" + # ... + ``` + + ```toml tab="Static Configuration (TOML)" + [providers.swarm] + endpoint = "http://127.0.0.1:2375" + # ... + ``` + + ```bash tab="CLI" + --providers.swarm.endpoint=http://127.0.0.1:2375 + # ... + ``` + +??? example "Using TCP" + + Using Docker Engine API you can connect Traefik to remote daemon using TCP. + + ```yaml tab="File (YAML)" + providers: + swarm: + endpoint: "tcp://127.0.0.1:2375" + # ... + ``` + + ```toml tab="File (TOML)" + [providers.swarm] + endpoint = "tcp://127.0.0.1:2375" + # ... + ``` + + ```bash tab="CLI" + --providers.swarm.endpoint=tcp://127.0.0.1:2375 + # ... + ``` + +```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` + +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..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..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..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 +# ... +``` + +### `defaultRule` + +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 name can be accessed with the `ContainerName` identifier. +The service name can be accessed with the `Name` identifier. +The template has access to all the labels defined on this container with the `Labels` identifier. + +```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"}}`)' +# ... +``` + +??? info "Default rule and Traefik service" + + The exposure of the Traefik container, combined with the default rule mechanism, + can lead to create a router targeting itself in a loop. + In this case, to prevent an infinite loop, + Traefik adds an internal middleware to refuse the request if it comes from the same router. + +### `constraints` + +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`) +# ... +``` + +## 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..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: + + +- 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). + +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 +``` + +### 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). + +### 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. + +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 [...] + +#### 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) +- Authentication using HTTP Basic authentication through an HTTP proxy that exposes the Docker daemon socket. + +#### 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) + +{!traefik-for-business-applications.md!} diff --git a/docs/content/reference/install-configuration/tls/certificate-resolvers/acme.md b/docs/content/reference/install-configuration/tls/certificate-resolvers/acme.md new file mode 100644 index 000000000..4876feb76 --- /dev/null +++ b/docs/content/reference/install-configuration/tls/certificate-resolvers/acme.md @@ -0,0 +1,321 @@ +--- +title: "Traefik & ACME Certificates Resolver" +description: "Automatic Certificate Management Environment using Let's Encrypt." +--- + +## Configuration Example + +Below is an example of a basic configuration for ACME in Traefik. + +```yaml tab="File (YAML)" +entryPoints: + web: + address: ":80" + + websecure: + address: ":443" + +certificatesResolvers: + myresolver: + acme: + email: your-email@example.com + storage: acme.json + httpChallenge: + # used during the challenge + entryPoint: web +``` + +```toml tab="File (TOML)" +[entryPoints] + [entryPoints.web] + address = ":80" + + [entryPoints.websecure] + address = ":443" + +[certificatesResolvers.myresolver.acme] + email = "your-email@example.com" + storage = "acme.json" + [certificatesResolvers.myresolver.acme.httpChallenge] + # used during the challenge + entryPoint = "web" +``` + +```bash tab="CLI" +--entryPoints.web.address=:80 +--entryPoints.websecure.address=:443 +# ... +--certificatesresolvers.myresolver.acme.email=your-email@example.com +--certificatesresolvers.myresolver.acme.storage=acme.json +# used during the challenge +--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web +``` + +```yaml tab="Helm Chart Values" +# Traefik entryPoints configuration for HTTP and HTTPS. +entryPoints: + web: + address: ":80" + websecure: + address: ":443" + +certificatesResolvers: + myresolver: + acme: + email: "your-email@example.com" + storage: "/data/acme.json" # Path to store the certificate information. + httpChallenge: + # Entry point to use during the ACME HTTP-01 challenge. + entryPoint: "web" +``` + +## Configuration Options + +ACME certificate resolvers have the following configuration options: + +| Field | Description | Default | Required | +|:------------------|:--------------------|:-----------------------------------------------|:---------| +| `acme.email` | Email address used for registration. | "" | Yes | +| `acme.caServer` | CA server to use. | https://acme-v02.api.letsencrypt.org/directory | No | +| `acme.preferredChain` | Preferred chain to use. If the CA offers multiple certificate chains, prefer the chain with an issuer matching this Subject Common Name. If no match, the default offered chain will be used. | "" | No | +| `acme.keyType` | KeyType to use. | "RSA4096" | No | +| `acme.eab` | Enable external account binding.| "" | No | +| `acme.eab.kid` | Key identifier from External CA. | | No | +| `acme.eab.hmacEncoded` | HMAC key from External CA, should be in Base64 URL Encoding without padding format. | "" | No | +| `acme.certificatesDuration` | The certificates' duration in hours, exclusively used to determine renewal dates. | 2160 | No | +| `acme.dnsChallenge` | Enable DNS-01 challenge. More information [here](#dnschallenge). | - | No | +| `acme.dnsChallenge.provider` | DNS provider to use. | | No | +| `acme.dnsChallenge.delayBeforeCheck` | By default, the provider will verify the TXT DNS challenge record before letting ACME verify. If `delayBeforeCheck` is greater than zero, this check is delayed for the configured duration in seconds. Useful if internal networks block external DNS queries. | | No | +| `acme.dnsChallenge.resolvers` | DNS servers to resolve the FQDN authority. | | No | +| `acme.dnsChallenge.disablePropagationCheck` | Disable the DNS propagation checks before notifying ACME that the DNS challenge is ready. | | No | +| `acme.httpChallenge` | Enable HTTP-01 challenge. More information [here](#httpchallenge). | | No | +| `acme.httpChallenge.entryPoint` | EntryPoint to use for the HTTP-01 challenges. Must be reachable by Let's Encrypt through port 80 | "" | Yes | +| `acme.tlsChallenge` | Enable TLS-ALPN-01 challenge. Traefik must be reachable by Let's Encrypt through port 443. More information [here](#tlschallenge). | - | No | +| `acme.storage` | File path used for certificates storage. | "acme.json" | Yes | + +## Automatic Certificate Renewal + +Traefik automatically tracks the expiry date of certificates it generates. Certificates that are no longer used may still be renewed, as Traefik does not currently check if the certificate is being used before renewing. + +By default, Traefik manages 90-day certificates and starts renewing them 30 days before their expiry. +When using a certificate resolver that issues certificates with custom durations, the `certificatesDuration` option can be used to configure the certificates' duration. + +!!! note + Certificates that are no longer used may still be renewed, as Traefik does not currently check if the certificate is being used before renewing. + +## The Different ACME Challenges + +### dnsChallenge + +The DNS-01 challenge to generate and renew ACME certificates by provisioning a DNS record. + +Traefik relies internally on [Lego](https://go-acme.github.io/lego/ "Link to Lego website") for ACME. +You can find the list of all the supported DNS providers in their [documentation](https://go-acme.github.io/lego/dns/ "Link to Lego DNS challenge documentation page") +with instructions about which environment variables need to be setup. + +!!! note + + CNAME are supported and even [encouraged](https://letsencrypt.org/2019/10/09/onboarding-your-customers-with-lets-encrypt-and-acme.html#the-advantages-of-a-cname "Link to The Advantages of a CNAME article"). + + If needed, CNAME support can be turned off with the following environment variable: + + ```env + LEGO_DISABLE_CNAME_SUPPORT=true + ``` + +??? warning "Multiple DNS challenge" + + Multiple DNS challenge provider are not supported with Traefik, but you can use CNAME to handle that. + For example, if you have `example.org` (account foo) and `example.com` (account bar) you can create a CNAME on `example.org` called `_acme-challenge.example.org` pointing to `challenge.example.com`. + This way, you can obtain certificates for `example.com` with the foo account. + +??? info "`delayBeforeCheck`" + By default, the `provider` verifies the TXT record _before_ letting ACME verify. + You can delay this operation by specifying a delay (in seconds) with `delayBeforeCheck` (value must be greater than zero). + This option is useful when internal networks block external DNS queries. + +### `tlsChallenge` + +Use the `TLS-ALPN-01` challenge to generate and renew ACME certificates by provisioning a TLS certificate. + +As described on the Let's Encrypt [community forum](https://community.letsencrypt.org/t/support-for-ports-other-than-80-and-443/3419/72), +when using the `TLS-ALPN-01` challenge, Traefik must be reachable by Let's Encrypt through port 443. + +??? example "Configuring the `tlsChallenge`" + + ```yaml tab="File (YAML)" + certificatesResolvers: + myresolver: + acme: + # ... + tlsChallenge: {} + ``` + + ```toml tab="File (TOML)" + [certificatesResolvers.myresolver.acme] + # ... + [certificatesResolvers.myresolver.acme.tlsChallenge] + ``` + + ```bash tab="CLI" + # ... + --certificatesresolvers.myresolver.acme.tlschallenge=true + ``` + +### `httpChallenge` + +Use the `HTTP-01` challenge to generate and renew ACME certificates by provisioning an HTTP resource under a well-known URI. + +As described on the Let's Encrypt [community forum](https://community.letsencrypt.org/t/support-for-ports-other-than-80-and-443/3419/72), +when using the `HTTP-01` challenge, `certificatesresolvers.myresolver.acme.httpchallenge.entrypoint` must be reachable by Let's Encrypt through port 80. + +??? example "Using an EntryPoint Called web for the `httpChallenge`" + + ```yaml tab="File (YAML)" + entryPoints: + web: + address: ":80" + + websecure: + address: ":443" + + certificatesResolvers: + myresolver: + acme: + # ... + httpChallenge: + entryPoint: web + ``` + + ```toml tab="File (TOML)" + [entryPoints] + [entryPoints.web] + address = ":80" + + [entryPoints.websecure] + address = ":443" + + [certificatesResolvers.myresolver.acme] + # ... + [certificatesResolvers.myresolver.acme.httpChallenge] + entryPoint = "web" + ``` + + ```bash tab="CLI" + --entryPoints.web.address=:80 + --entryPoints.websecure.address=:443 + # ... + --certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web + ``` + +!!! info "" + Redirection is fully compatible with the `HTTP-01` challenge. + +## Domain Definition + +A certificate resolver requests certificates for a set of domain names inferred from routers, according to the following: + +- If the IngressRoute has a `tls.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 IngressRoute's rule. + +You can set SANs (alternative domains) for each main domain. +Every domain must have A/AAAA records pointing to Traefik. +Each domain & SAN will lead to a certificate request. + +[ACME v2](https://community.letsencrypt.org/t/acme-v2-and-wildcard-certificate-support-is-live/55579) supports wildcard certificates. +As described in [Let's Encrypt's post](https://community.letsencrypt.org/t/staging-endpoint-for-acme-v2/49605) wildcard certificates can only be generated through a `DNS-01` challenge. +It is not possible to request a double wildcard certificate for a domain (for example `*.*.local.com`). + +Most likely the root domain should receive a certificate too, so it needs to be specified as SAN and 2 `DNS-01` challenges are invoked. +In such a case the generated DNS TXT record for both domains is the same. +Even though this behavior is [DNS RFC](https://community.letsencrypt.org/t/wildcard-issuance-two-txt-records-for-the-same-name/54528/2) compliant, +it can lead to problems as all DNS providers keep DNS records cached for a given time (TTL) and this TTL can be greater than the challenge timeout making the `DNS-01` challenge fail. + +The Traefik ACME client library [lego](https://github.com/go-acme/lego) supports some but not all DNS providers to work around this issue. +The supported `provider` table indicates if they allow generating certificates for a wildcard domain and its root domain. + +### Wildcard Domains + +[ACME V2](https://community.letsencrypt.org/t/acme-v2-and-wildcard-certificate-support-is-live/55579) supports wildcard certificates. +As described in [Let's Encrypt's post](https://community.letsencrypt.org/t/staging-endpoint-for-acme-v2/49605) wildcard certificates can only be generated through a [`DNS-01` challenge](#dnschallenge). + +### External Account Binding + +- `kid`: Key identifier from External CA +- `hmacEncoded`: HMAC key from External CA, should be in Base64 URL Encoding without padding format + +```yaml tab="File (YAML)" +certificatesResolvers: + myresolver: + acme: + # ... + eab: + kid: abc-keyID-xyz + hmacEncoded: abc-hmac-xyz +``` + +```toml tab="File (TOML)" +[certificatesResolvers.myresolver.acme] + # ... + [certificatesResolvers.myresolver.acme.eab] + kid = "abc-keyID-xyz" + hmacEncoded = "abc-hmac-xyz" +``` + +```bash tab="CLI" +# ... +--certificatesresolvers.myresolver.acme.eab.kid=abc-keyID-xyz +--certificatesresolvers.myresolver.acme.eab.hmacencoded=abc-hmac-xyz +``` + +## Using LetsEncrypt with Kubernetes + +When using LetsEncrypt with kubernetes, there are some known caveats with both the [Ingress](../../providers/kubernetes/kubernetes-ingress.md) and [CRD](../../providers/kubernetes/kubernetes-crd.md) providers. + +!!! note + If you intend to run multiple instances of Traefik with LetsEncrypt, please ensure you read the sections on those provider pages. + +### LetsEncrypt Support with the Ingress Provider + +By design, Traefik is a stateless application, +meaning that it only derives its configuration from the environment it runs in, +without additional configuration. +For this reason, users can run multiple instances of Traefik at the same time to +achieve HA, as is a common pattern in the kubernetes ecosystem. + +When using a single instance of Traefik Proxy with Let's Encrypt, +you should encounter no issues. However, this could be a single point of failure. +Unfortunately, it is not possible to run multiple instances of Traefik 2.0 +with Let's Encrypt enabled, because there is no way to ensure that the correct +instance of Traefik receives the challenge request, and subsequent responses. +Early versions (v1.x) of Traefik used a +[KV store](https://doc.traefik.io/traefik/v1.7/configuration/acme/#storage) +to attempt to achieve this, but due to sub-optimal performance that feature +was dropped in 2.0. + +If you need Let's Encrypt with high availability in a Kubernetes environment, +we recommend using [Traefik Enterprise](https://traefik.io/traefik-enterprise/) +which includes distributed Let's Encrypt as a supported feature. + +If you want to keep using Traefik Proxy, +LetsEncrypt HA can be achieved by using a Certificate Controller such as [Cert-Manager](https://cert-manager.io/docs/). +When using Cert-Manager to manage certificates, +it creates secrets in your namespaces that can be referenced as TLS secrets in +your [ingress objects](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls) +. + +## Fallback + +If Let's Encrypt is not reachable, the following certificates will apply: + + 1. Previously generated ACME certificates (before downtime) + 2. Expired ACME certificates + 3. Provided certificates + +!!! important + For new (sub)domains which need Let's Encrypt authentication, the default Traefik certificate will be used until Traefik is restarted. + +{!traefik-for-business-applications.md!} diff --git a/docs/content/reference/install-configuration/tls/certificate-resolvers/overview.md b/docs/content/reference/install-configuration/tls/certificate-resolvers/overview.md new file mode 100644 index 000000000..5652f0982 --- /dev/null +++ b/docs/content/reference/install-configuration/tls/certificate-resolvers/overview.md @@ -0,0 +1,20 @@ +--- +title: "Certificates Resolver" +description: "Automatic Certificate Management using Let's Encrypt/Vault and Tailscale." +--- + + +In Traefik, TLS Certificates can be generated using Certificates Resolvers. + +In Traefik, two certificate resolvers exist: + +- [`acme`](./acme.md): It allows generating ACME certificates stored in a file (not distributed). +- [`tailscale`](./tailscale.md): It allows provisioning TLS certificates for internal Tailscale services. + +The Certificates resolvers are defined in the static configuration. + +!!! note 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 it. + +{!traefik-for-business-applications.md!} diff --git a/docs/content/reference/install-configuration/tls/certificate-resolvers/tailscale.md b/docs/content/reference/install-configuration/tls/certificate-resolvers/tailscale.md new file mode 100644 index 000000000..747805c1b --- /dev/null +++ b/docs/content/reference/install-configuration/tls/certificate-resolvers/tailscale.md @@ -0,0 +1,182 @@ +--- +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. + +## Configuration Example + +To obtain a TLS certificate from the Tailscale daemon, +a Tailscale certificate resolver needs to be configured as below. + +!!! 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" + 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)" + 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" + 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)" + 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)" + 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" + ``` + +!!! 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. + +## 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` 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. + +!!! info "Tailscale Domain Format" + + A domain is only considered if it is a Tailscale-specific one—that is, in the form `machine-name.domains-alias.ts.net`. + +## Tailscale Certificates Renewal + +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 the Tailscale daemon renewal policy. diff --git a/docs/content/reference/install-configuration/tls/spiffe.md b/docs/content/reference/install-configuration/tls/spiffe.md new file mode 100644 index 000000000..d7067c8f0 --- /dev/null +++ b/docs/content/reference/install-configuration/tls/spiffe.md @@ -0,0 +1,78 @@ +--- +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. + +!!! 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. + +## Workload API + +To enable SPIFFE globally, you need to set up the [static configuration](../../../getting-started/configuration-overview.md#the-static-configuration). The `workloadAPIAddr` option specifies the address of the SPIFFE [Workload API](https://spiffe.io/docs/latest/spiffe-about/spiffe-concepts/#spiffe-workload-api). + +```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 +``` + +## ServersTransport + +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)). + +### Configuration Example + +```yaml tab="File (YAML)" +serversTransport: + spiffe: + ids: + - spiffe://trust-domain/id1 + - spiffe://trust-domain/id2 + trustDomain: "spiffe://trust-domain" +``` + +```toml tab="File (TOML)" +[serversTransport.spiffe] +ids = [ "spiffe://trust-domain/id1", "spiffe://trust-domain/id2" ] +trustDomain = "spiffe://trust-domain" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.io/v1alpha1 +kind: ServersTransportTCP +metadata: + name: mytransport + namespace: default + +spec: + spiffe: + ids: + - spiffe://trust-domain/id1 + - spiffe://trust-domain/id2 +``` diff --git a/docs/content/routing/providers/kubernetes-gateway.md b/docs/content/routing/providers/kubernetes-gateway.md index c2da4447c..50ccfd565 100644 --- a/docs/content/routing/providers/kubernetes-gateway.md +++ b/docs/content/routing/providers/kubernetes-gateway.md @@ -750,4 +750,4 @@ spec: [...] ``` -{!traefik-for-business-applications.md!} \ No newline at end of file +{!traefik-for-business-applications.md!} diff --git a/docs/content/routing/providers/swarm.md b/docs/content/routing/providers/swarm.md index 39c46235f..ebe339b7a 100644 --- a/docs/content/routing/providers/swarm.md +++ b/docs/content/routing/providers/swarm.md @@ -680,10 +680,10 @@ You can tell Traefik to consider (or not) the container by setting `traefik.enab This option overrides the value of `exposedByDefault`. -#### `traefik.docker.network` +#### `traefik.swarm.network` ```yaml -- "traefik.docker.network=mynetwork" +- "traefik.swarm.network=mynetwork" ``` Overrides the default docker network to use for connections to the container. @@ -691,13 +691,10 @@ Overrides the default docker network to use for connections to the container. If a container is linked to several networks, be sure to set the proper network name (you can check this with `docker inspect `), otherwise it will randomly pick one (depending on how docker is returning them). -!!! warning - The Docker Swarm provider still uses the same per-container mechanism as the Docker provider, so therefore the label still uses the `docker` keyword intentionally. - !!! warning When deploying a stack from a compose file `stack`, the networks defined are prefixed with `stack`. -#### `traefik.docker.lbswarm` +#### `traefik.swarm.lbswarm` ```yaml - "traefik.docker.lbswarm=true" @@ -707,6 +704,3 @@ Enables Swarm's inbuilt load balancer (only relevant in Swarm Mode). If you enable this option, Traefik will use the virtual IP provided by docker swarm instead of the containers IPs. Which means that Traefik will not perform any kind of load balancing and will delegate this task to swarm. - -!!! warning - The Docker Swarm provider still uses the same per-container mechanism as the Docker provider, so therefore the label still uses the `docker` keyword intentionally. diff --git a/docs/docs.Dockerfile b/docs/docs.Dockerfile index 2ed4d0528..e15440a36 100644 --- a/docs/docs.Dockerfile +++ b/docs/docs.Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.20 +FROM alpine:3.21 ENV PATH="${PATH}:/venv/bin" diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 2d05e8f05..6fd2b21e5 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -52,6 +52,7 @@ markdown_extensions: use_pygments: false # hljs is used instead of pygment for TOML highlighting support - pymdownx.smartsymbols - pymdownx.superfences + - pymdownx.tabbed - pymdownx.tasklist - pymdownx.snippets: check_paths: true @@ -190,13 +191,45 @@ nav: - 'Data Collection': 'contributing/data-collection.md' - 'Advocating': 'contributing/advocating.md' - 'Maintainers': 'contributing/maintainers.md' - - 'References': - - 'Static Configuration': - - 'Overview': 'reference/static-configuration/overview.md' - - 'File': 'reference/static-configuration/file.md' - - 'CLI': 'reference/static-configuration/cli.md' - - 'Environment variables': 'reference/static-configuration/env.md' - - 'Dynamic Configuration': + - 'Reference': + - 'Install Configuration': + - 'Boot Environment': 'reference/install-configuration/boot-environment.md' + - 'Configuration Discovery': + - 'Overview' : 'reference/install-configuration/providers/overview.md' + - 'Kubernetes': + - 'Kubernetes Gateway API' : 'reference/install-configuration/providers/kubernetes/kubernetes-gateway.md' + - 'Kubernetes CRD' : 'reference/install-configuration/providers/kubernetes/kubernetes-crd.md' + - 'Kubernetes Ingress' : 'reference/install-configuration/providers/kubernetes/kubernetes-ingress.md' + - 'Docker': 'reference/install-configuration/providers/docker.md' + - 'Swarm': 'reference/install-configuration/providers/swarm.md' + - 'Hashicorp': + - 'Nomad': "reference/install-configuration/providers/hashicorp/nomad.md" + - 'Consul': 'reference/install-configuration/providers/hashicorp/consul.md' + - 'Consul Catalog': 'reference/install-configuration/providers/hashicorp/consul-catalog.md' + - 'KV Stores': + - 'Redis': 'reference/install-configuration/providers/kv/redis.md' + - 'Consul': 'reference/install-configuration/providers/kv/consul.md' + - 'etcd': 'reference/install-configuration/providers/kv/etcd.md' + - 'ZooKeeper' : 'reference/install-configuration/providers/kv/zk.md' + - 'Others': + - 'File': 'reference/install-configuration/providers/others/file.md' + - 'ECS': 'reference/install-configuration/providers/others/ecs.md' + - 'HTTP': 'reference/install-configuration/providers/others/http.md' + - 'EntryPoints': 'reference/install-configuration/entrypoints.md' + - 'API & Dashboard': 'reference/install-configuration/api-dashboard.md' + - 'TLS': + - 'Certificate Resolvers': + - "Overview" : 'reference/install-configuration/tls/certificate-resolvers/overview.md' + - "ACME" : 'reference/install-configuration/tls/certificate-resolvers/acme.md' + - "Tailscale" : 'reference/install-configuration/tls/certificate-resolvers/tailscale.md' + - "SPIFFE" : 'reference/install-configuration/tls/spiffe.md' + - 'Observability': + - 'Metrics' : 'reference/install-configuration/observability/metrics.md' + - 'Tracing': 'reference/install-configuration/observability/tracing.md' + - 'Logs & AccessLogs': 'reference/install-configuration/observability/logs-and-accesslogs.md' + - 'Health Check (CLI & Ping)': 'reference/install-configuration/observability/healthcheck.md' + # - 'Options List': 'reference/install-configuration/cli-options-list.md' -- Todo + - 'Dynamic Configuration': - 'File': 'reference/dynamic-configuration/file.md' - 'Docker': 'reference/dynamic-configuration/docker.md' - 'Swarm': 'reference/dynamic-configuration/swarm.md' diff --git a/go.mod b/go.mod index aef9401b1..7ea47f85e 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/docker/go-connections v0.5.0 github.com/fatih/structs v1.1.0 github.com/fsnotify/fsnotify v1.7.0 - github.com/go-acme/lego/v4 v4.20.2 + github.com/go-acme/lego/v4 v4.20.4 github.com/go-kit/kit v0.13.0 github.com/go-kit/log v0.2.1 github.com/golang/protobuf v1.5.4 @@ -50,7 +50,7 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // No tag on the repo. github.com/prometheus/client_golang v1.19.1 github.com/prometheus/client_model v0.6.1 - github.com/quic-go/quic-go v0.47.0 + github.com/quic-go/quic-go v0.48.2 github.com/rs/zerolog v1.33.0 github.com/sirupsen/logrus v1.9.3 github.com/spiffe/go-spiffe/v2 v2.1.1 @@ -91,9 +91,9 @@ require ( golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // No tag on the repo. golang.org/x/mod v0.21.0 golang.org/x/net v0.30.0 - golang.org/x/sync v0.9.0 - golang.org/x/sys v0.27.0 - golang.org/x/text v0.20.0 + golang.org/x/sync v0.10.0 + golang.org/x/sys v0.28.0 + golang.org/x/text v0.21.0 golang.org/x/time v0.7.0 golang.org/x/tools v0.25.0 google.golang.org/grpc v1.67.1 @@ -106,7 +106,7 @@ require ( k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // No tag on the repo. mvdan.cc/xurls/v2 v2.5.0 sigs.k8s.io/controller-runtime v0.18.0 - sigs.k8s.io/gateway-api v1.2.0 + sigs.k8s.io/gateway-api v1.2.1 sigs.k8s.io/yaml v1.4.0 ) @@ -364,9 +364,9 @@ require ( go.uber.org/ratelimit v0.3.0 // indirect go.uber.org/zap v1.26.0 // indirect golang.org/x/arch v0.4.0 // indirect - golang.org/x/crypto v0.28.0 // indirect + golang.org/x/crypto v0.31.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect - golang.org/x/term v0.25.0 // indirect + golang.org/x/term v0.27.0 // indirect google.golang.org/api v0.204.0 // indirect google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect diff --git a/go.sum b/go.sum index b9b987803..185f3341f 100644 --- a/go.sum +++ b/go.sum @@ -364,8 +364,8 @@ github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwv github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= -github.com/go-acme/lego/v4 v4.20.2 h1:ZwO3oLZb8fL6up1OZVJP3yHuvqhozzlEmyqKmhrPchQ= -github.com/go-acme/lego/v4 v4.20.2/go.mod h1:foauPlhnhoq8WUphaWx5U04uDc+JGhk4ZZtPz/Vqsjg= +github.com/go-acme/lego/v4 v4.20.4 h1:yCQGBX9jOfMbriEQUocdYm7EBapdTp8nLXYG8k6SqSU= +github.com/go-acme/lego/v4 v4.20.4/go.mod h1:foauPlhnhoq8WUphaWx5U04uDc+JGhk4ZZtPz/Vqsjg= github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= @@ -1033,8 +1033,8 @@ github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoG github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= -github.com/quic-go/quic-go v0.47.0 h1:yXs3v7r2bm1wmPTYNLKAAJTHMYkPEsfYJmTazXrCZ7Y= -github.com/quic-go/quic-go v0.47.0/go.mod h1:3bCapYsJvXGZcipOHuu7plYtaV6tnF+z7wIFsU0WK9E= +github.com/quic-go/quic-go v0.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE= +github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4= @@ -1391,8 +1391,8 @@ golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIi golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= -golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1518,8 +1518,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1611,8 +1611,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1624,8 +1624,8 @@ golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= -golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1642,8 +1642,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1906,8 +1906,8 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/controller-runtime v0.18.0 h1:Z7jKuX784TQSUL1TIyeuF7j8KXZ4RtSX0YgtjKcSTME= sigs.k8s.io/controller-runtime v0.18.0/go.mod h1:tuAt1+wbVsXIT8lPtk5RURxqAnq7xkpv2Mhttslg7Hw= -sigs.k8s.io/gateway-api v1.2.0 h1:LrToiFwtqKTKZcZtoQPTuo3FxhrrhTgzQG0Te+YGSo8= -sigs.k8s.io/gateway-api v1.2.0/go.mod h1:EpNfEXNjiYfUJypf0eZ0P5iXA9ekSGWaS1WgPaM42X0= +sigs.k8s.io/gateway-api v1.2.1 h1:fZZ/+RyRb+Y5tGkwxFKuYuSRQHu9dZtbjenblleOLHM= +sigs.k8s.io/gateway-api v1.2.1/go.mod h1:EpNfEXNjiYfUJypf0eZ0P5iXA9ekSGWaS1WgPaM42X0= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= diff --git a/integration/conformance-reports/v1.2.0/experimental-v3.2-default-report.yaml b/integration/conformance-reports/v1.2.1/experimental-v3.2-default-report.yaml similarity index 98% rename from integration/conformance-reports/v1.2.0/experimental-v3.2-default-report.yaml rename to integration/conformance-reports/v1.2.1/experimental-v3.2-default-report.yaml index 78dabdc37..69b40a3de 100644 --- a/integration/conformance-reports/v1.2.0/experimental-v3.2-default-report.yaml +++ b/integration/conformance-reports/v1.2.1/experimental-v3.2-default-report.yaml @@ -1,7 +1,7 @@ apiVersion: gateway.networking.k8s.io/v1 date: '-' gatewayAPIChannel: experimental -gatewayAPIVersion: v1.2.0 +gatewayAPIVersion: v1.2.1 implementation: contact: - '@traefik/maintainers' diff --git a/integration/fixtures/k8s-conformance/00-experimental-v1.2.0.yml b/integration/fixtures/k8s-conformance/00-experimental-v1.2.1.yml similarity index 99% rename from integration/fixtures/k8s-conformance/00-experimental-v1.2.0.yml rename to integration/fixtures/k8s-conformance/00-experimental-v1.2.1.yml index b1c48b5da..69b689846 100644 --- a/integration/fixtures/k8s-conformance/00-experimental-v1.2.0.yml +++ b/integration/fixtures/k8s-conformance/00-experimental-v1.2.1.yml @@ -24,7 +24,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.2.0 + gateway.networking.k8s.io/bundle-version: v1.2.1 gateway.networking.k8s.io/channel: experimental creationTimestamp: null labels: @@ -525,7 +525,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.2.0 + gateway.networking.k8s.io/bundle-version: v1.2.1 gateway.networking.k8s.io/channel: experimental creationTimestamp: null labels: @@ -1154,7 +1154,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.2.0 + gateway.networking.k8s.io/bundle-version: v1.2.1 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: gatewayclasses.gateway.networking.k8s.io @@ -1674,7 +1674,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.2.0 + gateway.networking.k8s.io/bundle-version: v1.2.1 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: gateways.gateway.networking.k8s.io @@ -4090,7 +4090,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.2.0 + gateway.networking.k8s.io/bundle-version: v1.2.1 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: grpcroutes.gateway.networking.k8s.io @@ -6328,7 +6328,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.2.0 + gateway.networking.k8s.io/bundle-version: v1.2.1 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: httproutes.gateway.networking.k8s.io @@ -12490,7 +12490,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.2.0 + gateway.networking.k8s.io/bundle-version: v1.2.1 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: referencegrants.gateway.networking.k8s.io @@ -12683,7 +12683,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.2.0 + gateway.networking.k8s.io/bundle-version: v1.2.1 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: tcproutes.gateway.networking.k8s.io @@ -13428,7 +13428,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.2.0 + gateway.networking.k8s.io/bundle-version: v1.2.1 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: tlsroutes.gateway.networking.k8s.io @@ -14236,7 +14236,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.2.0 + gateway.networking.k8s.io/bundle-version: v1.2.1 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: udproutes.gateway.networking.k8s.io diff --git a/integration/k8s_conformance_test.go b/integration/k8s_conformance_test.go index c0e524ea3..959443be6 100644 --- a/integration/k8s_conformance_test.go +++ b/integration/k8s_conformance_test.go @@ -90,7 +90,7 @@ func (s *K8sConformanceSuite) SetupSuite() { s.k3sContainer, err = k3s.Run(ctx, k3sImage, - k3s.WithManifest("./fixtures/k8s-conformance/00-experimental-v1.2.0.yml"), + k3s.WithManifest("./fixtures/k8s-conformance/00-experimental-v1.2.1.yml"), k3s.WithManifest("./fixtures/k8s-conformance/01-rbac.yml"), k3s.WithManifest("./fixtures/k8s-conformance/02-traefik.yml"), network.WithNetwork(nil, s.network), diff --git a/internal/release/release.go b/internal/release/release.go index d27eed270..d011982ac 100644 --- a/internal/release/release.go +++ b/internal/release/release.go @@ -25,14 +25,22 @@ func main() { ParseFiles("./.goreleaser.yml.tmpl"), ) - outputPath := path.Join(os.TempDir(), fmt.Sprintf(".goreleaser_%s.yml", goos)) + goarch := "" + outputFileName := fmt.Sprintf(".goreleaser_%s.yml", goos) + if strings.Contains(goos, "-") { + split := strings.Split(goos, "-") + goos = split[0] + goarch = split[1] + } + + outputPath := path.Join(os.TempDir(), outputFileName) output, err := os.Create(outputPath) if err != nil { log.Fatal(err) } - err = tmpl.Execute(output, map[string]string{"GOOS": goos}) + err = tmpl.Execute(output, map[string]string{"GOOS": goos, "GOARCH": goarch}) if err != nil { log.Fatal(err) } diff --git a/pkg/plugins/fixtures/withoutsocket/demo.go b/pkg/plugins/fixtures/withoutsocket/demo.go new file mode 100644 index 000000000..92b1a6ddb --- /dev/null +++ b/pkg/plugins/fixtures/withoutsocket/demo.go @@ -0,0 +1,52 @@ +package main + +import ( + "encoding/json" + "fmt" + "net/http" + "os" + + "github.com/http-wasm/http-wasm-guest-tinygo/handler" + "github.com/http-wasm/http-wasm-guest-tinygo/handler/api" +) + +type config struct { + File string `json:"file"` + Envs []string `json:"envs"` +} + +var cfg config + +// Built with +// tinygo build -o plugin.wasm -scheduler=none --no-debug -target=wasi ./demo.go +func main() { + err := json.Unmarshal(handler.Host.GetConfig(), &cfg) + if err != nil { + handler.Host.Log(api.LogLevelError, fmt.Sprintf("Could not load config %v", err)) + os.Exit(1) + } + + handler.HandleRequestFn = handleRequest +} + +func handleRequest(req api.Request, resp api.Response) (next bool, reqCtx uint32) { + var bodyContent []byte + if cfg.File != "" { + var err error + bodyContent, err = os.ReadFile(cfg.File) + if err != nil { + resp.SetStatusCode(http.StatusInternalServerError) + resp.Body().Write([]byte(fmt.Sprintf("error reading file %q: %w", cfg.File, err.Error()))) + return false, 0 + } + } + + if len(cfg.Envs) > 0 { + for _, env := range cfg.Envs { + bodyContent = append(bodyContent, []byte(os.Getenv(env)+"\n")...) + } + } + + resp.Body().Write(bodyContent) + return false, 0 +} diff --git a/pkg/plugins/fixtures/withoutsocket/go.mod b/pkg/plugins/fixtures/withoutsocket/go.mod new file mode 100644 index 000000000..f684c5a2c --- /dev/null +++ b/pkg/plugins/fixtures/withoutsocket/go.mod @@ -0,0 +1,5 @@ +module withoutsocket + +go 1.23.0 + +require github.com/http-wasm/http-wasm-guest-tinygo v0.4.0 diff --git a/pkg/plugins/fixtures/withoutsocket/go.sum b/pkg/plugins/fixtures/withoutsocket/go.sum new file mode 100644 index 000000000..fab3d3577 --- /dev/null +++ b/pkg/plugins/fixtures/withoutsocket/go.sum @@ -0,0 +1,2 @@ +github.com/http-wasm/http-wasm-guest-tinygo v0.4.0 h1:sWd1hqOL8LF3DVRPXloVELTQItibKtDCtVSA4UfMf4Y= +github.com/http-wasm/http-wasm-guest-tinygo v0.4.0/go.mod h1:zcKr7h/t5ha2ZWIMwV4iOqhfC/qno/tNPYgybVkn/MQ= diff --git a/pkg/plugins/fixtures/withoutsocket/plugin.wasm b/pkg/plugins/fixtures/withoutsocket/plugin.wasm new file mode 100644 index 000000000..23df7b8da Binary files /dev/null and b/pkg/plugins/fixtures/withoutsocket/plugin.wasm differ diff --git a/pkg/plugins/middlewarewasm.go b/pkg/plugins/middlewarewasm.go index 8b182a1dc..c33858a9d 100644 --- a/pkg/plugins/middlewarewasm.go +++ b/pkg/plugins/middlewarewasm.go @@ -83,7 +83,7 @@ func (b *wasmMiddlewareBuilder) buildMiddleware(ctx context.Context, next http.H config := wazero.NewModuleConfig().WithSysWalltime().WithStartFunctions("_start", "_initialize") for _, env := range b.settings.Envs { - config.WithEnv(env, os.Getenv(env)) + config = config.WithEnv(env, os.Getenv(env)) } if len(b.settings.Mounts) > 0 { @@ -97,14 +97,14 @@ func (b *wasmMiddlewareBuilder) buildMiddleware(ctx context.Context, next http.H parts := strings.Split(prefix, ":") switch { case len(parts) == 1: - withDir(parts[0], parts[0]) + fsConfig = withDir(parts[0], parts[0]) case len(parts) == 2: - withDir(parts[0], parts[1]) + fsConfig = withDir(parts[0], parts[1]) default: return nil, nil, fmt.Errorf("invalid directory %q", mount) } } - config.WithFSConfig(fsConfig) + config = config.WithFSConfig(fsConfig) } opts := []handler.Option{ diff --git a/pkg/plugins/middlewarewasm_test.go b/pkg/plugins/middlewarewasm_test.go new file mode 100644 index 000000000..38fee4bbe --- /dev/null +++ b/pkg/plugins/middlewarewasm_test.go @@ -0,0 +1,120 @@ +package plugins + +import ( + "context" + "net/http" + "net/http/httptest" + "os" + "path" + "reflect" + "testing" + + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/tetratelabs/wazero" +) + +func TestSettingsWithoutSocket(t *testing.T) { + cache := wazero.NewCompilationCache() + + zerolog.SetGlobalLevel(zerolog.DebugLevel) + + ctx := log.Logger.WithContext(context.Background()) + + t.Setenv("PLUGIN_TEST", "MY-TEST") + t.Setenv("PLUGIN_TEST_B", "MY-TEST_B") + + testCases := []struct { + desc string + getSettings func(t *testing.T) (Settings, map[string]interface{}) + expected string + }{ + { + desc: "mounts path", + getSettings: func(t *testing.T) (Settings, map[string]interface{}) { + t.Helper() + + tempDir := t.TempDir() + filePath := path.Join(tempDir, "hello.txt") + err := os.WriteFile(filePath, []byte("content_test"), 0o644) + require.NoError(t, err) + + return Settings{Mounts: []string{ + tempDir, + }}, map[string]interface{}{ + "file": filePath, + } + }, + expected: "content_test", + }, + { + desc: "mounts src to dest", + getSettings: func(t *testing.T) (Settings, map[string]interface{}) { + t.Helper() + + tempDir := t.TempDir() + filePath := path.Join(tempDir, "hello.txt") + err := os.WriteFile(filePath, []byte("content_test"), 0o644) + require.NoError(t, err) + + return Settings{Mounts: []string{ + tempDir + ":/tmp", + }}, map[string]interface{}{ + "file": "/tmp/hello.txt", + } + }, + expected: "content_test", + }, + { + desc: "one env", + getSettings: func(t *testing.T) (Settings, map[string]interface{}) { + t.Helper() + + envs := []string{"PLUGIN_TEST"} + return Settings{Envs: envs}, map[string]interface{}{ + "envs": envs, + } + }, + expected: "MY-TEST\n", + }, + { + desc: "two env", + getSettings: func(t *testing.T) (Settings, map[string]interface{}) { + t.Helper() + + envs := []string{"PLUGIN_TEST", "PLUGIN_TEST_B"} + return Settings{Envs: envs}, map[string]interface{}{ + "envs": envs, + } + }, + expected: "MY-TEST\nMY-TEST_B\n", + }, + } + + for _, test := range testCases { + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + settings, config := test.getSettings(t) + + builder := &wasmMiddlewareBuilder{path: "./fixtures/withoutsocket/plugin.wasm", cache: cache, settings: settings} + + cfg := reflect.ValueOf(config) + + m, applyCtx, err := builder.buildMiddleware(ctx, http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.WriteHeader(http.StatusTeapot) + }), cfg, "test") + require.NoError(t, err) + + rw := httptest.NewRecorder() + req := httptest.NewRequestWithContext(applyCtx(ctx), "GET", "/", http.NoBody) + + m.ServeHTTP(rw, req) + + assert.Equal(t, http.StatusOK, rw.Code) + assert.Equal(t, test.expected, rw.Body.String()) + }) + } +} diff --git a/pkg/provider/docker/config.go b/pkg/provider/docker/config.go index d69fbbe81..4d819862a 100644 --- a/pkg/provider/docker/config.go +++ b/pkg/provider/docker/config.go @@ -21,10 +21,11 @@ import ( type DynConfBuilder struct { Shared apiClient client.APIClient + swarm bool } -func NewDynConfBuilder(configuration Shared, apiClient client.APIClient) *DynConfBuilder { - return &DynConfBuilder{Shared: configuration, apiClient: apiClient} +func NewDynConfBuilder(configuration Shared, apiClient client.APIClient, swarm bool) *DynConfBuilder { + return &DynConfBuilder{Shared: configuration, apiClient: apiClient, swarm: swarm} } func (p *DynConfBuilder) build(ctx context.Context, containersInspected []dockerData) *dynamic.Configuration { @@ -321,16 +322,16 @@ func (p *DynConfBuilder) getIPAddress(ctx context.Context, container dockerData) logger := log.Ctx(ctx) netNotFound := false - if container.ExtraConf.Docker.Network != "" { + if container.ExtraConf.Network != "" { settings := container.NetworkSettings if settings.Networks != nil { - network := settings.Networks[container.ExtraConf.Docker.Network] + network := settings.Networks[container.ExtraConf.Network] if network != nil { return network.Addr } netNotFound = true - logger.Warn().Msgf("Could not find network named %q for container %q. Maybe you're missing the project's prefix in the label?", container.ExtraConf.Docker.Network, container.Name) + logger.Warn().Msgf("Could not find network named %q for container %q. Maybe you're missing the project's prefix in the label?", container.ExtraConf.Network, container.Name) } } @@ -360,12 +361,12 @@ func (p *DynConfBuilder) getIPAddress(ctx context.Context, container dockerData) containerParsed := parseContainer(containerInspected) extraConf, err := p.extractLabels(containerParsed) if err != nil { - logger.Warn().Err(err).Msgf("Unable to get IP address for container %s : failed to get extra configuration for container %s", container.Name, containerInspected.Name) + logger.Warn().Err(err).Msgf("Unable to get IP address for container %s: failed to get extra configuration for container %s", container.Name, containerInspected.Name) return "" } - if extraConf.Docker.Network == "" { - extraConf.Docker.Network = container.ExtraConf.Docker.Network + if extraConf.Network == "" { + extraConf.Network = container.ExtraConf.Network } containerParsed.ExtraConf = extraConf @@ -396,3 +397,10 @@ func (p *DynConfBuilder) getPortBinding(container dockerData, serverPort string) return nil, fmt.Errorf("unable to find the external IP:Port for the container %q", container.Name) } + +func (p *DynConfBuilder) extractLabels(container dockerData) (configuration, error) { + if p.swarm { + return p.Shared.extractSwarmLabels(container) + } + return p.Shared.extractDockerLabels(container) +} diff --git a/pkg/provider/docker/config_test.go b/pkg/provider/docker/config_test.go index adddd6468..2a6f8ed32 100644 --- a/pkg/provider/docker/config_test.go +++ b/pkg/provider/docker/config_test.go @@ -405,18 +405,16 @@ func TestDynConfBuilder_DefaultRule(t *testing.T) { DefaultRule: test.defaultRule, }, } + require.NoError(t, p.Init()) - err := p.Init() - require.NoError(t, err) + builder := NewDynConfBuilder(p.Shared, nil, false) for i := range len(test.containers) { var err error - test.containers[i].ExtraConf, err = p.extractLabels(test.containers[i]) + test.containers[i].ExtraConf, err = builder.extractLabels(test.containers[i]) require.NoError(t, err) } - builder := NewDynConfBuilder(p.Shared, nil) - configuration := builder.build(context.Background(), test.containers) assert.Equal(t, test.expected, configuration) @@ -3662,17 +3660,16 @@ func TestDynConfBuilder_build(t *testing.T) { } p.Constraints = test.constraints - err := p.Init() - require.NoError(t, err) + require.NoError(t, p.Init()) + + builder := NewDynConfBuilder(p.Shared, nil, false) for i := range len(test.containers) { var err error - test.containers[i].ExtraConf, err = p.extractLabels(test.containers[i]) + test.containers[i].ExtraConf, err = builder.extractLabels(test.containers[i]) require.NoError(t, err) } - builder := NewDynConfBuilder(p.Shared, nil) - configuration := builder.build(context.Background(), test.containers) assert.Equal(t, test.expected, configuration) @@ -3843,7 +3840,7 @@ func TestDynConfBuilder_getIPPort_docker(t *testing.T) { builder := NewDynConfBuilder(Shared{ Network: "testnet", UseBindPortIP: true, - }, nil) + }, nil, false) actualIP, actualPort, actualError := builder.getIPPort(context.Background(), dData, test.serverPort) if test.expected.error { @@ -3956,12 +3953,12 @@ func TestDynConfBuilder_getIPAddress_docker(t *testing.T) { dData := parseContainer(test.container) - dData.ExtraConf.Docker.Network = conf.Network + dData.ExtraConf.Network = conf.Network if len(test.network) > 0 { - dData.ExtraConf.Docker.Network = test.network + dData.ExtraConf.Network = test.network } - builder := NewDynConfBuilder(conf, nil) + builder := NewDynConfBuilder(conf, nil, false) actual := builder.getIPAddress(context.Background(), dData) assert.Equal(t, test.expected, actual) @@ -3995,7 +3992,7 @@ func TestDynConfBuilder_getIPAddress_swarm(t *testing.T) { { service: swarmService( serviceLabels(map[string]string{ - "traefik.docker.network": "barnet", + "traefik.swarm.network": "barnet", }), withEndpointSpec(modeVIP), withEndpoint( @@ -4019,12 +4016,13 @@ func TestDynConfBuilder_getIPAddress_swarm(t *testing.T) { t.Run(strconv.Itoa(serviceID), func(t *testing.T) { t.Parallel() - p := &SwarmProvider{} + var p SwarmProvider + require.NoError(t, p.Init()) dData, err := p.parseService(context.Background(), test.service, test.networks) require.NoError(t, err) - builder := NewDynConfBuilder(p.Shared, nil) + builder := NewDynConfBuilder(p.Shared, nil, false) actual := builder.getIPAddress(context.Background(), dData) assert.Equal(t, test.expected, actual) }) diff --git a/pkg/provider/docker/pdocker.go b/pkg/provider/docker/pdocker.go index 9b7506711..44ff3470d 100644 --- a/pkg/provider/docker/pdocker.go +++ b/pkg/provider/docker/pdocker.go @@ -79,7 +79,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } defer func() { _ = dockerClient.Close() }() - builder := NewDynConfBuilder(p.Shared, dockerClient) + builder := NewDynConfBuilder(p.Shared, dockerClient, false) serverVersion, err := dockerClient.ServerVersion(ctx) if err != nil { @@ -179,7 +179,7 @@ func (p *Provider) listContainers(ctx context.Context, dockerClient client.Conta continue } - extraConf, err := p.extractLabels(dData) + extraConf, err := p.extractDockerLabels(dData) if err != nil { log.Ctx(ctx).Error().Err(err).Msgf("Skip container %s", getServiceName(dData)) continue diff --git a/pkg/provider/docker/pswarm.go b/pkg/provider/docker/pswarm.go index 07f5dbd0b..07ad3cabc 100644 --- a/pkg/provider/docker/pswarm.go +++ b/pkg/provider/docker/pswarm.go @@ -82,7 +82,7 @@ func (p *SwarmProvider) Provide(configurationChan chan<- dynamic.Message, pool * } defer func() { _ = dockerClient.Close() }() - builder := NewDynConfBuilder(p.Shared, dockerClient) + builder := NewDynConfBuilder(p.Shared, dockerClient, true) serverVersion, err := dockerClient.ServerVersion(ctx) if err != nil { @@ -200,7 +200,7 @@ func (p *SwarmProvider) listServices(ctx context.Context, dockerClient client.AP continue } - if dData.ExtraConf.Docker.LBSwarm { + if dData.ExtraConf.LBSwarm { if len(dData.NetworkSettings.Networks) > 0 { dockerDataList = append(dockerDataList, dData) } @@ -229,37 +229,38 @@ func (p *SwarmProvider) parseService(ctx context.Context, service swarmtypes.Ser NetworkSettings: networkSettings{}, } - extraConf, err := p.extractLabels(dData) + extraConf, err := p.extractSwarmLabels(dData) if err != nil { return dockerData{}, err } dData.ExtraConf = extraConf - if service.Spec.EndpointSpec != nil { - if service.Spec.EndpointSpec.Mode == swarmtypes.ResolutionModeDNSRR { - if dData.ExtraConf.Docker.LBSwarm { - logger.Warn().Msgf("Ignored %s endpoint-mode not supported, service name: %s. Fallback to Traefik load balancing", swarmtypes.ResolutionModeDNSRR, service.Spec.Annotations.Name) + if service.Spec.EndpointSpec == nil { + return dData, nil + } + if service.Spec.EndpointSpec.Mode == swarmtypes.ResolutionModeDNSRR { + if dData.ExtraConf.LBSwarm { + logger.Warn().Msgf("Ignored %s endpoint-mode not supported, service name: %s. Fallback to Traefik load balancing", swarmtypes.ResolutionModeDNSRR, service.Spec.Annotations.Name) + } + } else if service.Spec.EndpointSpec.Mode == swarmtypes.ResolutionModeVIP { + dData.NetworkSettings.Networks = make(map[string]*networkData) + for _, virtualIP := range service.Endpoint.VirtualIPs { + networkService := networkMap[virtualIP.NetworkID] + if networkService == nil { + logger.Debug().Msgf("Network not found, id: %s", virtualIP.NetworkID) + continue } - } else if service.Spec.EndpointSpec.Mode == swarmtypes.ResolutionModeVIP { - dData.NetworkSettings.Networks = make(map[string]*networkData) - for _, virtualIP := range service.Endpoint.VirtualIPs { - networkService := networkMap[virtualIP.NetworkID] - if networkService != nil { - if len(virtualIP.Addr) > 0 { - ip, _, _ := net.ParseCIDR(virtualIP.Addr) - network := &networkData{ - Name: networkService.Name, - ID: virtualIP.NetworkID, - Addr: ip.String(), - } - dData.NetworkSettings.Networks[network.Name] = network - } else { - logger.Debug().Msgf("No virtual IPs found in network %s", virtualIP.NetworkID) - } - } else { - logger.Debug().Msgf("Network not found, id: %s", virtualIP.NetworkID) - } + if len(virtualIP.Addr) == 0 { + logger.Debug().Msgf("No virtual IPs found in network %s", virtualIP.NetworkID) + continue } + ip, _, _ := net.ParseCIDR(virtualIP.Addr) + network := &networkData{ + Name: networkService.Name, + ID: virtualIP.NetworkID, + Addr: ip.String(), + } + dData.NetworkSettings.Networks[network.Name] = network } } return dData, nil diff --git a/pkg/provider/docker/pswarm_test.go b/pkg/provider/docker/pswarm_test.go index c9fae5f12..5406c99be 100644 --- a/pkg/provider/docker/pswarm_test.go +++ b/pkg/provider/docker/pswarm_test.go @@ -65,7 +65,9 @@ func TestListTasks(t *testing.T) { t.Run(strconv.Itoa(caseID), func(t *testing.T) { t.Parallel() - p := SwarmProvider{} + var p SwarmProvider + require.NoError(t, p.Init()) + dockerData, err := p.parseService(context.Background(), test.service, test.networks) require.NoError(t, err) @@ -100,8 +102,8 @@ func TestSwarmProvider_listServices(t *testing.T) { swarmService( serviceName("service1"), serviceLabels(map[string]string{ - "traefik.docker.network": "barnet", - "traefik.docker.LBSwarm": "true", + "traefik.swarm.network": "barnet", + "traefik.swarm.LBSwarm": "true", }), withEndpointSpec(modeVIP), withEndpoint( @@ -111,8 +113,8 @@ func TestSwarmProvider_listServices(t *testing.T) { swarmService( serviceName("service2"), serviceLabels(map[string]string{ - "traefik.docker.network": "barnet", - "traefik.docker.LBSwarm": "true", + "traefik.swarm.network": "barnet", + "traefik.swarm.LBSwarm": "true", }), withEndpointSpec(modeDNSRR)), }, @@ -126,8 +128,8 @@ func TestSwarmProvider_listServices(t *testing.T) { swarmService( serviceName("service1"), serviceLabels(map[string]string{ - "traefik.docker.network": "barnet", - "traefik.docker.LBSwarm": "true", + "traefik.swarm.network": "barnet", + "traefik.swarm.LBSwarm": "true", }), withEndpointSpec(modeVIP), withEndpoint( @@ -137,8 +139,8 @@ func TestSwarmProvider_listServices(t *testing.T) { swarmService( serviceName("service2"), serviceLabels(map[string]string{ - "traefik.docker.network": "barnet", - "traefik.docker.LBSwarm": "true", + "traefik.swarm.network": "barnet", + "traefik.swarm.LBSwarm": "true", }), withEndpointSpec(modeDNSRR)), }, @@ -173,7 +175,7 @@ func TestSwarmProvider_listServices(t *testing.T) { swarmService( serviceName("service1"), serviceLabels(map[string]string{ - "traefik.docker.network": "barnet", + "traefik.swarm.network": "barnet", }), withEndpointSpec(modeVIP), withEndpoint( @@ -183,7 +185,7 @@ func TestSwarmProvider_listServices(t *testing.T) { swarmService( serviceName("service2"), serviceLabels(map[string]string{ - "traefik.docker.network": "barnet", + "traefik.swarm.network": "barnet", }), withEndpointSpec(modeDNSRR)), }, @@ -233,7 +235,8 @@ func TestSwarmProvider_listServices(t *testing.T) { dockerClient := &fakeServicesClient{services: test.services, tasks: test.tasks, dockerVersion: test.dockerVersion, networks: test.networks} - p := SwarmProvider{} + var p SwarmProvider + require.NoError(t, p.Init()) serviceDockerData, err := p.listServices(context.Background(), dockerClient) assert.NoError(t, err) @@ -351,7 +354,8 @@ func TestSwarmProvider_parseService_task(t *testing.T) { t.Run(strconv.Itoa(caseID), func(t *testing.T) { t.Parallel() - p := SwarmProvider{} + var p SwarmProvider + require.NoError(t, p.Init()) dData, err := p.parseService(context.Background(), test.service, test.networks) require.NoError(t, err) diff --git a/pkg/provider/docker/shared_labels.go b/pkg/provider/docker/shared_labels.go index f17e51508..6eab7143d 100644 --- a/pkg/provider/docker/shared_labels.go +++ b/pkg/provider/docker/shared_labels.go @@ -1,8 +1,10 @@ package docker import ( + "errors" "fmt" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v3/pkg/config/label" ) @@ -11,29 +13,73 @@ const ( labelDockerComposeService = "com.docker.compose.service" ) -// configuration Contains information from the labels that are globals (not related to the dynamic configuration) +// configuration contains information from the labels that are globals (not related to the dynamic configuration) // or specific to the provider. type configuration struct { - Enable bool - Docker specificConfiguration -} - -type specificConfiguration struct { + Enable bool Network string LBSwarm bool } -func (p *Shared) extractLabels(container dockerData) (configuration, error) { - conf := configuration{ - Enable: p.ExposedByDefault, - Docker: specificConfiguration{ - Network: p.Network, - }, +type labelConfiguration struct { + Enable bool + Docker *specificConfiguration + Swarm *specificConfiguration +} + +type specificConfiguration struct { + Network *string + LBSwarm bool +} + +func (p *Shared) extractDockerLabels(container dockerData) (configuration, error) { + conf := labelConfiguration{Enable: p.ExposedByDefault} + if err := label.Decode(container.Labels, &conf, "traefik.docker.", "traefik.enable"); err != nil { + return configuration{}, fmt.Errorf("decoding Docker labels: %w", err) } - err := label.Decode(container.Labels, &conf, "traefik.docker.", "traefik.enable") - if err != nil { - return configuration{}, err + network := p.Network + if conf.Docker != nil && conf.Docker.Network != nil { + network = *conf.Docker.Network + } + + return configuration{ + Enable: conf.Enable, + Network: network, + }, nil +} + +func (p *Shared) extractSwarmLabels(container dockerData) (configuration, error) { + labelConf := labelConfiguration{Enable: p.ExposedByDefault} + if err := label.Decode(container.Labels, &labelConf, "traefik.enable", "traefik.docker.", "traefik.swarm."); err != nil { + return configuration{}, fmt.Errorf("decoding Swarm labels: %w", err) + } + + if labelConf.Docker != nil && labelConf.Swarm != nil { + return configuration{}, errors.New("both Docker and Swarm labels are defined") + } + + conf := configuration{ + Enable: labelConf.Enable, + Network: p.Network, + } + + if labelConf.Docker != nil { + log.Warn().Msg("Labels traefik.docker.* for Swarm provider are deprecated. Please use traefik.swarm.* labels instead") + + conf.LBSwarm = labelConf.Docker.LBSwarm + + if labelConf.Docker.Network != nil { + conf.Network = *labelConf.Docker.Network + } + } + + if labelConf.Swarm != nil { + conf.LBSwarm = labelConf.Swarm.LBSwarm + + if labelConf.Swarm.Network != nil { + conf.Network = *labelConf.Swarm.Network + } } return conf, nil diff --git a/pkg/provider/docker/shared_test.go b/pkg/provider/docker/shared_test.go index 0f542d00a..90022c067 100644 --- a/pkg/provider/docker/shared_test.go +++ b/pkg/provider/docker/shared_test.go @@ -98,7 +98,8 @@ func Test_getPort_swarm(t *testing.T) { t.Run(strconv.Itoa(serviceID), func(t *testing.T) { t.Parallel() - p := SwarmProvider{} + var p SwarmProvider + require.NoError(t, p.Init()) dData, err := p.parseService(context.Background(), test.service, test.networks) require.NoError(t, err) diff --git a/pkg/provider/traefik/internal.go b/pkg/provider/traefik/internal.go index e65ab64dc..39c0e9294 100644 --- a/pkg/provider/traefik/internal.go +++ b/pkg/provider/traefik/internal.go @@ -223,6 +223,12 @@ func (i *Provider) entryPointModels(cfg *dynamic.Configuration) { } for name, ep := range i.staticCfg.EntryPoints { + if defaultRuleSyntax != "" { + cfg.TCP.Models[name] = &dynamic.TCPModel{ + DefaultRuleSyntax: defaultRuleSyntax, + } + } + if len(ep.HTTP.Middlewares) == 0 && ep.HTTP.TLS == nil && defaultRuleSyntax == "" { continue } @@ -250,16 +256,6 @@ func (i *Provider) entryPointModels(cfg *dynamic.Configuration) { m.DefaultRuleSyntax = defaultRuleSyntax cfg.HTTP.Models[name] = m - - if cfg.TCP == nil { - continue - } - - mTCP := &dynamic.TCPModel{ - DefaultRuleSyntax: defaultRuleSyntax, - } - - cfg.TCP.Models[name] = mTCP } } diff --git a/pkg/server/aggregator.go b/pkg/server/aggregator.go index 0a849e3d8..72934d469 100644 --- a/pkg/server/aggregator.go +++ b/pkg/server/aggregator.go @@ -2,6 +2,7 @@ package server import ( "slices" + "strings" "github.com/go-acme/lego/v4/challenge/tlsalpn01" "github.com/rs/zerolog/log" @@ -156,7 +157,11 @@ func applyModel(cfg dynamic.Configuration) dynamic.Configuration { router := rt.DeepCopy() if !router.DefaultRule && router.RuleSyntax == "" { - for _, model := range cfg.HTTP.Models { + for modelName, model := range cfg.HTTP.Models { + // models cannot be provided by another provider than the internal one. + if !strings.HasSuffix(modelName, "@internal") { + continue + } router.RuleSyntax = model.DefaultRuleSyntax break } diff --git a/script/deploy.sh b/script/deploy.sh index 3c16b7446..0233235c2 100755 --- a/script/deploy.sh +++ b/script/deploy.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -e -if [ -n "${SEMAPHORE_GIT_TAG_NAME}" ]; then +if [ -n "${VERSION}" ]; then echo "Deploying..." else echo "Skipping deploy" @@ -13,8 +13,8 @@ git config --global user.name "Traefiker" # load ssh key eval "$(ssh-agent -s)" -chmod 600 /home/semaphore/.ssh/traefiker_rsa -ssh-add /home/semaphore/.ssh/traefiker_rsa +chmod 600 ~/.ssh/traefiker_rsa +ssh-add ~/.ssh/traefiker_rsa # update traefik-library-image repo (official Docker image) echo "Updating traefik-library-imag repo..." diff --git a/script/gcg/traefik-bugfix.toml b/script/gcg/traefik-bugfix.toml index 36ccdecf2..539d04d2f 100644 --- a/script/gcg/traefik-bugfix.toml +++ b/script/gcg/traefik-bugfix.toml @@ -4,11 +4,11 @@ RepositoryName = "traefik" OutputType = "file" FileName = "traefik_changelog.md" -# example new bugfix v3.2.1 +# example new bugfix v3.2.2 CurrentRef = "v3.2" -PreviousRef = "v3.2.0" +PreviousRef = "v3.2.1" BaseBranch = "v3.2" -FutureCurrentRefName = "v3.2.1" +FutureCurrentRefName = "v3.2.2" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10