# 🔒 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

```plaintext
# 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:

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

---

## ✅ Step 2: Docker WordPress SSL Setup (docker.hassandevops.site)

### 📄 Docker Compose:

```plaintext
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:

```plaintext
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:

```plaintext
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:

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

### 📄 Kubernetes Ingress with Custom TLS:

```plaintext
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
```

```plaintext
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:

```plaintext
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**](https://grafana.hassandevops.site) - Secured  
✅ [**https://cadvisor.hassandevops.site**](https://cadvisor.hassandevops.site) - Secured  
✅ [**https://docker.hassandevops.site**](https://docker.hassandevops.site) - WordPress on Docker Secured  
✅ [**https://nginx.hassandevops.site**](https://nginx.hassandevops.site) - NGINX App on K8s Secured  
✅ [**https://wordpress.hassandevops.site**](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.
