Deploying Nginx with Self-Signed TLS Using Helm and Minikube (Dev & Staging Environments)

Tandap Noel Bansikah - Oct 20 - - Dev Community

In this tutorial, I will guide you through the process of deploying an Nginx server with a self-signed TLS certificate using Helm in a Minikube Kubernetes cluster. We'll create two distinct environments: development (dev) and (staging), each with its own configurations. This will help simulate a real-world scenario where both environments are separated, allowing for proper testing and production-like simulation.

The deployment will demonstrate how to configure your environments for different purposes, using Helm values files to manage the differences between dev and staging.

Why Use TLS and Separate Environments?

TLS (Transport Layer Security) ensures that the traffic between clients and servers is encrypted, which is crucial for protecting sensitive data. Having separate dev and staging environments allows for thorough testing of different configurations before moving to production, ensuring that any bugs or misconfigurations can be caught early.

Prerequisites
Before we start, make sure you have the following tools installed:

  1. Helm
  2. Minikube or you can use Kind, or Civo any one of your choice
  3. Kubectl

Step 1: Start Minikube
Start your Minikube cluster and enable Nginx ingress:

minikube start
minikube addons enable ingress
Enter fullscreen mode Exit fullscreen mode

To simulate access to the Nginx server, map the Minikube IP to custom domain names in /etc/hosts for both the dev and staging environments:

echo "$(minikube ip) noelbansikah.dev" | sudo tee -a /etc/hosts
echo "$(minikube ip) noelbansikah.com" | sudo tee -a /etc/hosts
Enter fullscreen mode Exit fullscreen mode

This will allow you to access the application using the URLs http://noelbansikah.dev and https://noelbansikah.com in your browser.

Step 2: Create the Helm Chart
We'll create a Helm chart named nginx-chart to manage our Nginx deployment. This chart will handle Kubernetes resources like Deployment, Service, Ingress, and TLS secrets.
Helm Chart Structure
Here's the structure of the Helm chart:

nginx-chart/
├── Chart.yaml
├── templates/
│   ├── deployment.yaml
│   ├── ingress.yaml
│   ├── service.yaml
│   ├── tls-secret.yaml
├── values-dev.yaml
├── values-staging.yaml
Enter fullscreen mode Exit fullscreen mode

Chart.yaml
The Chart.yaml file contains metadata about our Helm chart:

apiVersion: v2
name: nginx-chart
description: A Helm chart for deploying Nginx with self-signed TLS
version: 0.1.0
appVersion: "1.21.0"
Enter fullscreen mode Exit fullscreen mode

Step 3: Define Kubernetes Resources
We'll define Kubernetes resources for Nginx in the templates/ directory. These will include a Deployment, Service, and Ingress resource.

deployment.yaml
Defines the Nginx deployment. The replica count and image tag will be different for dev and staging environments:

#templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-portfolio
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: portfolio
  template:
    metadata:
      labels:
        app: portfolio
    spec:
      containers:
      - name: portfolio
        image: bansikah/noel-portfolio:{{ .Values.image.tag }}
        ports:
        - containerPort: 80
Enter fullscreen mode Exit fullscreen mode

service.yaml
The service will expose Nginx internally in the cluster:

#templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: {{ .Release.Name }}-portfolio-service
spec:
  selector:
    app: portfolio
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
Enter fullscreen mode Exit fullscreen mode

ingress.yaml
The ingress resource is responsible for routing external traffic to the Nginx service. For the staging environment, we'll enable TLS using a self-signed certificate:

#templates/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ .Release.Name }}-portfolio-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  {{- if .Values.ingress.tls }}
  tls:
  - hosts:
    - {{ .Values.ingress.host }}
    secretName: {{ .Release.Name }}-tls
  {{- end }}
  rules:
  - host: {{ .Values.ingress.host }}
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: {{ .Release.Name }}-portfolio-service
            port: 
              number: 80
Enter fullscreen mode Exit fullscreen mode

Step 4: Generate Self-Signed Certificates (Staging Environment)
We need to generate self-signed certificates for the staging environment using OpenSSL:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls/tls.key -out tls/tls.crt -subj "/CN=noelbansikah.com"
Enter fullscreen mode Exit fullscreen mode

Stores the generated tls.key and tls.crt in a tls/ directory inside the Helm chart folder.

tls-secret.yaml
Define the TLS secret for the staging environment:

#/templates/tls-secret.yaml
{{- if .Values.ingress.tls }}
apiVersion: v1
kind: Secret
metadata:
  name: {{ .Release.Name }}-tls
type: kubernetes.io/tls
data:
  tls.crt: {{ .Files.Get "tls/tls.crt" | b64enc }}
  tls.key: {{ .Files.Get "tls/tls.key" | b64enc }}
{{- end }}
Enter fullscreen mode Exit fullscreen mode

Step 5: Configure Values for Dev and Staging Environments
We'll use separate values files to configure the dev and staging environments.
values-dev.yaml

#values-dev.yaml
replicaCount: 1
image:
  tag: "v1"
ingress:
  host: noelbansikah.dev
  tls: false
Enter fullscreen mode Exit fullscreen mode

values-staging.yaml

#values-staging.yaml
replicaCount: 2
image:
  tag: "v1"
ingress:
  host: noelbansikah.com
  tls: true
Enter fullscreen mode Exit fullscreen mode

Step 6: Deploy Nginx Using Helm
Now that we have our chart and values files set up, we can deploy Nginx to both environments.
Dev Environment
Create a namespace for the dev environment and deploy the Helm chart using the values-dev.yaml file:

kubectl create namespace dev
helm install portfolio-dev . -f values-dev.yaml -n dev
Enter fullscreen mode Exit fullscreen mode

Staging Environment
Similarly, create a namespace for staging and deploy using the values-staging.yaml file:

kubectl create namespace staging
helm install nginx-staging . -f values-staging.yaml -n staging
Enter fullscreen mode Exit fullscreen mode

You can check the name spaces using this command

kubectl get namespaces
Enter fullscreen mode Exit fullscreen mode

you should have something like this

Image description

Step 7: Verify the Deployments
You can verify the deployments in both namespaces by checking the resources created:
Check dev environment

kubectl get all -n dev
Enter fullscreen mode Exit fullscreen mode

Check staging environment

kubectl get all -n staging
Enter fullscreen mode Exit fullscreen mode

you shoud see :

Image description

Check the ingress resources:
Dev ingress

kubectl get ingress -n dev
Enter fullscreen mode Exit fullscreen mode

Staging ingress

kubectl get ingress -n staging
Enter fullscreen mode Exit fullscreen mode

you should see:

Image description

If the TLS certificate was correctly configured, you'll also see the secret in the staging namespace:

kubectl get secret -n staging
Enter fullscreen mode Exit fullscreen mode

Image description

Step 8: Test the Deployments
To test the deployments, open your browser and access the following URLs:

Dev environment: http://noelbansikah.dev
Staging environment: https://noelbansikah.com

Test using the curl

### dev deployment
curl http://noelbansikah.dev
### staging deployment
curl -v -k https://noelbansikah.com
Enter fullscreen mode Exit fullscreen mode

Or use the Browser
If everything is comfigured correctly you should be able to see this
For Dev environment you should see

Image description

And for the staging you should see

Image description

It still shows the warning because we didn't used a well known Certificate Authority(CA.. like let's encrypt and google) which is good for production.

Note

The image used to create this application is similar to the official nginx image, you can create or customize it to suit your need there is the docker file below

Dockerfile

FROM nginx:alpine

COPY index.html /usr/share/nginx/html/
COPY styles.css /usr/share/nginx/html/

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]
Enter fullscreen mode Exit fullscreen mode

Conclusion
In this article, we walked through how to deploy Nginx with self-signed TLS in separate dev and staging environments using Helm in Minikube. We demonstrated how Helm’s values files can help manage different configurations for different environments, making it easier to test and prepare your application for production.

Always reach out if you find any difficults, Happy coding 😎😊👋

Ref:
Helm

Minikube

Kubectl

Kubernetes

Self signed

. . . . . . . . . . . . . . . . . . . . . . . . . . .