Skip to main content

Command Palette

Search for a command to run...

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

Updated
β€’4 min read
πŸ”’ Full Guide: Setting Up SSL for Monitoring, Docker, and Kubernetes (MicroK8s)

πŸ“Œ 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.

More from this blog

DevOps Journey with M Hassan

174 posts

I am writing these blogs because I recently completed a comprehensive DevOps course where I gained in-depth knowledge of the topics mentioned. As I progressed through the course, I realized the importance of having a concise and accessible resource to revise and reinforce my understanding of each topic. Therefore, I decided to create cheat sheets in the form of blog posts. These cheat sheets will not only serve as a handy reference for myself but also benefit others who are also interested in mastering DevOps concepts. By documenting each topic and providing concise explanations, I aim to create a valuable resource that simplifies complex concepts and facilitates hands-on practice. This way, I can solidify my own understanding while helping others on their DevOps journey.