Helm Charts are updated regularly, so variable names and their locations can change. As a result, we cannot guarantee that every article is always fully up to date. If you notice any information is no longer correct, we’d love to hear from you.
Traefik is a popular open-source reverse proxy and load balancer designed for microservices and containerised applications. Traefik can automatically discover the Services running in a Kubernetes cluster and route traffic to those Services using various load-balancing algorithms.
Traefik sits in front of other Services within your cluster. With Traefik, you can host multiple applications on a Kubernetes cluster and route their traffic through Traefik. Traefik can then act as a single load balancer for all of these applications and can also provision Let’s Encrypt SSL certificates.
In this guide, we’ll show you how to install and use Traefik. We’ll use a custom (sub)domain name (optional) to connect to Traefik and secure it with an SSL certificate. To log in to the Traefik dashboard, we’ll set up a username and password.
For this guide you’ll need:
- Kubectl and a working connection to your Kubernetes cluster; see our Kubectl guide.
- The Helm package manager. Install Helm via our Helm installation guide if you haven’t done so yet.
- A TransIP API private key. Enable the API and generate a Key Pair as described in this guide.
Installing Traefik
Step 1
Add the official Traefik repository and update your Helm repositories so you can use it:
helm repo add traefik https://helm.traefik.io/traefik helm repo update
Step 2
Traefik can generate Let’s Encrypt certificates for applications that communicate via Traefik. In this guide, we assume you want to use this for your own use case as well. To do so, you’ll use an ACME DNS challenge provider. We support this option via our API. Please note that the provider you choose must support this functionality, and the domains you use must be registered with that provider in the account you use for this guide.
Create a directory where you’ll store your TransIP API key, for example:
mkdir transipNext, create a file in the directory you just created containing a private key from your TransIP API account, for example:
cat << EOF > transip/transip.key
-----BEGIN PRIVATE KEY-----
MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDKoaYJtbVnJw58
PYGH8WIJ7ZjWd2lke0IbMV+dNGs=
-----END PRIVATE KEY-----
EOFThis example only includes a small fragment of a private key. Your private key will be much longer.
Step 3
Create a namespace for Traefik in your cluster:
kubectl create ns traefik
Step 4
Generate a Secret based on your API private key that Traefik can use to communicate with the TransIP API. If necessary, replace the following values:
- -n traefik: Use the name of the namespace you created in step 3.
- transip/transip.key: Change this to the directory and file name you created in step 2.
kubectl create -n traefik secret generic transip-key --from-file transip/transip.key
Step 5
Speaking of Secrets: if you configure Traefik to be accessible via the public internet, by default there is no username and/or password set. So we’ll create another Secret containing a username and password to log in to the Traefik dashboard.
Use htpasswd to generate a username and password:
htpasswd -nb <username> <password> >> htpasswd.txtThe contents of the htpasswd.txt file will look roughly like this:
demouser:$2a$13$2QBmxHS5a1hWU9aeyJ.DPNWRFjXcNRNTjcu56QTLhZS.yAre you using Windows to follow these steps? Then use our htpasswd tool and generate an htpasswd username and password. Save the output to a file in the folder where you’re running the commands in this guide, for example c:\Users\Administrator\kubernetes\htpasswd.txt
Then create the Secret based on the contents of the file you just created:
kubectl create secret generic traefik-dashboard-basicauth --from-file=users=htpasswd.txt -n traefik
Step 6
To install Traefik, you’ll use the official Helm Chart in the next step. In an additional .yaml file you’ll make a few changes; create a .yaml file for this, for example:
nano traefik.yamlPopulate the file with the contents below, adjusting a few values:
- example@transip.nl: Change this to your email address.
- jouwaccount: Replace jouwaccount with the name of your TransIP account.
- /transip/transip.key: Change this (if needed) to the directory and file name you created in step 2.
- traefik.transip.nl: Change this to the (sub)domain you want to connect to Traefik.
deployment:
initContainers:
- name: volume-permissions
image: busybox:latest
command: ["sh", "-c", "touch /data/acme.json; chmod -v 600 /data/acme.json"]
volumeMounts:
- mountPath: /data
name: data
podSecurityContext:
fsGroup: 65532
fsGroupChangePolicy: "OnRootMismatch"
additionalArguments:
- "--certificatesresolvers.myresolver.acme.email=shagting@transip.nl"
- "--certificatesresolvers.myresolver.acme.dnschallenge.provider=transip"
- "--certificatesresolvers.myresolver.acme.dnschallenge.propagation.delayBeforeChecks=120"
- "--certificatesresolvers.myresolver.acme.storage=/data/acme.json"
- "--providers.kubernetescrd.namespaces="
env:
- name: TRANSIP_ACCOUNT_NAME
value: testtransip
- name: TRANSIP_PRIVATE_KEY_PATH
value: /transip/transip.key
volumes:
- name: transip-key
mountPath: "/transip"
type: secret
persistence:
enabled: true
size: 128Mi
ports:
websecure:
tls:
enabled: true
expose:
default: true
exposedPort: 443
ingressRoute:
dashboard:
enabled: true
entryPoints:
- websecure
matchRule: Host(`traefik.supporttest.nl`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))
tls:
certResolver: myresolver
middlewares:
- name: "dashboard-auth"
namespace: "traefik"
extraObjects:
- apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: dashboard-auth
namespace: traefik
spec:
basicAuth:
secret: "traefik-dashboard-basicauth"
podAnnotations:
prometheus.io/port: "8082"
prometheus.io/scrape: "true"
providers:
kubernetesGateway:
enabled: true
kubernetesIngress:
publishedService:
enabled: true
priorityClassName: "system-cluster-critical"
image:
registry: docker.io
repository: traefik
tolerations:
- key: "CriticalAddonsOnly"
operator: "Exists"
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
- key: "node-role.kubernetes.io/master"
operator: "Exists"
effect: "NoSchedule"
- key: "node-role.kubernetes.io/master"
operator: "Exists"
effect: "NoSchedule"Code explanation
For a full overview of the available options, see the official Helm chart. In a nutshell, the different sections mean the following:
- deployment.initcontainers: Out of the box, Traefik is configured not to have permission to write SSL certificates to the default file intended for this purpose, /data/acme.json. This section ensures Traefik gets read and write permissions by adjusting the permissions with a chmod command.
- podsecuritycontext: Ensures each volume has the correct owner (65532).
- additionalArguments: The values provided specify which email address will receive notifications related to generating SSL certificates, that you use TransIP’s systems (via our API) to generate Let’s Encrypt certificates, how often they are renewed, where they are stored, and that Traefik monitors and can use all namespaces.
- env: Information related to your TransIP API details (from steps 2 and 4).
- volumes: Here you configure additional volumes (a kind of disk); in this case, the /transip volume to store your API details.
- persistence: Controls whether the volume used to store SSL certificates (/data) is retained if you remove your Traefik installation. In this .yaml file, this option is enabled.
- ports: The configuration related to using Traefik over SSL (whether it can be used, which port, etc.).
- ingressRoute: An IngressRoute ensures incoming network requests are routed to the correct Services.
- extraObjects: Adds extra components to your Traefik setup. In this setup, you add a Middleware that prompts for a password when you open the Traefik dashboard in your browser, as configured in the traefik-dashboard-basicauth Secret (which you created in step 5).
- podAnnotations: Additional labels to attach to the Traefik pod, in this case to enable the use of Prometheus in conjunction with Traefik.
- providers: Enables (a) using Traefik as a Gateway instead of the traditional (end-of-life) Nginx Ingress and (b) Traefik’s option to discover Kubernetes Ingress resources. This option is enabled by default in the official Helm Chart. We’ve included it here anyway, in case Traefik decides to disable it by default at a later date.
- priorityClassName: Sets a priority class for Traefik. If, for whatever reason, Kubernetes needs to decide which Pods to prioritise when creating them, a Pod with a priority class will be prioritised.
- image: Which image is used to create the Traefik deployment.
- tolerations: Certain pods cannot be placed (i.e. scheduled) on a node with a taint unless the pod has a toleration for that specific taint; see our article on taints & tolerations.
Step 7
Install the Traefik Helm Chart using the command below.
helm install -f traefik.yaml traefik traefik/traefik -n traefik
- helm install: Installs the Helm Chart.
- -f traefik.yaml: The file from step 6 that we use to customise the installation.
- traefik: The name of the Helm ‘release’, which you can check with the ‘helm list’ command.
- traefik/traefik: Respectively, the name of the repository and the Helm Chart to install.
- -n traefik: The namespace in which the Helm release is installed; see step 3.
You’ll now see a confirmation that looks roughly like this:
NAME: traefik
LAST DEPLOYED: Wed Feb 12 09:22:05 2025
NAMESPACE: traefik
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
traefik with docker.io/traefik:v3.3.3 has been deployed successfully on traefik namespace !
🚨 When enabling persistence for certificates, permissions on acme.json can be
lost when Traefik restarts. You can ensure correct permissions with an
initContainer. See https://github.com/traefik/traefik-helm-chart/blob/master/EXAMPLES.md#use-traefik-native-lets-encrypt-integration-without-cert-managerYou can ignore the warning: you addressed this issue at the start of the traefik.yaml file you created in the previous step.
Traefik has now been installed successfully, but… what’s next? That brings us to the Traefik dashboard first; see the next section.
The Traefik dashboard
Traefik comes with a web interface that gives you insight into the status of your Kubernetes cluster and the traffic processed by your cluster. It shows information about the routers and Services used to handle traffic, as well as the load-balancing algorithms in use. The dashboard also gives you the ability to view logs and metrics generated by Traefik. In short, the dashboard is a handy tool for monitoring and troubleshooting Traefik.
Step 1
To use the Traefik dashboard, first find the external IP address of your Traefik LoadBalancer (created automatically):
kubectl get svc -n traefikIn the output, under ‘external-IP’, you’ll see an address that looks like: 86-105-245-108.haip.transip.net. Note down the numbers and replace the hyphens with dots, i.e.: 86.105.245.108.
Step 2
Want to link Traefik to a (sub)domain? First create an A record for your domain name; see this guide. For example, use the name ‘traefik’ and set its value to the IP address from the previous step.
Step 3
At the start of this article, we told you that you’ll be using the TransIP API and that you’ll need a key for it. When you created the API key, you were given the option to restrict the key to whitelisted IP addresses only. If you chose this option, also add the IP address from step 1 to your API whitelist; see our API guide again.
It may take a little while for the DNS and API changes to be picked up. Once they’ve been processed, you can view the Traefik dashboard in a browser via your subdomain, for example https://traefik.voorbeeld.nl/dashboard/, or directly via the IP address at https://<ip-address>:/dashboard/. When prompted for a username and password, use the ones from step 5 of the previous section.
Updating your configuration
It’s advisable to keep the public IP address of your load balancer when you make changes to Traefik’s configuration. So, where possible, don’t remove your entire Traefik installation when making changes. Instead, apply any changes in traefik.yaml and update your Helm installation with:
helm upgrade -f traefik.yaml traefik traefik/traefik -n traefik
Cert-manager or not
Traefik can generate Let’s Encrypt certificates perfectly well. However, do you use Cert-manager for your use case? If so, you’ll need a few changes in the .yaml file from step 6 of the Traefik installation and configuration. Update traefik.yaml so it looks like the example below (only remove the deployment.initcontainers section if you don’t need /data for your project):
podSecurityContext:
fsGroup: 65532
fsGroupChangePolicy: "OnRootMismatch"
persistence:
enabled: true
size: 128Mi
ports:
websecure:
tls:
enabled: true
expose:
default: true
exposedPort: 443
ingressRoute:
dashboard:
enabled: true
entryPoints:
- websecure
matchRule: Host(`traefik.supporttest.nl`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))
tls:
secretName: traefik-dashboard-tls
middlewares:
- name: "dashboard-auth"
namespace: "traefik"
extraObjects:
- apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: dashboard-auth
namespace: traefik
spec:
basicAuth:
secret: "traefik-dashboard-basicauth"
podAnnotations:
prometheus.io/port: "8082"
prometheus.io/scrape: "true"
providers:
kubernetesGateway:
enabled: true
kubernetesIngress:
publishedService:
enabled: true
priorityClassName: "system-cluster-critical"
image:
registry: docker.io
repository: traefik
tolerations:
- key: "CriticalAddonsOnly"
operator: "Exists"
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
- key: "node-role.kubernetes.io/master"
operator: "Exists"
effect: "NoSchedule"Also use a separate .yaml file (or include the configuration in your existing .yaml) to define the certificate you want to request, e.g. certificate.yaml:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: demo-cert
namespace: demo-setup
spec:
secretName: demo-setup-tls
issuerRef:
name: letsencrypt-issuer
kind: ClusterIssuer
dnsNames:
- demo.voorbeeld.nlOf course, update the name, namespace, secretName, issuerRef.name and dnsNames to match your project.
Finally, apply the configuration:
helm upgrade -f traefik.yaml traefik traefik/traefik -n traefik
kubectl apply -f certificate.yaml
Example of using Traefik
You can now use Traefik to route traffic to your deployments via the Gateway API. Below is an example of how to expose a simple Nginx application through a Traefik Gateway and HTTPRoute, including an HTTP->HTTPS redirect without redirect loops. Note: don’t copy this 1:1—adjust namespaces, hostnames, and secret names to match your use case (e.g. nginx.example.com).
Nginx Deployment and Service:
The example below deploys a simple Nginx setup that receives traffic on port 80.
apiVersion: v1
kind: Namespace
metadata:
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: nginx
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:stable-alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: nginx
spec:
selector:
app: nginx
ports:
- name: http
port: 80
targetPort: 80
Certificate (cert-manager):
cert-manager creates a TLS Secret (for example nginx-example-com-tls). You then attach that Secret to the HTTPS listener in the Gateway via tls.certificateRefs.
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: nginx-cert
namespace: nginx
spec:
secretName: nginx-example-com-tls
issuerRef:
name: letsencrypt-issuer
kind: ClusterIssuer
dnsNames:
- nginx.example.com
Gateway:
The Gateway defines the “entry point” to your cluster for this hostname. The HTTPS listener uses the certificate from the Secret created by cert-manager. Note: in many Traefik Helm installs the entryPoints listen internally on 8000/8443; make sure your listener ports match your Traefik entryPoints.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: nginx-gateway
namespace: nginx
spec:
gatewayClassName: traefik
listeners:
- name: web
protocol: HTTP
port: 8000
hostname: nginx.example.com
allowedRoutes:
namespaces:
from: Same
- name: websecure
protocol: HTTPS
port: 8443
hostname: nginx.example.com
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: nginx-example-com-tls
allowedRoutes:
namespaces:
from: Same
HTTPRoute (redirect HTTP -> HTTPS):
To automatically redirect HTTP to HTTPS without redirect loops, create a separate HTTPRoute that only attaches to the HTTP listener (sectionName: web) and applies a RequestRedirect filter.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: nginx-route-redirect
namespace: nginx
spec:
parentRefs:
- name: nginx-gateway
sectionName: web
hostnames:
- nginx.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /
filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301
HTTPRoute (HTTPS to the Service):
This route attaches to the HTTPS listener (sectionName: websecure) and forwards traffic to the Nginx Service.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: nginx-route
namespace: nginx
spec:
parentRefs:
- name: nginx-gateway
sectionName: websecure
hostnames:
- nginx.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: nginx
port: 80Apply the resources and verify their status:
kubectl apply -f nginx-deployment-service.yaml
kubectl apply -f nginx-certificate.yaml
kubectl apply -f nginx-gateway.yaml
kubectl apply -f nginx-httproute-redirect.yaml
kubectl apply -f nginx-httproute.yaml
kubectl get certificate -n nginx
kubectl describe gateway nginx-gateway -n nginx
kubectl describe httproute nginx-route-redirect -n nginx
kubectl describe httproute nginx-route -n nginx
That brings us to the end of our guide on installing and using Traefik in Kubernetes.