diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 9ffa9a5339fd6fbb330a2fe03b08abe536bcdcf5..25c9a77322c47c1f14dcb0c9df2d0c1ba5af2909 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -14,3 +14,4 @@ include:
 - mailu/pipeline.yml
 - oauth2-proxy/pipeline.yml
 - quassel/pipeline.yml
+- restic/pipeline.yml
diff --git a/restic/Chart.yaml b/restic/Chart.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..469748208f0b33af443c24100318f720c8d04530
--- /dev/null
+++ b/restic/Chart.yaml
@@ -0,0 +1,6 @@
+apiVersion: v2
+name: restic
+description: Helm Chart for restic
+type: application
+version: 1.0.0
+appVersion: "0.13.1"
diff --git a/restic/pipeline.yml b/restic/pipeline.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d5129fa07c8355387e85c06cc896694d69ecaf8f
--- /dev/null
+++ b/restic/pipeline.yml
@@ -0,0 +1,16 @@
+lint-restic:
+  stage: lint
+  script:
+    - helm lint restic
+
+release-restic:
+  stage: release
+  needs:
+    - lint-restic
+  rules:
+    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
+  script:
+    - apk add --no-cache git
+    - helm plugin install https://github.com/chartmuseum/helm-push.git
+    - helm repo add --username gitlab-ci-token --password $CI_JOB_TOKEN repo ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/helm/stable
+    - helm cm-push restic repo
diff --git a/restic/templates/_helpers.tpl b/restic/templates/_helpers.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..48290e164f7d341f2c21d33d6d299b07572b6769
--- /dev/null
+++ b/restic/templates/_helpers.tpl
@@ -0,0 +1,56 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "restic-helm.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "restic-helm.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "restic-helm.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "restic-helm.labels" -}}
+helm.sh/chart: {{ include "restic-helm.chart" . }}
+{{ include "restic-helm.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "restic-helm.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "restic-helm.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+
+{{- define "restic-helm.sslPath" -}}
+/certs
+{{- end }}
diff --git a/restic/templates/cronjob_backup.yaml b/restic/templates/cronjob_backup.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..502d4d6bb19f2d36b880302bc9bb8368c82b8c58
--- /dev/null
+++ b/restic/templates/cronjob_backup.yaml
@@ -0,0 +1,67 @@
+apiVersion: batch/v1
+kind: CronJob
+metadata:
+  name: {{ include "restic-helm.fullname" . }}
+  labels:
+    {{- include "restic-helm.labels" . | nindent 4 }}
+spec:
+  schedule: "{{ .Values.schedule }}"
+  jobTemplate:
+    metadata:
+      {{- with .Values.jobAnnotations }}
+      annotations:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      labels:
+        {{- include "restic-helm.labels" . | nindent 8 }}
+    spec:
+      template:
+        metadata:
+          {{- with .Values.podAnnotations }}
+          annotations:
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
+          labels:
+            {{- include "restic-helm.labels" . | nindent 12 }}
+        spec:
+          {{- with .Values.imagePullSecrets }}
+          imagePullSecrets:
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
+          securityContext:
+            {{- toYaml .Values.podSecurityContext | nindent 12 }}
+          volumes:
+            - name: data
+              {{- .Values.volume | nindent 14 }}
+          containers:
+            - name: {{ .Chart.Name }}
+              securityContext:
+                {{- toYaml .Values.securityContext | nindent 16 }}
+              image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+              imagePullPolicy: {{ .Values.image.pullPolicy }}
+              workingDir: "/sync"
+              args:
+                - "-r"
+                - "{{ .Values.repository.name }}"
+                - "backup"
+                - "."
+              envFrom:
+                - secretRef:
+                    name: {{ include "restic-helm.fullname" . }}
+              resources:
+                {{- toYaml .Values.resources | nindent 16 }}
+              volumeMounts:
+                - mountPath: "/sync"
+                  name: data
+          {{- with .Values.nodeSelector }}
+          nodeSelector:
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
+          {{- with .Values.affinity }}
+          affinity:
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
+          {{- with .Values.tolerations }}
+          tolerations:
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
diff --git a/restic/templates/job_init.yaml b/restic/templates/job_init.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..68a0e662942616ceab03b74672f7f5b6a694c3da
--- /dev/null
+++ b/restic/templates/job_init.yaml
@@ -0,0 +1,56 @@
+apiVersion: batch/v1
+kind: Job
+metadata:
+  name: {{ include "restic-helm.fullname" . }}
+  labels:
+    {{- include "restic-helm.labels" . | nindent 4 }}
+spec:
+  template:
+    metadata:
+      {{- with .Values.podAnnotations }}
+      annotations:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      labels:
+        {{- include "restic-helm.labels" . | nindent 8 }}
+    spec:
+      {{- with .Values.imagePullSecrets }}
+      imagePullSecrets:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      securityContext:
+        {{- toYaml .Values.podSecurityContext | nindent 8 }}
+      volumes:
+        - name: data
+          {{- .Values.volume | nindent 10 }}
+      containers:
+        - name: {{ .Chart.Name }}
+          securityContext:
+            {{- toYaml .Values.securityContext | nindent 12 }}
+          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+          imagePullPolicy: {{ .Values.image.pullPolicy }}
+          workingDir: "/sync"
+          args:
+            - "-r"
+            - "{{ .Values.repository.name }}"
+            - "init"
+          envFrom:
+            - secretRef:
+                name: {{ include "restic-helm.fullname" . }}
+          resources:
+            {{- toYaml .Values.resources | nindent 12 }}
+          volumeMounts:
+            - mountPath: "/sync"
+              name: data
+      {{- with .Values.nodeSelector }}
+      nodeSelector:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.affinity }}
+      affinity:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.tolerations }}
+      tolerations:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
diff --git a/restic/templates/secret.yaml b/restic/templates/secret.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..51e93aff3de345912ae7807a41490d36c8a43343
--- /dev/null
+++ b/restic/templates/secret.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ include "restic-helm.fullname" . }}
+  labels:
+    {{- include "restic-helm.labels" . | nindent 4 }}
+data:
+  RESTIC_PASSWORD: "{{ .Values.repository.key }}"
+  RESTIC_REPOSITORY: "{{ .Values.repository.name }}"
+  {{- toYaml .Values.auth | nindent 2 }}
diff --git a/restic/values.yaml b/restic/values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a0a9051524b3096444fc51f2a86338319d233400
--- /dev/null
+++ b/restic/values.yaml
@@ -0,0 +1,49 @@
+image:
+  repository: restic/restic
+  pullPolicy: IfNotPresent
+  tag: ""
+
+imagePullSecrets: [ ]
+nameOverride: ""
+fullnameOverride: ""
+
+volume: |-
+  emptyDir: {}
+
+schedule: "0 0 * * *"
+
+auth:
+  B2_ACCOUNT_ID: "AzureDiamond"
+  B2_ACCOUNT_KEY: "hunter2"
+
+repository:
+  name: "mybackuprepo"
+  key: "mypassword"
+
+jobAnnotations: { }
+
+podAnnotations: { }
+
+podSecurityContext:
+  fsGroup: 2000
+
+securityContext:
+  capabilities:
+    drop:
+      - ALL
+  runAsNonRoot: true
+  runAsUser: 1000
+
+resources:
+  limits:
+    cpu: 500m
+    memory: 512Mi
+  requests:
+    cpu: 10m
+    memory: 64Mi
+
+nodeSelector: { }
+
+tolerations: [ ]
+
+affinity: { }