diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 747e768527fec27b63a5d3bb7a99a1905641a9cf..46226f170df3636e5fa8aa302c6e369cd1ab3408 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,7 +1,6 @@
 stages:
-  - steve
-  - build_webservice
-  - test_maxima
+  - build_server
+  - build
 
 variables:
   GIT_SUBMODULE_STRATEGY: recursive
@@ -9,8 +8,8 @@ variables:
 
 # gitlab ci script taken from https://gist.github.com/danielneis/5c6140ec8150c6151a54bccd26950278
 
-steve_jobs:
-  stage: steve
+build_server_binary:
+  stage: build_server
   image: golang
   tags:
     - docker
@@ -21,12 +20,25 @@ steve_jobs:
     - bin/web
     expire_in: 1 week
 
-build_webservice:
+build_goemaxima_containers:
   image: "docker:latest"
-  stage: build_webservice
+  stage: build
   tags:
     - docker
   before_script:
     - docker login -u mathinstitut -p "$DOCKERHUB_PASS"
   script:
     - ./build.sh "$REGISTRY" "$CI_COMMIT_TAG"
+
+build_gitrollout:
+  image: "docker:latest"
+  stage: build
+  tags:
+    - docker
+  before_script:
+    - docker login -u mathinstitut -p "$DOCKERHUB_PASS"
+  script:
+    - docker build -t mathinstitut/gitrollout:latest git-rollout
+  only:
+    changes:
+      - git-rollout/**
diff --git a/git-rollout/Dockerfile b/git-rollout/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..34b09fae2d8f377fa1e1bdeb3fa640e41645147f
--- /dev/null
+++ b/git-rollout/Dockerfile
@@ -0,0 +1,10 @@
+from alpine:latest
+run apk update && apk add git git-daemon jq && \
+    wget "https://dl.k8s.io/release/$(wget -q -O- https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" && \
+    chmod a+x kubectl && \
+    cp kubectl /bin/kubectl && \
+    mkdir -p /git
+copy update.sh /bin/update.sh
+workdir /git
+entrypoint ["/bin/update.sh"]
+
diff --git a/git-rollout/README.md b/git-rollout/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..bcd515d2c1239eae6361a7e86436512f67546322
--- /dev/null
+++ b/git-rollout/README.md
@@ -0,0 +1,13 @@
+git-rollout
+===========
+
+This directory contains git-rollout, a small container and kubernetes config to update
+rollout new containers whenever some git repository is updated.
+
+At the MI, this is used to make the goemaxima containers automatically restart with new
+macro files downloaded from git (see also the enableGitRollout and gitRollout values
+in helmmaxima).
+
+It has to be in the same namespace as the goemaxima instances and looks for the label
+gitrollout=goemaxima label, which is already added if you use the helmmaxima chart with
+enableGitRollout value set to true.
diff --git a/git-rollout/git-rollout.yml b/git-rollout/git-rollout.yml
new file mode 100644
index 0000000000000000000000000000000000000000..25ed14d7ac068a6a123014340baba209c95688dd
--- /dev/null
+++ b/git-rollout/git-rollout.yml
@@ -0,0 +1,61 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+  name: git-rollout
+rules:
+ - apiGroups: ["apps", "extensions"]
+   resources: ["deployments"]
+   verbs: ["get", "patch", "list"]
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: git-rollout
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: git-rollout
+subjects:
+- kind: ServiceAccount
+  name: git-rollout
+roleRef:
+  kind: Role
+  name: git-rollout
+  apiGroup: rbac.authorization.k8s.io
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: git-rollout
+  labels:
+    app: git-rollout
+spec:
+  selector:
+    matchLabels:
+      app: git-rollout
+  template:
+    metadata:
+      labels:
+        app: git-rollout
+    spec:
+      serviceAccountName: git-rollout
+      containers:
+      - name: git-rollout
+        image: "mathinstitut/git-rollout:latest"
+        imagePullPolicy: "Always"
+        args: ['https://github.com/eLearning-TUDarmstadt/maxima-scripts', 'gitrollout=goemaxima']
+        ports:
+        - containerPort: 9418
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: git-rollout
+spec:
+  selector:
+    app: git-rollout
+  ports:
+    - protocol: TCP
+      port: 9418
+      targetPort: 9418
diff --git a/git-rollout/update.sh b/git-rollout/update.sh
new file mode 100755
index 0000000000000000000000000000000000000000..4c8cc353da493f51cf820037cacdc3967d1c32fa
--- /dev/null
+++ b/git-rollout/update.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+SLEEP_TIME=180
+DIR_NAME="git"
+rm -rf "$DIR_NAME"
+git clone "$1" "$DIR_NAME"
+# required for git daemon to work on this repo
+touch "$DIR_NAME/.git/git-daemon-export-ok"
+git daemon --base-path="$(pwd)" --log-destination=stderr &
+cd "$DIR_NAME"
+while true; do
+	git remote update
+	# check whether there has been any update
+	if [ "$(git rev-parse @)" = "$(git rev-parse '@{u}')" ]; then
+		# do nothing if no update
+		sleep "$SLEEP_TIME"
+		continue
+	fi
+	# checkout latest commit
+	git reset --hard origin
+	# names of all deployments that match the labels in $2
+	deployments="$(kubectl get deployment -l "$2" -o json | jq -r '.items[].metadata.name')"
+	# restart all those deployments
+	for deployment in $deployments; do
+		kubectl rollout restart "deployment/$deployment"
+	done
+	sleep "$SLEEP_TIME"
+done
diff --git a/helmmaxima/templates/deployment.yaml b/helmmaxima/templates/deployment.yaml
index 4af9b554e9c059a3bcedea98a4164e0729bf5094..e44f8690822ea001a2b9a06178ca071e03c73193 100644
--- a/helmmaxima/templates/deployment.yaml
+++ b/helmmaxima/templates/deployment.yaml
@@ -3,6 +3,9 @@ kind: Deployment
 metadata:
   name: {{ include "helmmaxima.fullname" . }}
   labels:
+    {{ if .Values.enableGitRollout -}}
+    gitrollout: goemaxima
+    {{- end -}}
     {{- include "helmmaxima.labels" . | nindent 4 }}
 spec:
   replicas: {{ .Values.replicaCount }}
@@ -15,6 +18,7 @@ spec:
         {{- include "helmmaxima.selectorLabels" . | nindent 8 }}
         app: {{ include "helmmaxima.fullname" . }}
     spec:
+      terminationGracePeriodSeconds: 45
     {{- with .Values.imagePullSecrets }}
       imagePullSecrets:
         {{- toYaml . | nindent 8 }}
@@ -22,6 +26,20 @@ spec:
       securityContext:
         {{- toYaml .Values.podSecurityContext | nindent 8 }}
       automountServiceAccountToken: false
+      {{ if .Values.enableGitRollout }}
+      initContainers:
+        - name: "{{ .Chart.Name }}-git"
+          image: "k8s.gcr.io/git-sync/git-sync:v3.6.1"
+          args: ['--root=/mnt', '--one-time', '--depth=1']
+          volumeMounts:
+            - mountPath: /mnt
+              name: git
+          env:
+            - name: GIT_SYNC_REPO
+              value: "{{ .Values.gitRollout.repo }}"
+            - name: GIT_SYNC_BRANCH
+              value: "{{ .Values.gitRollout.branch }}"
+      {{ end }}
       containers:
         - name: {{ .Chart.Name }}
           securityContext:
@@ -35,6 +53,10 @@ spec:
           volumeMounts:
             - mountPath: /tmp
               name: tmptmpfs
+            {{ if .Values.enableGitRollout }}
+            - mountPath: /mnt
+              name: git
+            {{ end }}
           livenessProbe:
             httpGet:
               path: '/maxima?health=1'
@@ -49,12 +71,26 @@ spec:
             initialDelaySeconds: 5
             periodSeconds: 5
             failureThreshold: 3
+          {{ if .Values.enableGitRollout }}
+          env:
+            - name: GOEMAXIMA_EXTRA_PACKAGES
+              value: "{{ .Values.gitRollout.includefile }}"
+          {{ end }}
+          lifecycle:
+            preStop:
+              exec:
+                command: ["/bin/sleep", "35"]
           resources:
             {{- toYaml .Values.resources | nindent 12 }}
       volumes:
         - name: tmptmpfs
           emptyDir:
             medium: "Memory"
+        {{ if .Values.enableGitRollout }}
+        - name: git
+          emptyDir:
+            medium: "Memory"
+        {{ end }}
       {{- with .Values.nodeSelector }}
       nodeSelector:
         {{- toYaml . | nindent 8 }}
diff --git a/helmmaxima/templates/network.yaml b/helmmaxima/templates/network.yaml
index ba84ae6b7c5f64e22c53fb0d975ba7a0517998c6..c967275a21afdbb403172b9f5875f7e430ccebbf 100644
--- a/helmmaxima/templates/network.yaml
+++ b/helmmaxima/templates/network.yaml
@@ -6,6 +6,16 @@ spec:
   podSelector:
     matchLabels:
       app: {{ include "helmmaxima.fullname" . }}
-  # block all egress traffic
+  # block egress traffic
   policyTypes:
   - Egress
+  {{ if .Values.enableGitRollout }}
+  egress:
+    - to:
+        - podSelector:
+            matchLabels:
+              app: git-rollout
+    - ports:
+        - protocol: TCP
+          port: 9418
+  {{ end }}
diff --git a/helmmaxima/values.yaml b/helmmaxima/values.yaml
index 1696f035af8239c5b1328a64d13a7634804c4739..ebdf182a4bf425d634edff2a54715b380df9b64c 100644
--- a/helmmaxima/values.yaml
+++ b/helmmaxima/values.yaml
@@ -12,6 +12,12 @@ image:
   image_prefix: mathinstitut/goemaxima
   pullPolicy: Always
 
+enableGitRollout: false
+gitRollout:
+  repo: 'git://$(GIT_ROLLOUT_SERVICE_HOST)/git'
+  branch: main
+  includefile: '/mnt/git/main.mac'
+
 imagePullSecrets: []
 nameOverride: ""
 fullnameOverride: ""