Tailscale¶
Provision TLS certificates for your internal Tailscale services.
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.
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.
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 themain
option oftls.domains
. -
Otherwise, the certificate resolver derives the domain name from any
Host()
orHostSNI()
matchers in the router's rule.
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¶
Enabling Tailscale certificate resolution
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
certificatesResolvers:
myresolver:
tailscale: {}
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.websecure]
address = ":443"
[certificatesResolvers.myresolver.tailscale]
--entrypoints.web.address=:80
--entrypoints.websecure.address=:443
# ...
--certificatesresolvers.myresolver.tailscale=true
Domain from Router's Rule Example
## Dynamic configuration
labels:
- traefik.http.routers.blog.rule=Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`)
- traefik.http.routers.blog.tls.certresolver=myresolver
## Dynamic configuration
deploy:
labels:
- traefik.http.routers.blog.rule=Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`)
- traefik.http.routers.blog.tls.certresolver=myresolver
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
## Dynamic configuration
http:
routers:
blog:
rule: "Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`)"
tls:
certResolver: myresolver
## Dynamic configuration
[http.routers]
[http.routers.blog]
rule = "Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`)"
[http.routers.blog.tls]
certResolver = "myresolver"
Domain from Router's tls.domain Example
## 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
## 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
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
## Dynamic configuration
http:
routers:
blog:
rule: "Path(`/metrics`)"
tls:
certResolver: myresolver
domains:
- main: "monitoring.yak-bebop.ts.net"
## Dynamic configuration
[http.routers]
[http.routers.blog]
rule = "Path(`/metrics`)"
[http.routers.blog.tls]
certResolver = "myresolver"
[[http.routers.blog.tls.domains]]
main = "monitoring.yak-bebop.ts.net"
Automatic Renewals¶
Traefik automatically tracks the expiry date of each Tailscale certificate it fetches, and starts to renew a certificate 14 days before its expiry to match Tailscale daemon renew policy.