diff --git a/charts/jupyter-hub-customizations/Chart.yaml b/charts/jupyter-hub-customizations/Chart.yaml
index 0cf0103b2a38511eeadd15eec0de6aa5d788e729..969ea4fa089d683023ef8b1eaa4700a9328d646c 100644
--- a/charts/jupyter-hub-customizations/Chart.yaml
+++ b/charts/jupyter-hub-customizations/Chart.yaml
@@ -15,7 +15,7 @@ type: application
 # This is the chart version. This version number should be incremented each time you make changes
 # to the chart and its templates, including the app version.
 # Versions are expected to follow Semantic Versioning (https://semver.org/)
-version: 0.12.8
+version: 0.13.0
 
 # This is the version number of the application being deployed. This version number should be
 # incremented each time you make changes to the application. Versions are not expected to
diff --git a/charts/jupyter-hub-customizations/templates/configmap_check_frontend_files.yaml b/charts/jupyter-hub-customizations/templates/configmap_check_frontend_files.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..92121461accabb48ea0fbc9427d6b0c718fbb5e5
--- /dev/null
+++ b/charts/jupyter-hub-customizations/templates/configmap_check_frontend_files.yaml
@@ -0,0 +1,125 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ .Values.global.name }}-check-frontend-files
+  labels:
+    {{- include "jupyter-hub-customizations.labels" . | nindent 4 }}
+data:
+  run.sh: |
+    #!/bin/bash
+
+    # Variables used for git clone commands
+    SHARE_BASE_DIR="/tmp/share_base"
+    SHARE_OVERLAYS_DIR="/tmp/share_overlays"
+
+    # Prepare base + overlays in this directory, before moving it to /mnt/shared-data
+    SHARE_COPY_DIR="/tmp/share_copy"
+
+    # In this directory JupyterHub will look for the template files
+    SHARE_JHUB_DIR="/mnt/shared-data/share/jupyterhub"
+    mkdir -p ${SHARE_JHUB_DIR}
+
+    # In this directory nginx will look for the static files
+    SHARE_NGINX_DIR="/mnt/shared-data/static-files"
+    mkdir -p ${SHARE_NGINX_DIR}
+
+    # create temporary folders
+    mkdir -p $(dirname ${SHARE_BASE_DIR})
+
+    if [[ -e ${SHARE_BASE_DIR} ]]; then
+        rm -rf ${SHARE_BASE_DIR}
+    fi
+
+    cd $(dirname ${SHARE_BASE_DIR})
+    git clone --single-branch --branch ${SHARE_BASE_GIT_BRANCH} https://${SHARE_BASE_GIT_USERNAME}:${SHARE_BASE_GIT_PASSWORD}@${SHARE_BASE_GIT_REPO#"https://"} $(basename ${SHARE_BASE_DIR})
+
+    if [[ -n ${SHARE_OVERLAYS_GIT_REPO} ]]; then
+        mkdir -p $(dirname ${SHARE_OVERLAYS_DIR})
+
+        if [[ -e ${SHARE_OVERLAYS_DIR} ]]; then
+            rm -rf ${SHARE_OVERLAYS_DIR}
+        fi
+
+        cd $(dirname ${SHARE_OVERLAYS_DIR})
+        if [[ -n ${SHARE_OVERLAYS_GIT_USERNAME} && -n ${SHARE_OVERLAYS_GIT_PASSWORD} ]]; then
+            git clone --single-branch --branch ${SHARE_OVERLAYS_GIT_BRANCH} https://${SHARE_OVERLAYS_GIT_USERNAME}:${SHARE_OVERLAYS_GIT_PASSWORD}@${SHARE_OVERLAYS_GIT_REPO#"https://"} $(basename ${SHARE_OVERLAYS_DIR})
+        else
+            git clone --single-branch --branch ${SHARE_OVERLAYS_GIT_BRANCH} ${SHARE_OVERLAYS_GIT_REPO} $(basename ${SHARE_OVERLAYS_DIR})
+        fi
+    fi
+
+    git config --global pull.ff only
+
+
+    update() {
+      echo "$(date) - Check for updates in templates and static files"
+
+      if [[ ${1} == "force" ]]; then
+          FORCE=1
+      else
+          FORCE=0
+      fi
+
+      # Check if base templates got an update
+
+      check_git_update() {
+          # Check for changes on remote origin
+          cd ${1}
+          git fetch -q
+          test "$(git rev-parse HEAD)" == "$(git rev-parse @{u})"
+          echo $?
+      }
+
+      SHARE_BASE_UPDATED=$(check_git_update ${SHARE_BASE_DIR})
+      if [[ -n ${SHARE_OVERLAYS_GIT_REPO} ]]; then
+          SHARE_OVERLAYS_UPDATED=$(check_git_update ${SHARE_OVERLAYS_DIR})
+      else
+          SHARE_OVERLAYS_UPDATED=0
+      fi
+
+      # If one was updated, we have to prepare a new directory
+      if [[ ${SHARE_BASE_UPDATED} -eq 1 || ${SHARE_OVERLAYS_UPDATED} -eq 1 || ${FORCE} -eq 1 ]]; then
+          echo "$(date) - Shared files update (Base: ${SHARE_BASE_UPDATED} , Overlays: ${SHARE_OVERLAYS_UPDATED}, Force ${FORCE})"
+          mkdir -p ${SHARE_COPY_DIR}
+          cd ${SHARE_BASE_DIR}
+          git pull origin ${SHARE_BASE_GIT_BRANCH}
+          cp -r ${SHARE_BASE_DIR}/* ${SHARE_COPY_DIR}/.
+
+          if [[ ${SHARE_OVERLAYS_UPDATED} -eq 1 || (${FORCE} -eq 1 && -d ${SHARE_OVERLAYS_DIR}) ]]; then
+              cd ${SHARE_OVERLAYS_DIR}
+              git pull origin ${SHARE_OVERLAYS_GIT_BRANCH}
+
+              copy_overlays_subdir() {
+                  if [[ -d ${SHARE_OVERLAYS_DIR}/${1} ]]; then
+                      if [[ ! -d ${SHARE_COPY_DIR}/${1} ]]; then
+                          mkdir -p ${SHARE_COPY_DIR}/${1}
+                      fi
+                      cp -r ${SHARE_OVERLAYS_DIR}/${1}/* ${SHARE_COPY_DIR}/${1}/.
+                  fi
+              }
+              copy_overlays_subdir templates
+              copy_overlays_subdir static
+
+          fi
+          # Remove footer.systems images. These are managed by check_incidents in antoher script.
+          if [[ -d ${SHARE_COPY_DIR}/static/images/footer/systems ]]; then
+              rm -r ${SHARE_COPY_DIR}/static/images/footer/systems/*
+          fi
+
+          chown -R 1000:1000 ${SHARE_COPY_DIR}
+          cp -r ${SHARE_COPY_DIR}/* ${SHARE_JHUB_DIR}/.
+          cp -r ${SHARE_COPY_DIR}/static/* ${SHARE_NGINX_DIR}/.
+          chown -R 1000:1000 ${SHARE_JHUB_DIR}
+          chown -R 1000:1000 ${SHARE_NGINX_DIR}
+          rm -rf ${SHARE_COPY_DIR}
+      fi
+    }
+
+    update force
+
+    if [[ ! ${1} == "once" ]]; then
+        while true; do
+            sleep 60
+            update
+        done
+    fi
diff --git a/charts/jupyter-hub-customizations/templates/configmap_init_script.yaml b/charts/jupyter-hub-customizations/templates/configmap_init_script.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..00d152c56a507016e08e40091cdbf3d57ec427ae
--- /dev/null
+++ b/charts/jupyter-hub-customizations/templates/configmap_init_script.yaml
@@ -0,0 +1,60 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ .Values.global.name }}-init-script
+  labels:
+    {{- include "jupyter-hub-customizations.labels" . | nindent 4 }}
+data:
+  run.sh: |
+    #!/bin/bash
+
+    preparation() {
+        # Internal ssl variables
+        INTERNAL_SSL_SRC="/mnt/internal_ssl/*"
+        INTERNAL_SSL_DEST="/mnt/persistent/internal-ssl"
+    }
+
+    internal_ssl_dir() {
+        # Take the given internal_ssl (mounted via secret)
+        # and prepare it for JupyterHub in a persistent storage
+        mkdir -p ${INTERNAL_SSL_DEST}
+        for f in ${INTERNAL_SSL_SRC}; do
+            filename=$(basename $f)
+            if [[ ${filename} = certipy.json ]]; then
+                cp $f ${INTERNAL_SSL_DEST}/${filename}
+            elif [[ ! ${filename} = *_trust.crt ]]; then
+                dirname=${filename%%_*}
+                mkdir -p ${INTERNAL_SSL_DEST}/${dirname}
+                filename=${filename##*_}
+                cp $f ${INTERNAL_SSL_DEST}/${dirname}/${filename}
+            else
+                cp $f ${INTERNAL_SSL_DEST}/${filename}
+            fi
+        done
+    }
+
+    twofa_setup() {
+        # Fix twofa ssh keys permissions
+        if [[ -f /mnt/twofa_keypair/..data/twofa ]]; then
+            mkdir -p /mnt/shared-data/twofa
+            cp -r /mnt/twofa_keypair/..data/twofa /mnt/shared-data/twofa/twofa
+            chmod 400 /mnt/shared-data/twofa/twofa
+        fi
+
+        if [[ -f /mnt/twofa_remove_keypair/..data/twofa ]]; then
+            mkdir -p /mnt/shared-data/twofa
+            cp -r /mnt/twofa_remove_keypair/..data/twofa /mnt/shared-data/twofa/twofaremove
+            chmod 400 /mnt/shared-data/twofa/twofaremove
+        fi
+    }
+
+    wrap_up() {
+        # set ownership
+        chown -R 1000:100 /mnt/shared-data
+        chown -R 1000:100 /mnt/persistent
+    }
+
+    preparation
+    internal_ssl_dir
+    twofa_setup
+    wrap_up
diff --git a/charts/jupyter-hub-customizations/templates/configmap_sidecar_nginx.yaml b/charts/jupyter-hub-customizations/templates/configmap_sidecar_nginx.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..0655ab514df3ea9cfeae141c95d374238a4de198
--- /dev/null
+++ b/charts/jupyter-hub-customizations/templates/configmap_sidecar_nginx.yaml
@@ -0,0 +1,90 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ .Values.global.name }}-sidecar-nginx-config
+  labels:
+    {{- include "jupyter-hub-customizations.labels" . | nindent 4 }}
+data:
+  nginx.conf: |
+    user  nginx;
+    worker_processes  auto;
+
+    error_log  /var/log/nginx/error.log notice;
+    pid        /var/run/nginx.pid;
+
+
+    events {
+        worker_connections  1024;
+    }
+
+
+    http {
+        include       /etc/nginx/mime.types;
+        default_type  text/html;
+
+        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
+                          '$status $body_bytes_sent "$http_referer" '
+                          '"$http_user_agent" "$http_x_forwarded_for"';
+
+        access_log  /var/log/nginx/access.log  main;
+
+        sendfile        on;
+        #tcp_nopush     on;
+
+        keepalive_timeout  65;
+
+        #gzip  on;
+
+        include /etc/nginx/conf.d/*.conf;
+    }
+  jupyter.conf: |
+    server {
+        listen 8070 default_server;
+        server_name  _;
+
+        access_log  /var/log/nginx/host.access.log  main;
+
+        location ^~ /hub/static {
+            alias  /mnt/shared-data/share/jupyterhub/static/;
+            # root   /usr/share/nginx/html;
+            # index  index.html index.htm;
+        }
+
+        location / {
+            alias  /mnt/shared-data/share/jupyterhub/static/redirects/;
+            # root   /usr/share/nginx/html;
+            # index  index.html index.htm;
+        }
+
+        #error_page  404              /404.html;
+
+        # redirect server error pages to the static page /50x.html
+        #
+        error_page   500 502 503 504  /50x.html;
+        location = /50x.html {
+            root   /usr/share/nginx/html;
+        }
+
+        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
+        #
+        #location ~ \.php$ {
+        #    proxy_pass   http://127.0.0.1;
+        #}
+
+        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
+        #
+        #location ~ \.php$ {
+        #    root           html;
+        #    fastcgi_pass   127.0.0.1:9000;
+        #    fastcgi_index  index.php;
+        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
+        #    include        fastcgi_params;
+        #}
+
+        # deny access to .htaccess files, if Apache's document root
+        # concurs with nginx's one
+        #
+        #location ~ /\.ht {
+        #    deny  all;
+        #}
+    }
diff --git a/charts/jupyter-hub-customizations/templates/configmap_values.yaml b/charts/jupyter-hub-customizations/templates/configmap_values.yaml
index de6a3e0b25a103fae0095d47caa4b58341d1fac6..1c023c96311a254ab91770e3b108950bd857c999 100644
--- a/charts/jupyter-hub-customizations/templates/configmap_values.yaml
+++ b/charts/jupyter-hub-customizations/templates/configmap_values.yaml
@@ -39,6 +39,114 @@ data:
           secretKeyRef:
             name: {{ .Values.oauthSecret }}
             key: client_secret
+      extraVolumes:
+        - name: shared-data
+          emptyDir: {}
+        - name: init-script
+          configMap:
+            defaultMode: 400
+            name: {{ .Values.global.name }}-init-script
+        - name: check-frontend-files
+          configMap:
+            defaultMode: 400
+            name: {{ .Values.global.name }}-check-frontend-files
+        - name: sidecar-nginx-config
+          configMap:
+            defaultMode: 400
+            name: {{ .Values.global.name }}-sidecar-nginx-config
+        - name: reservation-keypair
+          secret:
+            secretName: reservation-keypair
+        - name: tunnel-certs
+          secret:
+            secretName: tunnel-certs-public
+            items:
+              - key: tls.ca
+                path: ca.pem
+        - name: twofa-keypair
+          secret:
+            secretName: twofa-keypair
+            items:
+              - key: ssh-privatekey
+                path: twofa
+                mode: 0400
+        - name: twofa-remove-keypair
+          secret:
+            secretName: twofa-remove-keypair
+            items:
+              - key: ssh-privatekey
+                path: twofa
+                mode: 0400
+        - name: tz-config
+          hostPath:
+            path: /usr/share/zoneinfo/Europe/Berlin
+      initContainers:
+        - name: prepare-shared-data
+          image: alpine:3.18
+          imagePullPolicy: Always
+          command: ["/bin/sh"]
+          args:
+            - -c
+            - >-
+              apk add bash git &&
+              /bin/bash /mnt/init_script/..data/run.sh &&
+              /bin/bash /mnt/check_frontend_files/..data/run.sh once &&
+              mkdir -p /mnt/shared-data/reservation_key &&
+              cp -rp /mnt/reservation-keypair/..data/* /mnt/shared-data/reservation_key/. &&
+              chown 1000:1000 -R /mnt/shared-data/reservation_key &&
+              chmod 400 /mnt/shared-data/reservation_key/*
+          volumeMounts:
+            - name: shared-data
+              mountPath: /mnt/shared-data
+            - name: persistent
+              mountPath: /mnt/persistent
+            - name: internal-ssl
+              mountPath: /mnt/internal_ssl
+              readOnly: true
+            - name: reservation-keypair
+              mountPath: /mnt/reservation-keypair
+            - name: init-script
+              mountPath: /mnt/init_script
+            - name: check-frontend-files
+              mountPath: /mnt/check_frontend_files
+            - name: twofa-keypair
+              mountPath: /mnt/twofa_keypair
+            - name: twofa-remove-keypair
+              mountPath: /mnt/twofa_remove_keypair
+      extraContainers:
+        - name: check-frontend-files
+          image: alpine:3.18
+          imagePullPolicy: Always
+          command: ["/bin/sh"]
+          args:
+            - -c
+            - >-
+                apk add bash git &&
+                /bin/bash /mnt/check_frontend_files/..data/run.sh
+          volumeMounts:
+            - name: shared-data
+              mountPath: /mnt/shared-data
+            - name: check-frontend-files
+              mountPath: /mnt/check_frontend_files
+            - name: tz-config
+              mountPath: /etc/localtime
+        - name: sidecar-nginx
+          image: nginx:1.25.3-alpine3.18-slim
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 8070
+              protocol: TCP
+          volumeMounts:
+            - name: shared-data
+              mountPath: /mnt/shared-data
+            - name: sidecar-nginx-config
+              mountPath: /etc/nginx/nginx.conf
+              subPath: nginx.conf
+            - name: sidecar-nginx-config
+              mountPath: /etc/nginx/conf.d/jupyter.conf
+              subPath: jupyter.conf
+            - name: tz-config
+              mountPath: /etc/localtime
     proxy:
       chp:
         defaultTarget: "https://{{ .Values.global.name }}-hub:8081"