Minikube’s default HTTP setup is fine for local development, but eventually you’ll want to test your application’s HTTPS behavior. This usually means serving your app over TLS, which for local development means dealing with self-signed certificates.

Here’s how to get Minikube to serve your local services over HTTPS using self-signed certificates.

First, let’s get a basic service running in Minikube that we’ll later expose over HTTPS. We’ll use a simple Nginx deployment.

kubectl create deployment nginx-test --image=nginx
kubectl expose deployment nginx-test --port=80 --type=NodePort

Now, let’s find the NodePort assigned to our Nginx service.

kubectl get service nginx-test

You’ll see output like this:

NAME         TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
nginx-test   NodePort   10.101.11.222   <none>        80:31234/TCP   1m

The important part is 80:31234/TCP. The 31234 is the NodePort. Minikube’s IP address can be found with minikube ip. Let’s assume it’s 192.168.49.2. So, you can access your Nginx deployment at http://192.168.49.2:31234.

Now, let’s tackle the HTTPS part. We need a certificate and a private key for our local domain. Since we’re using Minikube, we’ll typically be accessing services via the Minikube IP and a NodePort, or by using minikube tunnel and an Ingress. For simplicity, let’s focus on direct NodePort access first, which means we need a certificate that covers the Minikube IP and potentially a hostname.

We can generate a self-signed certificate using openssl.

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    -keyout tls.key \
    -out tls.crt \
    -subj "/CN=minikube-local.com/O=minikube-local"

This creates tls.key (your private key) and tls.crt (your certificate). The /CN (Common Name) is crucial. While technically minikube-local.com isn’t a real domain you’re browsing to, it’s what the browser will check against the certificate. You could also use your Minikube IP here, but a hostname is generally better practice.

Next, we need to store these as a Kubernetes Secret. Secrets are the standard way to store sensitive information like TLS certificates.

kubectl create secret tls my-tls-secret --key tls.key --cert tls.crt

Now, we need to tell our Nginx deployment to use these TLS credentials. We can do this by mounting the secret as a volume into the Nginx pod and then configuring Nginx to use those files. We’ll need to edit our deployment.

First, let’s get the YAML for our deployment and service.

kubectl get deployment nginx-test -o yaml > nginx-test-deployment.yaml
kubectl get service nginx-test -o yaml > nginx-test-service.yaml

Now, edit nginx-test-deployment.yaml. We need to add a volume and volumeMounts section to the pod’s spec. We also need to modify the containers to use these mounts and configure Nginx.

Here’s an example of how you might modify the nginx-test-deployment.yaml. We’ll update the spec.template.spec to include:

    spec:
      volumes:
      - name: tls-certs
        secret:
          secretName: my-tls-secret
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: tls-certs
          mountPath: "/etc/nginx/ssl"
          readOnly: true
        # You'll need to add a command or config to tell Nginx to use these certs.
        # For a quick test, you can override the default nginx command to run a script
        # that configures nginx. Or, even simpler for demonstration, modify the image
        # or use a custom nginx.conf.
        # A more robust way is to provide a custom nginx.conf.

A simpler approach for local testing is to use an Ingress controller, which is designed to handle TLS termination. Minikube comes with an Ingress addon.

First, enable the Ingress addon:

minikube addons enable ingress

Once enabled, Minikube will deploy an Ingress controller. You can verify it’s running:

kubectl get pods -n kube-system | grep ingress

Now, we need to create an Ingress resource that points to our nginx-test service and uses the my-tls-secret.

Create a file named nginx-ingress.yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  annotations:
    # This annotation is crucial for Nginx Ingress Controller to use TLS
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
  tls:
  - hosts:
    - minikube-local.com
    secretName: my-tls-secret
  rules:
  - host: minikube-local.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-test
            port:
              number: 80

Apply this Ingress resource:

kubectl apply -f nginx-ingress.yaml

Now, you need to tell your local machine to resolve minikube-local.com to your Minikube IP. You can do this by editing your /etc/hosts file (on Linux/macOS) or C:\Windows\System32\drivers\etc\hosts (on Windows). Add the following line:

192.168.49.2    minikube-local.com

(Remember to replace 192.168.49.2 with the actual output of minikube ip).

Now, when you navigate to https://minikube-local.com in your browser, you should see the Nginx welcome page. Your browser will likely show a security warning because the certificate is self-signed. You’ll need to accept the risk to proceed.

The key insight here is that the Ingress controller acts as the TLS terminator. It takes the incoming HTTPS request, decrypts it using the certificate from my-tls-secret, and then forwards the request as plain HTTP to your nginx-test service. This is a common pattern for handling TLS termination in Kubernetes.

The next hurdle you’ll likely encounter is managing more complex certificate requirements, such as wildcard certificates or integrating with external certificate authorities for staging environments.

Want structured learning?

Take the full Minikube course →