Background
Last year, I started running Traefik full-time in my homelab. Coming from nginx, I’m happy that its
- not nginx
- HTTP/2 support out-the-box
- decent troubleshooting dashboard
- plug-n-play with k3s, prometheus
But it’s not all roses. I’ve lost a few evenings (and a couple Saturdays) troubleshooting my Traefik setup.
Hopefully these gotchas will saves someone, somewhere a few hours of head-scratching.
I can’t reach the Traefik dashboard
No, it’s not that you disabled the dashboard in the configuration file.
$ kubectl port-forward \
$(kubectl get pods --selector "app.kubernetes.io/name=traefik" --output=name) 9000:9000
After binding to the traefik pod, always remember to open localhost:9000/dashboard/.
localhost:9000, localhost:9000/dashboard – both of these will 404. It must be localhost:9000/dashboard/
How do I install Traefik v2?
First, k3s ships with an old version of Traefik. Don’t use it – most of the docs / support online are for v2.
$ curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--no-deploy traefik --node-label role=server " sh -
Install k3s servers without the old version of Traefik. Then install Traefik v2 from the helm chart.
How do I customize Traefik?
The docs are loaded with YAML / TOML examples, but its not clear how they end up in the Traefik container.
One way is to create a config map
apiVersion: v1
kind: ConfigMap
metadata:
name: traefik-config
data:
traefik-config.yaml: |
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
Customize the values in the Traefik helm chart to volume mount the config map
additionalArguments:
- --providers.file.filename=/config/traefik-config.yaml
logs:
general:
level: DEBUG # verbose, but handy for configuration error messages
volumes:
- mountPath: /config
name: traefik-config
type: configMap
And install
$ helm install traefik traefik/traefik -f traefik.yml
All the Traefik configuration that doesn’t pertain to individual ingress routes – the traefik-config.yaml
is where it should go.
How do I route traffic to a deployment?
With Traefik v1, you’d use native k8s ingress objects.
Don’t do this. Install Traefik v2.
With Traefik v2, you need three parts: a Deployment
, a Service
, and a Traefik CRD IngressRoute
.
apiVersion: apps/v1
kind: Deployment
metadata:
name: key
labels:
app: key
spec:
selector:
matchLabels:
app: key
replicas: 1
template:
metadata:
labels:
app: key
spec:
nodeSelector:
role: worker
containers:
- name: key
image: docker.home/key:latest
imagePullPolicy: Always
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
---
apiVersion: v1
kind: Service
metadata:
name: key
spec:
selector:
app: key
ports:
- port: 80
name: key
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: key
spec:
entryPoints:
- web
routes:
- match: Host(`key.home`) && PathPrefix(`/`)
kind: Rule
services:
- name: key
port: 80
(for this example: *.home
DNS requests are forwarded to my server running Traefik, the deployment is an HTTP server listening on port 80)
How do I allow self-signed certs through Traefik? (tls passthrough)
Popular homelab containers like the docker registry, unifi controller require HTTPS. If you don’t provide certs, they’ll default to the container’s self-signed certs.
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: docker-registry
spec:
entryPoints:
- websecure
routes:
- match: Host(`docker.home`)
services:
- name: docker-registry
port: 5000
tls:
passthrough: true
The Deployment
, Service
objects stay the same.
How do I specify custom certs through Traefik?
If you have your own certificate pair, the easiest approach is to slap it on the default Traefik cert store.
Change the traefik config map
apiVersion: v1
kind: ConfigMap
metadata:
name: traefik-config
data:
traefik-config.yaml: |
tls:
stores:
default:
defaultCertificate:
certFile: /certs/ca.crt
keyFile: /certs/ca.key
And update the helm chart values to volume mount certs into the Traefik deployment
...
volumes:
- mountPath: /config
name: traefik-config
type: configMap
- mountPath: /certs
name: my-certs
type: configMap
...
Where my-certs
could be a config map, secret, etc
apiVersion: v1
kind: ConfigMap
metadata:
name: my-certs
data:
ca.key: |
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
ca.crt: |
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
Lastly, set the passthrough to false.
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteTCP
metadata:
name: key
spec:
entryPoints:
- websecure
routes:
- match: HostSNI(`key.de1ux.com`)
services:
- name: key
port: 80
tls:
passthrough: false