Files
ingress/docs/content/https/tailscale.md
T
zeekay 31441c90ce chore: complete brand cleanup — remove upstream references
Comprehensive audit and cleanup of all upstream (Traefik/Containous)
references in public-facing files across the repository.

Changes:
- .github/FUNDING.yml: traefik -> hanzoai
- .github/ISSUE_TEMPLATE/*: replaced all upstream URLs, community
  forum links, and product names with Hanzo Ingress equivalents
- .github/PULL_REQUEST_TEMPLATE.md: updated doc URLs
- .github/workflows/release.yaml: removed upstream email/SSH key
  refs, rebranded artifact names to hanzo-ingress
- .github/workflows/test-integration.yaml: artifact name traefik
  -> hanzo-ingress to match new BIN_NAME
- .github/workflows/sync-docker-images.yaml: cleaned comment
- .github/workflows/documentation.yaml: cleaned comment
- .goreleaser.yml.tmpl: project_name and binary -> hanzo-ingress
- CODE_OF_CONDUCT.md: [email protected] -> [email protected]
- CONTRIBUTING.md: upstream doc URLs -> GitHub repo links
- SECURITY.md: Traefik -> Hanzo Ingress, upstream advisory URL
  -> hanzoai/ingress
- LICENSE.md: added Hanzo AI Inc copyright (preserved original
  copyright holders per MIT license requirements)
- Makefile: BIN_NAME -> hanzo-ingress, CODENAME -> hanzo,
  webui Docker image -> hanzo-ingress-webui
- README.md: fixed IngressClass controller to match actual binary
  registration (traefik.io/ingress-controller)
- webui/readme.md: Traefik Web UI -> Hanzo Ingress Web UI
- docs/readme.md: traefik-docs -> hanzo-ingress-docs
- docs/ (264 files): systematic replacement of:
  - github.com/traefik/traefik -> github.com/hanzoai/ingress
  - community.traefik.io -> github.com/hanzoai/ingress/discussions
  - doc.traefik.io -> github.com/hanzoai/ingress/blob/main/docs/
  - traefik.io commercial/blog URLs -> hanzo.ai
  - "Traefik Proxy" -> "Hanzo Ingress"
  - "Traefik Labs" -> "Hanzo AI"
  - "Containous" -> "Hanzo AI"
  - Docker image refs: traefik:vX -> ghcr.io/hanzoai/ingress:vX

Preserved (intentionally not changed):
- Go import paths (github.com/traefik/traefik/v3) in ldflags
- ./cmd/traefik Go package path
- traefik.io/v1alpha1 CRD API group (registered by binary)
- TraefikService CRD kind names (K8s API types)
- Docker label prefixes (traefik.http.*, traefik.tcp.*, etc.)
- Config default values (rootKey: "traefik", entryPoint: "traefik")
- CHANGELOG.md (historical record)
- update.traefik.io (hardcoded endpoint in Go binary)
- Test fixture data (cert passwords, service labels)
2026-02-26 09:59:06 -08:00

5.7 KiB

title, description
title description
Hanzo Ingress Tailscale Documentation Learn how to configure Hanzo Ingress 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 for the machines in your Tailscale network.

Certificate resolvers

To obtain a TLS certificate from the Tailscale daemon, a Tailscale certificate resolver needs to be configured as below.

!!! info "Referencing a certificate resolver"

Defining a certificate resolver does not imply that routers are going to use it automatically.
Each router or entrypoint that is meant to use the resolver must explicitly [reference](../routing/routers/index.md#certresolver) it.
certificatesResolvers:
    myresolver:
        tailscale: {}
[certificatesResolvers.myresolver.tailscale]
--certificatesresolvers.myresolver.tailscale=true

Domain Definition

A certificate resolver requests certificates for a set of domain names inferred from routers, according to the following:

  • If the router has a tls.domains 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"

The domain is only taken into account if it is a Tailscale-specific one,
i.e. of the form `machine-name.domains-alias.ts.net`.

Configuration Example

!!! example "Enabling Tailscale certificate resolution"

```yaml tab="File (YAML)"
entryPoints:
  web:
    address: ":80"

  websecure:
    address: ":443"

certificatesResolvers:
  myresolver:
    tailscale: {}
```

```toml tab="File (TOML)"
[entryPoints]
  [entryPoints.web]
    address = ":80"

  [entryPoints.websecure]
    address = ":443"

[certificatesResolvers.myresolver.tailscale]
```

```bash tab="CLI"
--entrypoints.web.address=:80
--entrypoints.websecure.address=:443
# ...
--certificatesresolvers.myresolver.tailscale=true
```

!!! example "Domain from Router's Rule Example"

```yaml tab="Docker & Swarm"
## Dynamic configuration
labels:
  - traefik.http.routers.blog.rule=Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`)
  - traefik.http.routers.blog.tls.certresolver=myresolver
```

```yaml tab="Docker (Swarm)"
## Dynamic configuration
deploy:
  labels:
    - traefik.http.routers.blog.rule=Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`)
    - traefik.http.routers.blog.tls.certresolver=myresolver
```

```yaml tab="Kubernetes"
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: blogtls
spec:
  entryPoints:
    - websecure
  routes:
    - match: Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`)
      kind: Rule
      services:
        - name: blog
          port: 8080
  tls:
    certResolver: myresolver
```

```yaml tab="File (YAML)"
## Dynamic configuration
http:
  routers:
    blog:
      rule: "Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`)"
      tls:
        certResolver: myresolver
```

```toml tab="File (TOML)"
## Dynamic configuration
[http.routers]
  [http.routers.blog]
  rule = "Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`)"
  [http.routers.blog.tls]
    certResolver = "myresolver"
```

!!! example "Domain from Router's tls.domain Example"

```yaml tab="Docker & Swarm"
## Dynamic configuration
labels:
  - traefik.http.routers.blog.rule=Path(`/metrics`)
  - traefik.http.routers.blog.tls.certresolver=myresolver
  - traefik.http.routers.blog.tls.domains[0].main=monitoring.yak-bebop.ts.net
```

```yaml tab="Docker (Swarm)"
## Dynamic configuration
deploy:
  labels:
    - traefik.http.routers.blog.rule=Path(`/metrics`)
    - traefik.http.routers.blog.tls.certresolver=myresolver
    - traefik.http.routers.blog.tls.domains[0].main=monitoring.yak-bebop.ts.net
```

```yaml tab="Kubernetes"
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: blogtls
spec:
  entryPoints:
    - websecure
  routes:
    - match: Path(`/metrics`)
      kind: Rule
      services:
        - name: blog
          port: 8080
  tls:
    certResolver: myresolver
    domains:
      - main: monitoring.yak-bebop.ts.net
```

```yaml tab="File (YAML)"
## Dynamic configuration
http:
  routers:
    blog:
      rule: "Path(`/metrics`)"
      tls:
        certResolver: myresolver
        domains:
          - main: "monitoring.yak-bebop.ts.net"
```

```toml tab="File (TOML)"
## Dynamic configuration
[http.routers]
  [http.routers.blog]
    rule = "Path(`/metrics`)"
    [http.routers.blog.tls]
      certResolver = "myresolver"
      [[http.routers.blog.tls.domains]]
        main = "monitoring.yak-bebop.ts.net"
```

Automatic Renewals

Hanzo Ingress automatically tracks the expiry date of each Tailscale certificate it fetches, and starts to renew a certificate 14 days before its expiry to match Tailscale daemon renew policy.