Deploying Secure HTTPS NGINX in Kubernetes

by Anish

Posted on Tuesday August 15, 2018



This sample chapter extracted from the book, Kubernetes for DevOps .

Get this book on Just $9 or Ask Author for Discount

In this article we will learn how to deploy nginix with modern TLS versions and Cipher suites in Kubernetes. This lab is tested on the this kubernetes versions

This example creates a nginx https service useful in verifying proof of concept, keys, secrets, configmap, and end-to-end https service creation in kubernetes

  • Definition of Modern TLS Nginx Deployment : A modern Nginx webservers should be free of these Vulnerability and only support TLS1.2

    • CCS injection vulnerability
    • renegotiation vulnerabilities
    • CRIME vulnerability
    • BREACH vulnerability
    • POODLE (SSL) vulnerability
    • FREAK vulnerability
    • BEAST vulnerability
    • LOGJAM vulnerability

  • nginx certs and Keys: First Generate self signed certificate and private keys, if you have already certificate and keys, then Ignore this step
     openssl req -newkey rsa:2048 -nodes -keyout nginx.key -x509 -days 365 -out nginx.crt 
  • Create Secrets
    In the next steps created secrets for the x.509 certificate and the private key

         kubectl create secret generic nginx-certs-keys --from-file=./nginx.crt --from-file=./nginx.key
        secret/nginx-certs-keys created
  • View Secrets

        kubectl describe secrets/nginx-certs-keys
      Name:         nginx-certs-keys
      Namespace:    default
      Labels:       <none>
      Annotations:  <none>
      Type:  Opaque
      nginx.crt:  1294 bytes
      nginx.key:  1675 bytes 
  • Define the Modern TLS nginx configuration file in the


       server {
              listen 80 default_server;
              listen [::]:80 default_server ipv6only=on;
              listen 443 ssl;
              root /usr/share/nginx/html;
              index index.html;
          server_name localhost;
          ssl_certificate /etc/nginx/ssl/nginx.crt;
          ssl_certificate_key /etc/nginx/ssl/nginx.key; 
          ssl_session_timeout 1d;
          ssl_session_cache shared:SSL:50m;
          ssl_session_tickets off;
          # modern configuration. tweak to your needs.
          ssl_protocols TLSv1.2;
          ssl_prefer_server_ciphers on; 
          # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
          add_header Strict-Transport-Security max-age=15768000;
          # OCSP Stapling ---
          # fetch OCSP records from URL in ssl_certificate and cache them
          ssl_stapling on;
          ssl_stapling_verify on;
          location / {
                  try_files $uri $uri/ =404;
  • The inotifywait linux command which efficiently waits for changes to files using Linux's inotify(7) interface. It is suitable for waiting for changes to files from shell scripts. It can either exit once an event occurs, or continually execute and output events as they occur

    The file: This will relaod the nginx configuration whenever any change in default.conf detected. This is done by inotifywait

    nginx "[email protected]"
    		oldcksum=`cksum /etc/nginx/conf.d/default.conf`
    		inotifywait -e modify,move,create,delete -mr --timefmt '%d/%m/%y %H:%M' --format '%T' \
    		/etc/nginx/conf.d/ | while read date time; do
    			newcksum=`cksum /etc/nginx/conf.d/default.conf`
    			if [ "$newcksum" != "$oldcksum" ]; then
    				echo "At ${time} on ${date}, config file update detected."
    				nginx -s reload
  • ConfigMaps allow you to decouple configuration artifacts from image content to keep containerized applications portable. This article provides a examples that demonstrate how to create ConfigMaps and configure Pods using data stored in ConfigMaps for nginx

    Create configmap for nginx default.conf file

       kubectl create configmap nginxconfigmap --from-file=default.conf
    configmap/nginxconfigmap created
  • Verify the configmap file

       kubectl describe  configmap nginxconfigmap
  • Here is the configuration file for the nginx-app.yaml deployment.

    When referencing a configMap object, you can simply provide its name in the volume to reference it

    The nginxconfigmap ConfigMap is mounted as a volume, and all contents stored in its entry are mounted into the Pod at path "/etc/nginx/conf.d". Note that this path is derived from the volume’s mountPath and the path keyed with configmap-volume

    The nginx-certs-keys secret is mounted as a volume, and all contents stored in its entry are mounted into the Pod at path "/etc/nginx/ssl". Note that this path is derived from the volume’s mountPath and the path keyed with secret-volume

      apiVersion: v1
    kind: Service
      name: nginxsvc
        app: nginx
      type: NodePort
      - port: 80
        protocol: TCP
        name: http
      - port: 443
        protocol: TCP
        name: https
        app: nginx
    apiVersion: v1
    kind: ReplicationController
      name: my-nginx
      replicas: 1
            app: nginx
          - name: secret-volume
               secretName: nginx-certs-keys 
          - name: configmap-volume
              name: nginxconfigmap 
          - name: nginxhttps
            image: ymqytw/nginxhttps:1.5
            command: ["/home/"]
            - containerPort: 443
            - containerPort: 80
                path: /index.html
                port: 80
              initialDelaySeconds: 30
              timeoutSeconds: 1
            - mountPath: /etc/nginx/ssl
              name: secret-volume
            - mountPath: /etc/nginx/conf.d
              name: configmap-volume 
  • Create the service and a replication controller using the configuration in nginx-app.yaml.

       kubectl create -f nginx-app.yml
      service/nginxsvc created
      replicationcontroller/my-nginx created
  • find the node port that Kubernetes is using for http and https traffic using the command

    kubectl get service nginxsvc -o json

  •      "spec": {
                "clusterIP": "",
                "externalTrafficPolicy": "Cluster",
                "ports": [
                        "name": "http",
                        "nodePort": 32210,
                        "port": 80,
                        "protocol": "TCP",
                        "targetPort": 80
                        "name": "https",
                        "nodePort": 30115,
                        "port": 443,
                        "protocol": "TCP",
                        "targetPort": 443 
  • Optionally you can check the nodeport in the Master node

       netstat -aonp | grep LISTEN  | grep kube-proxy
      tcp        0      0*               LISTEN      9087/kube-proxy  off (0.00/0/0)
      tcp6       0      0 :::30115                :::*                    LISTEN      9087/kube-proxy  off (0.00/0/0) 
      tcp6       0      0 :::10256                :::*                    LISTEN      9087/kube-proxy  off (0.00/0/0)
      tcp6       0      0 :::32210                :::*                    LISTEN      9087/kube-proxy  off (0.00/0/0) 
  • Now your service is up and running . use your browser or type the following commands.

        curl  -k  https://<node-ip>:<nodeport>

    Fetching the HTTP header Information to verify the server is up and serving the file as expected

       curl  -kI
      HTTP/1.1 200 OK
      Server: nginx/1.11.3
      Date: Tue, 14 Aug 2018 10:12:02 GMT
      Content-Type: text/html
      Content-Length: 804
      Last-Modified: Fri, 26 Aug 2016 20:22:28 GMT
      Connection: keep-alive
      ETag: "57c0a504-324"
      Accept-Ranges: bytes
  • Changes to nginxsvc doesn't requires any restart of the pod, for example remove the port 80 from the deployment, then remove the http port 80

    kubectl edit service/nginxsvc
    port: 80
                    protocol: TCP
                    name: http

    then find the node port that Kubernetes is using, you will be seeing only https port

    kubectl get service nginxsvc -o json
            "ports": [
                        "name": "https",
                        "nodePort": 30286,
                        "port": 443,
                        "protocol": "TCP",
                        "targetPort": 443
  • Update in configMap : This will be needed when there is any change in nginx default.conf file. This can be done through

       kubectl create configmap nginxconfigmap --from-file=default.conf -o yaml --dry-run | kubectl apply -f -
      configmap/nginxconfigmap configured

    In this case the app requires to be reloaded, or destroy the pod and recreate the pod

       kubectl replace --force -f  nginx-app.yml 

    Thats the purpose of the file to reload the nginx configuration if any change detected

Thanku for reading !!! Give a Share for Support

Asking for donation sound bad to me, so i'm raising fund from The Modern Cryptography CookBook for Just $9. Leanpub books Discount coupon first 100 reader. No hurry read the sample chapters here then decide.

Alternatively to support you can buy My all four Cryptography book Just $10.99

  • The Modern Cryptography Book.
  • Go lang Cryptography for developers
  • Python Cryptography
  • Cryptography for JavaScript Developer

python Cryptography Topics
For Coffee/ Beer/ Amazon Bill and further development of the project Support by Purchasing, The Modern Cryptography CookBook for Just $9 Coupon Price

Kubernetes for DevOps

Cryptography for Python Developers

Cryptography for JavaScript Developers

Go lang ryptography for Developers