diff --git a/roles/kubernetes-apps/helm/defaults/main.yml b/roles/kubernetes-apps/helm/defaults/main.yml
index 15e26596ae2866cd1246163c1401465771d554dd..5c6396b57ba7af66c2b7f3751bc389c0395841a3 100644
--- a/roles/kubernetes-apps/helm/defaults/main.yml
+++ b/roles/kubernetes-apps/helm/defaults/main.yml
@@ -10,6 +10,24 @@ helm_deployment_type: host
 # Do not download the local repository cache on helm init
 helm_skip_refresh: false
 
+# Secure Tiller installation with TLS
+tiller_enable_tls: false
+helm_config_dir: "{{ kube_config_dir }}/helm"
+helm_script_dir: "{{ bin_dir }}/helm-scripts"
+
+# Store tiller release information as Secret instead of a ConfigMap
+tiller_secure_release_info: false
+
+# Where private root key will be secured for TLS
+helm_tiller_cert_dir: "{{ helm_config_dir }}/ssl"
+tiller_tls_cert: "{{ helm_tiller_cert_dir }}/tiller.pem"
+tiller_tls_key: "{{ helm_tiller_cert_dir }}/tiller-key.pem"
+tiller_tls_ca_cert: "{{ helm_tiller_cert_dir }}/ca.pem"
+
+# Permission owner and group for helm client cert. Will be dependent on the helm_home_dir
+helm_cert_group: root
+helm_cert_owner: root
+
 # Set URL for stable repository
 # helm_stable_repo_url: "https://kubernetes-charts.storage.googleapis.com"
 
diff --git a/roles/kubernetes-apps/helm/files/helm-make-ssl.sh b/roles/kubernetes-apps/helm/files/helm-make-ssl.sh
new file mode 100644
index 0000000000000000000000000000000000000000..c4c9b060a69bd8cbccdabb17101060de68e7d56b
--- /dev/null
+++ b/roles/kubernetes-apps/helm/files/helm-make-ssl.sh
@@ -0,0 +1,76 @@
+#!/bin/bash
+
+set -o errexit
+set -o pipefail
+
+usage()
+{
+    cat << EOF
+Create self signed certificates
+
+Usage : $(basename $0) -f <config> [-d <ssldir>]
+      -h | --help         : Show this message
+      -e | --helm-home      : Helm home directory
+      -d | --ssldir       : Directory where the certificates will be installed
+EOF
+}
+
+# Options parsing
+while (($#)); do
+    case "$1" in
+        -h | --help)   usage;   exit 0;;
+        -e | --helm-home) HELM_HOME="${2}"; shift 2;;
+        -d | --ssldir) SSLDIR="${2}"; shift 2;;
+        *)
+            usage
+            echo "ERROR : Unknown option"
+            exit 3
+        ;;
+    esac
+done
+
+if [ -z ${SSLDIR} ]; then
+    SSLDIR="/etc/kubernetes/helm/ssl"
+fi
+
+tmpdir=$(mktemp -d /tmp/helm_cacert.XXXXXX)
+trap 'rm -rf "${tmpdir}"' EXIT
+cd "${tmpdir}"
+
+mkdir -p "${SSLDIR}"
+
+# Root CA
+if [ -e "$SSLDIR/ca-key.pem" ]; then
+    # Reuse existing CA
+    cp $SSLDIR/{ca.pem,ca-key.pem} .
+else
+    openssl genrsa -out ca-key.pem 4096 > /dev/null 2>&1
+    openssl req -x509 -new -nodes -key ca-key.pem -days 36500 -out ca.pem -subj "/CN=tiller-ca" > /dev/null 2>&1
+fi
+
+gen_key_and_cert() {
+    local name=$1
+    local subject=$2
+    openssl genrsa -out ${name}-key.pem 4096 > /dev/null 2>&1
+    openssl req -new -key ${name}-key.pem -sha256 -out ${name}.csr -subj "${subject}" > /dev/null 2>&1
+    openssl x509 -req -in ${name}.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out ${name}.pem -days 36500 > /dev/null 2>&1
+}
+
+#Generate cert and key for Tiller if they don't exist
+if ! [ -e "$SSLDIR/tiller.pem" ]; then
+    gen_key_and_cert "tiller" "/CN=tiller-server"
+fi
+
+#Generate cert and key for Helm client if they dont exist
+if ! [ -e "$SSLDIR/helm.pem" ]; then
+    gen_key_and_cert "helm" "/CN=helm-client"
+fi
+
+# Secure certs to first master
+mv *.pem ${SSLDIR}/
+
+# Install Helm client certs to first master
+# Copy using Helm default names for convenience
+cp ${SSLDIR}/ca.pem ${HELM_HOME}/ca.pem
+cp ${SSLDIR}/helm.pem ${HELM_HOME}/cert.pem
+cp ${SSLDIR}/helm-key.pem ${HELM_HOME}/key.pem
diff --git a/roles/kubernetes-apps/helm/tasks/gen_helm_tiller_certs.yml b/roles/kubernetes-apps/helm/tasks/gen_helm_tiller_certs.yml
new file mode 100644
index 0000000000000000000000000000000000000000..86a0c74515cd0cdacad835195cb2f6aa33b7eeb1
--- /dev/null
+++ b/roles/kubernetes-apps/helm/tasks/gen_helm_tiller_certs.yml
@@ -0,0 +1,107 @@
+---
+- name: "Gen_helm_tiller_certs | Create helm config directory (on {{groups['kube-master'][0]}})"
+  run_once: yes
+  delegate_to: "{{groups['kube-master'][0]}}"
+  file:
+    path: "{{ helm_config_dir }}"
+    state: directory
+    owner: kube
+
+- name: "Gen_helm_tiller_certs | Create helm script directory (on {{groups['kube-master'][0]}})"
+  run_once: yes
+  delegate_to: "{{groups['kube-master'][0]}}"
+  file:
+    path: "{{ helm_script_dir }}"
+    state: directory
+    owner: kube
+
+- name: Gen_helm_tiller_certs | Copy certs generation script
+  run_once: yes
+  delegate_to: "{{groups['kube-master'][0]}}"
+  copy:
+    src: "helm-make-ssl.sh"
+    dest: "{{ helm_script_dir }}/helm-make-ssl.sh"
+    mode: 0700
+
+- name: "Check_helm_certs | check if helm client certs have already been generated on first master (on {{groups['kube-master'][0]}})"
+  find:
+    paths: "{{ helm_home_dir }}"
+    patterns: "*.pem"
+    get_checksum: true
+  delegate_to: "{{groups['kube-master'][0]}}"
+  register: helmcert_master
+  run_once: true
+
+- name: Gen_helm_tiller_certs | run cert generation script
+  run_once: yes
+  delegate_to: "{{groups['kube-master'][0]}}"
+  command: "{{ helm_script_dir }}/helm-make-ssl.sh -e {{ helm_home_dir }} -d {{ helm_tiller_cert_dir }}"
+
+- set_fact:
+    helm_client_certs: ['ca.pem', 'cert.pem', 'key.pem']
+
+- name: "Check_helm_client_certs | check if a cert already exists on master node"
+  find:
+    paths: "{{ helm_home_dir }}"
+    patterns: "*.pem"
+    get_checksum: true
+  register: helmcert_node
+  when: inventory_hostname != groups['kube-master'][0]
+
+- name: "Check_helm_client_certs | Set 'sync_helm_certs' to true on masters"
+  set_fact:
+    sync_helm_certs: true
+  when: inventory_hostname != groups['kube-master'][0] and
+      (not item in helmcert_node.files | map(attribute='path') | map("basename") | list or
+      helmcert_node.files | selectattr("path", "equalto", "{{ helm_home_dir }}/{{ item }}") | map(attribute="checksum")|first|default('') != helmcert_master.files | selectattr("path", "equalto", "{{ helm_home_dir }}/{{ item }}") | map(attribute="checksum")|first|default(''))
+  with_items:
+    - "{{ helm_client_certs }}"
+
+- name: Gen_helm_tiller_certs | Gather helm client certs
+  shell: "tar cfz - -C {{ helm_home_dir }} -T /dev/stdin <<< {{ helm_client_certs|join(' ') }} | base64 --wrap=0"
+  args:
+    executable: /bin/bash
+  no_log: true
+  register: helm_client_cert_data
+  check_mode: no
+  delegate_to: "{{groups['kube-master'][0]}}"
+  when: sync_helm_certs|default(false) and inventory_hostname != groups['kube-master'][0]
+
+- name: Gen_helm_tiller_certs | Use tempfile for unpacking certs on masters
+  tempfile:
+    state: file
+    path: /tmp
+    prefix: helmcertsXXXXX
+    suffix: tar.gz
+  register: helm_cert_tempfile
+  when: sync_helm_certs|default(false) and inventory_hostname != groups['kube-master'][0]
+
+- name: Gen_helm_tiller_certs | Write helm client certs to tempfile
+  copy:
+    content: "{{helm_client_cert_data.stdout}}"
+    dest: "{{helm_cert_tempfile.path}}"
+    owner: root
+    mode: "0600"
+  when: sync_helm_certs|default(false) and inventory_hostname != groups['kube-master'][0]
+
+- name: Gen_helm_tiller_certs | Unpack helm certs on masters
+  shell: "base64 -d < {{ helm_cert_tempfile.path }} | tar xz -C {{ helm_home_dir }}"
+  no_log: true
+  changed_when: false
+  check_mode: no
+  when: sync_helm_certs|default(false) and inventory_hostname != groups['kube-master'][0]
+
+- name: Gen_helm_tiller_certs | Cleanup tempfile on masters
+  file:
+    path: "{{helm_cert_tempfile.path}}"
+    state: absent
+  when: sync_helm_certs|default(false) and inventory_hostname != groups['kube-master'][0]
+
+- name: Gen_certs | check certificate permissions
+  file:
+    path: "{{ helm_home_dir }}"
+    group: "{{ helm_cert_group }}"
+    state: directory
+    owner: "{{ helm_cert_owner }}"
+    mode: "u=rwX,g-rwx,o-rwx"
+    recurse: yes
diff --git a/roles/kubernetes-apps/helm/tasks/main.yml b/roles/kubernetes-apps/helm/tasks/main.yml
index 158eff5ca075d9d6665a440e251ae772a4fb0e37..bae058f2648bb799d17bb6e32dbb412cfec734a7 100644
--- a/roles/kubernetes-apps/helm/tasks/main.yml
+++ b/roles/kubernetes-apps/helm/tasks/main.yml
@@ -27,6 +27,11 @@
   with_items: "{{ manifests.results }}"
   when: dns_mode != 'none' and inventory_hostname == groups['kube-master'][0]
 
+# Generate necessary certs for securing Helm and Tiller connection with TLS
+- name: Helm | Set up TLS
+  include_tasks: "gen_helm_tiller_certs.yml"
+  when: tiller_enable_tls
+
 - name: Helm | Install/upgrade helm
   command: >
     {{ bin_dir }}/helm init --upgrade --tiller-image={{ tiller_image_repo }}:{{ tiller_image_tag }} --tiller-namespace={{ tiller_namespace }}
@@ -36,8 +41,11 @@
     {% if tiller_node_selectors is defined %} --node-selectors {{ tiller_node_selectors }}{% endif %}
     {% if tiller_override is defined %} --override {{ tiller_override }}{% endif %}
     {% if tiller_max_history is defined %} --history-max={{ tiller_max_history }}{% endif %}
+    {% if tiller_enable_tls %} --tiller-tls --tiller-tls-verify --tiller-tls-cert={{ tiller_tls_cert }} --tiller-tls-key={{ tiller_tls_key }} --tls-ca-cert={{ tiller_tls_ca_cert }} {% endif %}
+    {% if tiller_secure_release_info %} --override 'spec.template.spec.containers[0].command'='{/tiller,--storage=secret}' {% endif %}
   register: install_helm
   changed_when: false
+  environment: "{{proxy_env}}"
 
 # FIXME: https://github.com/helm/helm/issues/4063
 - name: Helm | Force apply tiller overrides if necessary
@@ -49,9 +57,12 @@
     {% if tiller_node_selectors is defined %} --node-selectors {{ tiller_node_selectors }}{% endif %}
     {% if tiller_override is defined %} --override {{ tiller_override }}{% endif %}
     {% if tiller_max_history is defined %} --history-max={{ tiller_max_history }}{% endif %}
+    {% if tiller_enable_tls %} --tiller-tls --tiller-tls-verify --tiller-tls-cert={{ tiller_tls_cert }} --tiller-tls-key={{ tiller_tls_key }} --tls-ca-cert={{ tiller_tls_ca_cert }} {% endif %}
+    {% if tiller_secure_release_info %} --override 'spec.template.spec.containers[0].command'='{/tiller,--storage=secret}' {% endif %}
     | kubectl apply -f -
   changed_when: false
   when: tiller_override is defined
+  environment: "{{proxy_env}}"
 
 - name: Helm | Set up bash completion
   shell: "umask 022 && {{ bin_dir }}/helm completion bash >/etc/bash_completion.d/helm.sh"