Today I once again came across a configuration issue in traefik.io regarding an authentication problem. Traefik is a cloud native networking solution for container platforms. It can be used for example within Kubernetes and is a build in function of K3S – a lightweight Kubernetes solution.
In K3S Traefik is used for the ingress configuration. For example to route Web traffic from an Internet domain to a specific service within your cluster.
My problem was that I wanted to install a private Docker Registry within my K3S cluster. The Docker Registry comes without any security. This is fine within a cluster, but in case you connect from outside you don’t want that your private registry is open for everyone. With Traefik you can easily secure you service. I will explain how you can do this.
Create a Secret
First you need to create a secret within your cluster to be used later for the basic authentication. With the command-line tool
htpasswd it’s easy to create a file that stores a username / password combination for basic authentication over HTTP.
So first create a password file using
$ htpasswd -c registry-auth-file admin
This command stores the hashed user and password in the file
registry-auth-file. This command will ask you for the password.
Next you can create from this file a corresponding Kubernetes secret using the
kubectl command line tool:
$ kubectl create secret generic registry-basic-auth --from-file=registry-auth
In this example I create a new secret named “registry-basic-auth’. And this secret I use for my Basic Authentication.
Setup a Secure IngressRoute
Now you can create a Traefik IngressRoute for your docker-registry. A IngressRoute is a traefik specific Ingress configuration. It is different to the Kubernets Ingress object. I put all the necessary configuration into one deployment file ‘docker-regsitry-network.yaml’:
# docker-registry-network.yaml --- apiVersion: v1 kind: Service metadata: name: docker-registry labels: app: docker-registry spec: type: LoadBalancer ports: - name: web port: 5000 selector: app: docker-registry --- kind: Middleware apiVersion: traefik.containo.us/v1alpha1 metadata: name: registry-basic-auth spec: basicAuth: secret: registry-basic-auth --- apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: docker-registry spec: entryPoints: - web routes: - match: Host(`example.foo.com`) kind: Rule middlewares: - name: registry-basic-auth services: - name: docker-registry port: 5000
In this deployment configuration I define 3 objects:
- A Service – the service listening on port 5000 for my Docker-Registry
- A Middleware – the traefik object handling the basic authentication with my secret
- A IngressRoute – the traefik Ingress configuration for my Internet domain pointing to my Service
You can apply the new objects with:
$ kubectl apply -f docker-registry-network.yaml
Now when you access your Docker Registry via the Internet Domain name ‘example.foo.com’ you will be prompted for a password.
To login with Docker into your new registy run:
$ docker login -u admin example.foo.com Password: