Also at Deasil Works · txn2 · Plexara
Profiles GitHub · X · LinkedIn
Theme Light · Auto · Dark
Professional notes by Craig Johnston
long-form, short-form, working drafts · since 2008
VOL. XIX · MMXXVI
122 NOTES IN PRINT
FOLIO XIX 2018-05-19 · 6 MIN · SHORT-FORM

Basic Auth on Kubernetes Ingress

Basic Auth is supported by nearly every major web client, library, and utility.

Diagram · folio xix
sequenceDiagram
    autonumber
    actor C as Client
    participant ING as Ingress-nginx
    participant SEC as basic-auth secret (htpasswd)
    participant API as backend service

    C->>ING: GET /api (no Authorization header)
    ING-->>C: 401 + WWW-Authenticate Basic

    Note over C: client prompts for username and password
    C->>ING: GET /api (Authorization Basic ...)
    ING->>SEC: bcrypt verify against htpasswd
    alt valid credentials
        ING->>API: forward
        API-->>ING: response
        ING-->>C: 200 + body
    else invalid
        ING-->>C: 401
    end

Basic Auth is one of the oldest and easiest ways to secure a web page or API endpoint. Basic Auth does not have many features and lacks the sophistication of more modern access controls (see Ingress Nginx Auth Examples). However, Basic Auth is supported by nearly every major web client, library, and utility. Basic Auth is secure, stable and perfect for quick security on Kubernetes projects. Basic Auth can easily be swapped out later as requirements demand, or provide a foundation for implementations such as OAuth 2 and JWT.


§2026 Update

The technique still works: an htpasswd Secret plus three annotations is still how you add Basic Auth on ingress-nginx. Two caveats for 2026.

The annotations are ingress-nginx-specific, and ingress-nginx is retired. The nginx.ingress.kubernetes.io/auth-* annotations only mean something to the ingress-nginx controller, which the Kubernetes project wound down in March 2026 (more in my 413 post). On a maintained controller you do the same thing its own way; Traefik, for example, has a BasicAuth middleware. The Gateway API has no built-in Basic Auth, so there you front the route with an external auth service. And for anything past a quick gate, skip Basic Auth and put an OIDC proxy like oauth2-proxy in front, which is the grown-up version of the OAuth2 and JWT direction mentioned at the top of this post.

The Ingress API also moved. The extensions/v1beta1 used in the example below was removed in Kubernetes 1.22; the current group is networking.k8s.io/v1, with a structured service.name and service.port.number backend, a required pathType, and ingressClassName. The auth annotations and the tls block carry over unchanged:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ok-auth
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: sysop
    nginx.ingress.kubernetes.io/auth-realm: "Authentication Required - ok"
spec:
  ingressClassName: nginx
  rules:
  - host: ok-auth.la.txn2.net
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: ok
            port:
              number: 5001
  tls:
  - hosts:
    - ok-auth.la.txn2.net
    secretName: la-txn2-net-tls

One small upgrade to the htpasswd step below: pass -B to force bcrypt (htpasswd -c -B ./auth sysop) rather than the older default hash.


Original article below. Everything from here down is the post as originally written. The 2026 Update above covers what’s changed since.

First, you need an Ingress controller on your Kubernetes cluster and at least one ingress rule that we can apply Basic Auth. If you are following along with my articles on building a Production Hobby Cluster Kubernetes and do not yet have Ingress installed, you should read Ingress on Custom Kubernetes before getting started.

§Security

The Basic Auth process sends credentials to the server in the clear, although encrypted and base64’d, they can be quickly reversed back into a human-readable string. Because of this, it is essential we are issuing calls over SSL/TLS. However, if the information or service being password protected should be hidden, then SSL/TLS encrypted communication would already be required.

For the Production Hobby Cluster we use Let’s Encrypt, so if you have not done so already you can check out my article on setting up Let’s Encrypt for your custom cluster read: Let’s Encrypt, Kubernetes.

§Create a User and Password

Start by creating an htpasswd file that contains the Basic Auth credentials. The following creates a user called sysop, choose whatever username you like.

htpasswd -c ./auth sysop

It is important to name the file auth. The filename is used as the key in the key-value pair under the data section of secret.

After entering a password for the new user twice, you end up with the file auth.

§Create a Secret

Kubernetes can create a generic Secret from the generated auth file, or from any file, however, the format of the htpasswd generated file is necessary for use with Basic Auth. The file name is used as the key in Basic Auth secret, therefore it’s best to name it auth and avoid having to edit the secret. Ingress uses the new Secret in its annotation section to provide Basic Auth.

The kubectl create secret command can create a secret from a local file, directory or literal value using the generic directive. In the example below I call the new secret sysop, named after the single set of credentials stored in it. However, if you are grouping many credentials, it would be better to give it a more generic name.

Create the Secret:

kubectl create secret generic sysop --from-file auth

Ensure the Secret was created successfully by viewing the details:

kubectl get secret sysop -o yaml

You should have a secret similar to the following:

apiVersion: v1
data:
  auth: c3avb2A2GGFwcjEkMmo5SwoucC4kcWtDR3NTVUxSDXJmTVkwNUwxUlZYLbo=
kind: Secret
metadata:
  creationTimestamp: 2018-05-18T06:55:51Z
  name: sysop
  namespace: default
  resourceVersion: "265674"
  selfLink: /api/v1/namespaces/default/secrets/sysop
  uid: 2bfb399c-58d6-11e8-b11e-5600017e897a
type: Opaque

Of course, you should avoid publishing your new Secret like I just did, since the auth: value under data: is only a base64 encoded version of the username and encoded password pair. The password may be reversed quickly with a dictionary attack or other password cracking utilities.

§Protect Ingress

The following is an example Ingress configuration for a test application called ok running on the phc.txn2.net test cluster. It uses the 2018 extensions/v1beta1 API; see the 2026 Update above for the current networking.k8s.io/v1 form.

 apiVersion: extensions/v1beta1
 kind: Ingress
 metadata:
   name: ok-auth
   labels:
     app: ok-auth
     system: test
   annotations:
     nginx.ingress.kubernetes.io/auth-type: basic
     nginx.ingress.kubernetes.io/auth-secret: sysop
     nginx.ingress.kubernetes.io/auth-realm: "Authentication Required - ok"
 spec:
   rules:
   - host: ok-auth.la.txn2.net
     http:
       paths:
       - backend:
           serviceName: "ok"
           servicePort: 5001
         path: /
   tls:
   - hosts:
     - ok-auth.la.txn2.net
     secretName: la-txn2-net-tls

All that is needed are three Ingress annotations:

  • nginx.ingress.kubernetes.io/auth-type: basic
  • nginx.ingress.kubernetes.io/auth-secret: sysop
  • nginx.ingress.kubernetes.io/auth-realm: “Authentication Required - ok.”

The Ingress for ok-auth.la.txn2.net is now Basic Auth protected using credentials in a Secret called sysop.

§Port Forwarding / Local Development

Check out kubefwd for a simple command line utility that bulk forwards services of one or more namespaces to your local workstation.

§Resources

If you found this article useful, you may want to check out all the articles used to build on the Production Hobby Cluster tagged with phc.txn2.net.

Additional examples of Ingress authentication can be found at the official Ingress Nginx Auth Examples repository.


If in a few days you find yourself setting up a cluster in Japan or Germany on Linode, and another two in Australia and France on vultr, then you may have just joined the PHC (Performance Hobby Clusters) club. Some people tinker late at night on their truck, we benchmark and test the resilience of node failures on our overseas, budget kubernetes clusters. It’s all about going big, on the cheap.

k8s performance hobby clusters

← back to all notes