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
:
$ 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:
That’s it.