diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..cafb485ab0c8e6047accb6c176d8914deed30f46
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,31 @@
+---
+include: 'https://gitlab.cern.ch/linuxsupport/cronjobs/base/raw/master/gitlab-ci.yml'
+
+
+build_stream8_backups:
+  stage: build
+  tags:
+    - docker-image-build
+  script: "echo" # unused but this line is required by GitLab CI
+  variables:
+    CONTEXT_DIR: stream8_backups
+    TO: $CI_REGISTRY_IMAGE/stream8_backups:$CI_COMMIT_REF_NAME
+
+deploy:
+  extends: .nomad
+  stage: deploy
+  script:
+    - for j in *.nomad; do echo -e "\n${j}:"; nomad job run <(envsubst < $j); done
+  only:
+    - tags
+    - master
+
+deploy_dev:
+  extends: .nomad
+  stage: deploy
+  script:
+    - for j in *.nomad; do echo -e "\n${j}:"; nomad job run <(envsubst < $j); done
+  except:
+    - tags
+    - master
+  when: manual
diff --git a/README.md b/README.md
index f47197f3eb5e3f8808cfebb3db1fee57f2d69efc..6f9969f6017d836a1e747cff468560179668785a 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,56 @@
 # stream8_backups
 
+This is a nomad job to backup the daily snapshots created by stream8_snapshots
+
+The entrypoint `backup.sh` performs a backup of $TODAY using restic, storing the data on s3.cern.ch
+
+A helper script `interactive.sh` (included in the docker image) provides the ability to query the restic repository in an interactive fashion.
+
+To launch `interactive.sh` it is recommended to run a privileged docker instance as follows:
+
+```bash
+    $ export BRANCH=<branch> EMAIL=<you>@cern.ch S3REPO=s8-backups-testing PATH_SNAPSHOTS=TMP;
+    docker run -it --rm --entrypoint bash \
+    --privileged --cap-add SYS_ADMIN --cap-add MKNOD --device /dev/fuse
+    -v /mnt/data1/dist:/data \
+    -e PATH_SNAPSHOTS="$PATH_SNAPSHOTS" \
+    -e RESTIC_REPOSITORY="s3:s3.cern.ch/$S3REPO" \
+    -e EMAIL_FROM="linux.support@cern.ch" \
+    -e EMAIL_ADMIN="$EMAIL" \
+    -e NOMAD_ADDR="https://lxsoftadm.cern.ch:4646" \
+    gitlab-registry.cern.ch/linuxsupport/cronjobs/stream8_backups/stream8_backups:$BRANCH
+```
+
+(for the production data, use `S3REPO="s8-backups-production" PATH_SNAPSHOTS="cern/centos"`)
+
+`interactive.sh` provides the following abilities:
+
+1. list snapshots
+`./interactive.sh snapshots`
+2. restore a snapshot
+`./interactive.sh restore YYYYMMDD /path/to/restore/to`
+3. fuse mount the restic respository
+`./interactive.sh mount` (mounts to `/root/fusemount`)
+4. unmount the restic repository
+`./interactive.sh unmount`
+
+S3 credentials are required to access the restic repo, which are embedded into the nomad job for the daily backup use case.
+
+We are currently using credentials that map to the "Linuxsoft service" OpenStack tenant, which has a quota of 500GB
+
+When using `interactive.sh`, the script will ask you to enter S3 credentials. These credentials are stored within the container in `/tmp/credentials`. If you wish to use restic directly (outside of the `interactive.sh` script), you may `source /tmp/credentils` after first running `interactive.sh`.
+
+If you do not know where to retrieve the credentials, they can be found in the 'Variables' section of <https://gitlab.cern.ch/linuxsupport/cronjobs/stream8/-/settings/ci_cd> or alternatively via `tbag showkeys --hg lxsoft/adm`.
+
+```
+for i in AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY RESTIC_PASSWORD; do tbag show --hg lxsoft/adm stream8_backups_$i; done
+```
+
+Note: The backup repository/bucket must be initialised once, which is a manual task.
+You can accomplish this by:
+```
+./get_credentials.sh
+source /tmp/credentials
+restic init
+```
+
diff --git a/dev.variables.sh b/dev.variables.sh
new file mode 100644
index 0000000000000000000000000000000000000000..7e68e7a5468f5377f09fac6180e9fc04e797a87d
--- /dev/null
+++ b/dev.variables.sh
@@ -0,0 +1,7 @@
+SCHEDULE="15 9 * * 1"
+DATA="/mnt/data1/dist"
+PATH_SNAPSHOTS="tmp"
+S3_REPOSITORY="s8-backups-testing"
+PRUNE_SNAPSHOTS_OLDER_THAN="2d"
+EMAIL_FROM="Linux.Support@cern.ch"
+EMAIL_ADMIN="morrice@cern.ch"
diff --git a/prod.variables.sh b/prod.variables.sh
new file mode 100644
index 0000000000000000000000000000000000000000..28a10b65c2264c809ae55f2e569507c92b184df6
--- /dev/null
+++ b/prod.variables.sh
@@ -0,0 +1,7 @@
+SCHEDULE="45 9 * * *"
+DATA="/mnt/data1/dist"
+PATH_SNAPSHOTS="cern/centos"
+S3_REPOSITORY="s8-backups-production"
+PRUNE_SNAPSHOTS_OLDER_THAN="730d"
+EMAIL_FROM="Linux.Support@cern.ch"
+EMAIL_ADMIN="lxsoft-admins@cern.ch"
diff --git a/stream8_backups.nomad b/stream8_backups.nomad
new file mode 100644
index 0000000000000000000000000000000000000000..ee82da97c8d602a38283e4d3fc96f7105fc22ba2
--- /dev/null
+++ b/stream8_backups.nomad
@@ -0,0 +1,58 @@
+job "${PREFIX}_stream8_backups" {
+  datacenters = ["meyrin"]
+
+  type = "batch"
+
+  periodic {
+    cron = "${SCHEDULE}"
+    time_zone = "Europe/Zurich"
+    prohibit_overlap = false
+  }
+
+  reschedule {
+    attempts       = 276
+    interval       = "23h"
+    unlimited      = false
+    delay          = "5m"
+    delay_function = "constant"
+  }
+
+  task "${PREFIX}_stream8_backups" {
+    driver = "docker"
+
+    config {
+      image = "https://gitlab-registry.cern.ch/linuxsupport/cronjobs/stream8_backups/stream8_backups:${CI_COMMIT_REF_NAME}"
+      force_pull = ${FORCE_PULL}
+      logging {
+        config {
+          tag = "${PREFIX}_stream8_backups"
+        }
+      }
+      volumes = [
+        "$DATA:/data",
+      ]
+    }
+
+    env {
+      RESTIC_PASSWORD = "$RESTIC_PASSWORD"
+      AWS_ACCESS_KEY_ID = "$AWS_ACCESS_KEY_ID"
+      AWS_SECRET_ACCESS_KEY = "$AWS_SECRET_ACCESS_KEY"
+      RESTIC_REPOSITORY = "s3:s3.cern.ch/$S3_REPOSITORY"
+      PRUNE_SNAPSHOTS_OLDER_THAN = "$PRUNE_SNAPSHOTS_OLDER_THAN"
+      PATH_SNAPSHOTS = "$PATH_SNAPSHOTS"
+      EMAIL_FROM = "$EMAIL_FROM"
+      EMAIL_ADMIN = "$EMAIL_ADMIN"
+      NOMAD_ADDR = "$NOMAD_ADDR"
+    }
+
+    resources {
+      cpu = 6000 # Mhz
+      memory = 1024 # MB
+
+      network {
+        mbits = 10
+      }
+    }
+
+  }
+}
diff --git a/stream8_backups/Dockerfile b/stream8_backups/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..9afd218463b398237c47b7cd872997802b8a7e73
--- /dev/null
+++ b/stream8_backups/Dockerfile
@@ -0,0 +1,11 @@
+FROM gitlab-registry.cern.ch/linuxsupport/cc7-base:latest
+
+RUN yum-config-manager --add-repo https://copr.fedorainfracloud.org/coprs/copart/restic/repo/epel-7/copart-restic-epel-7.repo
+RUN yum install -y restic ssmtp gettext fuse
+COPY ssmtp.conf /etc/ssmtp/ssmtp.conf
+COPY *.sh *.tpl /root/
+
+WORKDIR /root
+
+ENTRYPOINT ["/root/backup.sh"]
+
diff --git a/stream8_backups/backup.sh b/stream8_backups/backup.sh
new file mode 100755
index 0000000000000000000000000000000000000000..9296da78fb9b6a75b92ff01f83254bdddfa9720b
--- /dev/null
+++ b/stream8_backups/backup.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+source common.sh
+
+# we want to maintain the same $SOURCE path to simplify restores, but we
+# don't really want to read every snapshot on every run as this will take days
+# Let's just backup $TODAY, ignoring symlink snaps (zero updates) as well
+EXCLUDE_LIST=`mktemp`
+RESTIC_LOGFILE=`mktemp`
+find $SOURCE -mindepth 1 -maxdepth 1 \( -type l -o -type d \) ! -path "*$TODAY" > $EXCLUDE_LIST
+$RESTIC backup --tag $TODAY --exclude-file=$EXCLUDE_LIST $SOURCE &>> $RESTIC_LOGFILE
+rm -f $EXCLUDE_LIST
+
+# Check if there are any snapshots to forget/purge
+SNAPS_TO_REMOVE=`$RESTIC forget --dry-run --group-by paths --keep-within $PRUNE_SNAPSHOTS_OLDER_THAN | grep "remove .* snapshots" | awk '{print $2}'`
+if [ ! -z $SNAPS_TO_REMOVE ]; then
+  echo "Found $SNAPS_TO_REMOVE snapshots that are older than $PRUNE_SNAPSHOTS_OLDER_THAN. Purging from restic store ..." >> $RESTIC_LOGFILE
+  $RESTIC unlock &>> $RESTIC_LOGFILE
+  $RESTIC forget --group-by paths --keep-within $PRUNE_SNAPSHOTS_OLDER_THAN --prune &>> $RESTIC_LOGFILE
+fi
+
+echo "Sending email of $RESTIC_LOG to admins"
+export TODAY="$TODAY"
+export RESTIC_LOG="`cat $RESTIC_LOGFILE`"
+rm -f $RESTIC_LOGFILE
+
+envsubst < $TEMPLATE > email
+
+cat email | ssmtp -t -v
+rm -f email
diff --git a/stream8_backups/common.sh b/stream8_backups/common.sh
new file mode 100644
index 0000000000000000000000000000000000000000..648a0ee8dcdf620e7f452fa91b01e34561456ae6
--- /dev/null
+++ b/stream8_backups/common.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+TODAY=`/bin/date +%Y%m%d`
+SOURCE=/data/$PATH_SNAPSHOTS/s8-snapshots
+if [ ! -d $SOURCE/.restic ]; then
+  mkdir $SOURCE/.restic
+fi
+if [ ! -d $SOURCE/.restic/tmpdir ]; then
+  mkdir $SOURCE/.restic/tmpdir
+fi
+if [ ! -d $SOURCE/.restic/cachedir ]; then
+  mkdir $SOURCE/.restic/cachedir
+fi
+export TMPDIR=$SOURCE/.restic/tmpdir
+TEMPLATE=email_report.tpl
+# s3.connections default is 5, let's increase it for better perf
+# and set the cachedir explicitly
+RESTIC="restic -o s3.connections=32 --cache-dir $SOURCE/.restic/cachedir"
diff --git a/stream8_backups/email_report.tpl b/stream8_backups/email_report.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..09c6851ac60072d680e91bda13cfd0f91a544a34
--- /dev/null
+++ b/stream8_backups/email_report.tpl
@@ -0,0 +1,16 @@
+To: $EMAIL_ADMIN
+From: $EMAIL_FROM
+Reply-To: noreply.$EMAIL_FROM
+Return-Path: $EMAIL_ADMIN
+Subject: Stream8 - Backup for $TODAY
+
+Dear Linux admins,
+
+Today's backup ($TODAY) has completed with the following output:
+
+$RESTIC_LOG
+
+---
+Best regards,
+CERN Linux Droid
+(on behalf of the friendly humans of Linux Support)
diff --git a/stream8_backups/get_credentials.sh b/stream8_backups/get_credentials.sh
new file mode 100755
index 0000000000000000000000000000000000000000..645123140ba8dc9aad545d44b075858fe3d8ec92
--- /dev/null
+++ b/stream8_backups/get_credentials.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+echo "This script defines variables required to access the S3 repo"
+echo "These variables can be found at https://gitlab.cern.ch/linuxsupport/cronjobs/centos8_backups/-/settings/ci_cd"
+echo -n "Please enter AWS_ACCESS_KEY_ID: "
+read AWS_ACCESS_KEY_ID
+echo -n "Please enter AWS_SECRET_ACCESS_KEY: "
+read AWS_SECRET_ACCESS_KEY
+echo -n "Please enter RESTIC_PASSWORD: "
+read RESTIC_PASSWORD
+
+echo "export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID" >> /tmp/credentials
+echo "export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY" >> /tmp/credentials
+echo "export RESTIC_PASSWORD=$RESTIC_PASSWORD" >> /tmp/credentials
+echo "Credentials saved to /tmp/credentials"
diff --git a/stream8_backups/interactive.sh b/stream8_backups/interactive.sh
new file mode 100755
index 0000000000000000000000000000000000000000..8829e54683e0867223cae98ef227cfc90a1a042b
--- /dev/null
+++ b/stream8_backups/interactive.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+source common.sh
+FUSEMOUNT=fusemount
+
+if [ ! -f /tmp/credentials ]; then
+  source get_credentials.sh
+fi
+source /tmp/credentials
+
+if [ "$1" == "restore" ]; then
+  if [ -z $2 ]; then
+    echo "Error, need a snapshot [YYYYMMDD] to restore ..."
+    exit
+  fi
+  if [ -z $3 ]; then
+    echo "Error, need a target path to restore to ..."
+    exit
+  fi
+  $RESTIC restore latest --tag $2 -i $2 --target "$3"
+elif [ "$1" == "snapshots" ]; then
+  $RESTIC snapshots   
+elif [ "$1" == "unlock" ]; then
+  $RESTIC unlock   
+elif [ "$1" == "mount" ]; then
+  # TODO: check fusemount is not already mounted
+  if [ ! -d "$FUSEMOUNT" ]; then
+    mkdir $FUSEMOUNT
+  fi
+  echo "mounting \"$FUSEMOUNT\" (process backgrounded)"
+  echo "use: '$0 unmount' when finished"
+  $RESTIC mount $FUSEMOUNT &> /dev/null &
+elif [ "$1" == "unmount" ]; then
+  pkill -f $RESTIC &> /dev/null
+  fusermount -u $FUSEMOUNT &> /dev/null
+else
+  echo "usage: $0 <restore YYYYMMDD path|unlock|mount|unmount|snapshots>"
+fi
diff --git a/stream8_backups/ssmtp.conf b/stream8_backups/ssmtp.conf
new file mode 100644
index 0000000000000000000000000000000000000000..518eea4b157ce6079a05d25c1ce9747e12d0726c
--- /dev/null
+++ b/stream8_backups/ssmtp.conf
@@ -0,0 +1,4 @@
+root=postmaster
+mailhub=cernmx.cern.ch
+TLS_CA_File=/etc/pki/tls/certs/ca-bundle.crt
+FromLineOverride=YES