๐Ÿ”’ Full Guide: Setting Up SSL for Monitoring, Docker, and Kubernetes (MicroK8s)

Muhammad HassanMuhammad Hassan
4 min read

๐Ÿ“Œ Introduction

Securing your services with SSL is crucial for any production environment. In this blog, Iโ€™ll share how I configured SSL certificates (Let's Encrypt) across three major environments:

  1. Monitoring stack (Grafana, Prometheus, cAdvisor)

  2. Docker-based WordPress deployment

  3. Kubernetes MicroK8s deployments using Ingress


โœ… Step 1: SSL for Monitoring Stack (Grafana, Prometheus, cAdvisor)

๐Ÿ”ง Nginx Reverse Proxy Configuration

# Redirect all HTTP traffic to HTTPS
server {
    listen 80;
    server_name grafana.hassandevops.site prometheus.hassandevops.site cadvisor.hassandevops.site;

    return 301 https://$host$request_uri;
}

# Grafana HTTPS
server {
    listen 443 ssl;
    server_name grafana.hassandevops.site;

    ssl_certificate /etc/letsencrypt/live/hassandevops.site/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/hassandevops.site/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

# Prometheus HTTPS
server {
    listen 443 ssl;
    server_name prometheus.hassandevops.site;

    ssl_certificate /etc/letsencrypt/live/hassandevops.site/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/hassandevops.site/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;

    location / {
        proxy_pass http://localhost:9090;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

# cAdvisor HTTPS
server {
    listen 443 ssl;
    server_name cadvisor.hassandevops.site;

    ssl_certificate /etc/letsencrypt/live/hassandevops.site/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/hassandevops.site/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;

    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

๐Ÿ“‚ SSL Certificate Placement:

/etc/ssl/hassandevops.site/fullchain.pem
/etc/ssl/hassandevops.site/privkey.pem

โœ… Step 2: Docker WordPress SSL Setup (docker.hassandevops.site)

๐Ÿ“„ Docker Compose:

version: '3.8'

services:
  wordpress:
    image: wordpress
    restart: always
    ports:
      - 127.0.0.1:8081:80  # Only accessible from localhost
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: exampledb
    volumes:
      - wordpress:/var/www/html

  db:
    image: mysql:8.0
    restart: always
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
      MYSQL_RANDOM_ROOT_PASSWORD: '1'
    volumes:
      - db:/var/lib/mysql

volumes:
  wordpress:
  db:

๐Ÿ”ง Docker Nginx Reverse Proxy:

server {
    listen 80;
    server_name docker.hassandevops.site;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name docker.hassandevops.site;

    ssl_certificate /etc/ssl/hassandevops.site/fullchain.pem;
    ssl_certificate_key /etc/ssl/hassandevops.site/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8081;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

๐Ÿ“‚ Certificate copied via SCP:

scp -r /etc/ssl/hassandevops.site root@Docker-Server:/etc/ssl/hassandevops.site

โœ… Step 3: Kubernetes (MicroK8s) SSL via Ingress - WordPress & NGINX Apps

๐Ÿ“‚ SSL Certificate copied to K8s Server:

scp -r /etc/ssl/hassandevops.site root@K8s-Server:/etc/ssl/hassandevops.site

๐Ÿ“„ Kubernetes Ingress with Custom TLS:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-app
  template:
    metadata:
      labels:
        app: nginx-app
    spec:
      containers:
      - name: nginx-app
        image: nginx:1.14.2
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  tls:
  - hosts:
      - nginx.hassandevops.site
    secretName: hassandevops-tls
  rules:
  - host: nginx.hassandevops.site
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-service
            port:
              number: 80
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: wordpress-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        env:
        - name: MYSQL_DATABASE
          value: exampledb
        - name: MYSQL_USER
          value: exampleuser
        - name: MYSQL_PASSWORD
          value: examplepass
        - name: MYSQL_RANDOM_ROOT_PASSWORD
          value: "1"
        volumeMounts:
        - name: mysql-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-storage
        persistentVolumeClaim:
          claimName: mysql-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  selector:
    app: mysql
  ports:
    - protocol: TCP
      port: 3306
      targetPort: 3306
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wordpress
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      containers:
      - name: wordpress
        image: wordpress
        ports:
        - containerPort: 80
        env:
        - name: WORDPRESS_DB_HOST
          value: mysql
        - name: WORDPRESS_DB_USER
          value: exampleuser
        - name: WORDPRESS_DB_PASSWORD
          value: examplepass
        - name: WORDPRESS_DB_NAME
          value: exampledb
        volumeMounts:
        - name: wordpress-storage
          mountPath: /var/www/html
      volumes:
      - name: wordpress-storage
        persistentVolumeClaim:
          claimName: wordpress-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: wordpress
spec:
  selector:
    app: wordpress
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: wordpress-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  tls:
  - hosts:
      - wordpress.hassandevops.site
    secretName: hassandevops-tls
  rules:
  - host: wordpress.hassandevops.site
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: wordpress
            port:
              number: 80

๐Ÿ” TLS Secret Creation:

kubectl create secret tls nginx-tls --cert=/etc/ssl/hassandevops.site/fullchain.pem --key=/etc/ssl/hassandevops.site/privkey.pem
kubectl create secret tls wordpress-tls --cert=/etc/ssl/hassandevops.site/fullchain.pem --key=/etc/ssl/hassandevops.site/privkey.pem

๐Ÿ“ˆ Final Outcome:

โœ… https://grafana.hassandevops.site - Secured
โœ… https://cadvisor.hassandevops.site - Secured
โœ… https://docker.hassandevops.site - WordPress on Docker Secured
โœ… https://nginx.hassandevops.site - NGINX App on K8s Secured
โœ… https://wordpress.hassandevops.site - WordPress on K8s Secured


๐ŸŽฏ Conclusion:

This setup ensures your entire monitoring stack, Docker deployments, and Kubernetes services are secured with valid SSL certificates.
Proper reverse proxy configuration, TLS secret handling, and using Let's Encrypt certificates bring production-level security to your projects.

0
Subscribe to my newsletter

Read articles from Muhammad Hassan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Muhammad Hassan
Muhammad Hassan

Hey there! I'm currently working as an Associate DevOps Engineer, and I'm diving into popular DevOps tools like Azure Devops,Linux, Docker, Kubernetes,Terraform and Ansible. I'm also on the learning track with AWS certifications to amp up my cloud game. If you're into tech collaborations and exploring new horizons, let's connect!