Traefik and Basic Authentication

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.