summaryrefslogtreecommitdiff
path: root/images/backup
diff options
context:
space:
mode:
authorTill Höppner2017-05-31 18:00:15 +0200
committerTill Höppner2017-05-31 18:00:15 +0200
commit33c2361ab6f0d7bfc802d2fc10d2f29aef44867b (patch)
tree706f4c46e942433eb13cba20cedd816bb07226ae /images/backup
parentc20a9f58eb362ad84a1f0e3b911b89ffc9bf8451 (diff)
downloadserver-33c2361ab6f0d7bfc802d2fc10d2f29aef44867b.tar.gz
server-33c2361ab6f0d7bfc802d2fc10d2f29aef44867b.tar.xz
server-33c2361ab6f0d7bfc802d2fc10d2f29aef44867b.zip
Add backup image
Diffstat (limited to 'images/backup')
-rw-r--r--images/backup/.gitignore1
-rw-r--r--images/backup/backup.service11
-rw-r--r--images/backup/backup.timer9
-rw-r--r--images/backup/backup.yml21
-rw-r--r--images/backup/duplicity/Dockerfile16
-rwxr-xr-ximages/backup/duplicity/backup.sh39
-rw-r--r--images/backup/duplicity/gpg-agent.conf1
-rwxr-xr-ximages/backup/duplicity/restore.sh26
-rw-r--r--images/backup/gpg_keys/backups.pub.key108
-rw-r--r--images/backup/restore.yml16
10 files changed, 248 insertions, 0 deletions
diff --git a/images/backup/.gitignore b/images/backup/.gitignore
new file mode 100644
index 0000000..2549b3d
--- /dev/null
+++ b/images/backup/.gitignore
@@ -0,0 +1 @@
+config.env
diff --git a/images/backup/backup.service b/images/backup/backup.service
new file mode 100644
index 0000000..f4cce9b
--- /dev/null
+++ b/images/backup/backup.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Duplicity backups
+Requires=docker.service
+
+[Service]
+Restart=no
+ExecStart=/bin/sh -c 'docker-compose -f /storage/disk0/server15_backup/backup.yml up --no-recreate'
+ExecStop=/bin/sh -c 'docker-compose -f /storage/disk0/server15_backup/restore.yml stop'
+
+[Install]
+WantedBy=local.target
diff --git a/images/backup/backup.timer b/images/backup/backup.timer
new file mode 100644
index 0000000..35bf358
--- /dev/null
+++ b/images/backup/backup.timer
@@ -0,0 +1,9 @@
+[Unit]
+Description=Run backups daily
+
+[Timer]
+Persistent=true
+OnCalendar=04:04
+
+[Install]
+WantedBy=timers.target
diff --git a/images/backup/backup.yml b/images/backup/backup.yml
new file mode 100644
index 0000000..c182b8d
--- /dev/null
+++ b/images/backup/backup.yml
@@ -0,0 +1,21 @@
+version: '3'
+
+services:
+ backup:
+ env_file:
+ - config.env
+ build: ./duplicity
+ command: /bin/sh /backup.sh
+ hostname: duplicity
+ restart: "no"
+ volumes:
+ - cache:/cache
+ - ./gpg_keys:/gpg_keys:ro
+
+ - git_data:/data/git
+
+volumes:
+ cache:
+
+ # server_git_data:
+ #external: true
diff --git a/images/backup/duplicity/Dockerfile b/images/backup/duplicity/Dockerfile
new file mode 100644
index 0000000..9ce6d6b
--- /dev/null
+++ b/images/backup/duplicity/Dockerfile
@@ -0,0 +1,16 @@
+FROM alpine:3.5
+
+RUN apk add --update duplicity ca-certificates gnupg openssh-client py-paramiko py2-pip
+
+RUN pip install --upgrade setuptools
+RUN pip install --upgrade distribute
+
+ADD backup.sh /backup.sh
+ADD restore.sh /restore.sh
+
+RUN mkdir /root/.gnupg/
+ADD gpg-agent.conf /root/.gnupg/gpg-agent.conf
+RUN chmod 600 /root/.gnupg
+
+RUN mkdir /root/.ssh
+RUN chmod 600 /root/.ssh
diff --git a/images/backup/duplicity/backup.sh b/images/backup/duplicity/backup.sh
new file mode 100755
index 0000000..38223e3
--- /dev/null
+++ b/images/backup/duplicity/backup.sh
@@ -0,0 +1,39 @@
+#!/bin/sh -xe
+set -x
+set -e
+
+ls -lah /data
+
+CONNECTION_OPTIONS="--use-agent \
+ --verbosity $LOG_LEVEL \
+ --num-retries 3 \
+ --encrypt-key $FINGERPRINT \
+ --log-file /dev/stdout \
+ --archive-dir /cache/archive \
+ --ssh-options=-oIdentityFile=/ssh_keys/backup \
+ --gpg-options --passphrase=$PASSPHRASE \
+ --gpg-options --no-tty \
+ --gpg-options --batch \
+ --gpg-options --pinentry-mode=loopback"
+
+# Import and trust the GPG Keys
+gpg --passphrase $PASSPHRASE --no-tty --batch --import /gpg_keys/*.priv.asc
+echo "$FINGERPRINT:6:" | gpg --import-ownertrust
+
+mkdir -p /cache/archive
+
+# Make the actual backup
+duplicity --asynchronous-upload \
+ --volsize 250 \
+ --full-if-older-than 1M \
+ $CONNECTION_OPTIONS \
+ $EXCLUDE_DIRS \
+ /data/ "$BACKUP_STORAGE"
+
+# Clean up broken backups
+duplicity cleanup $CONNECTION_OPTIONS \
+ "$BACKUP_STORAGE"
+
+# Clean up old backups
+duplicity remove-all-but-n-full 1 $CONNECTION_OPTIONS \
+ "$BACKUP_STORAGE"
diff --git a/images/backup/duplicity/gpg-agent.conf b/images/backup/duplicity/gpg-agent.conf
new file mode 100644
index 0000000..d1b6ae3
--- /dev/null
+++ b/images/backup/duplicity/gpg-agent.conf
@@ -0,0 +1 @@
+allow-loopback-pinentry
diff --git a/images/backup/duplicity/restore.sh b/images/backup/duplicity/restore.sh
new file mode 100755
index 0000000..df3f9c9
--- /dev/null
+++ b/images/backup/duplicity/restore.sh
@@ -0,0 +1,26 @@
+#!/bin/sh -xe
+set -x
+set -e
+
+CONNECTION_OPTIONS="--use-agent \
+ --verbosity $LOG_LEVEL \
+ --num-retries 3 \
+ --encrypt-key $FINGERPRINT \
+ --log-file /dev/stdout \
+ --archive-dir /cache/archive \
+ --ssh-options=-oIdentityFile=/ssh_keys/backup \
+ --gpg-options --passphrase=$PASSPHRASE \
+ --gpg-options --no-tty \
+ --gpg-options --batch \
+ --gpg-options --pinentry-mode=loopback"
+
+# Import and trust the GPG Keys
+gpg --passphrase $PASSPHRASE --no-tty --batch --import /gpg_keys/*.priv.asc
+echo "$FINGERPRINT:6:" | gpg --import-ownertrust
+
+mkdir -p /cache/archive
+
+# Restore the Backup
+duplicity restore \
+ $CONNECTION_OPTIONS \
+ "$BACKUP_STORAGE" /data/
diff --git a/images/backup/gpg_keys/backups.pub.key b/images/backup/gpg_keys/backups.pub.key
new file mode 100644
index 0000000..b7377e3
--- /dev/null
+++ b/images/backup/gpg_keys/backups.pub.key
@@ -0,0 +1,108 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQINBFaz16gBEADdz43pCXw9r4NsJlnXJLALg+gRpNRNMzsNQgW6EojR9dx0bnIM
+nGl2wGhFIXEtRlFpFRRymle3CGQuOU8L7okDAMur+vWZjrIYC6H0ZEVeNnTS8Xqb
+aWGOio0OliITWbU/OP5QWDujLGSlrnT5IjCWrkugXnul9M55iFJGc7brAVIaNX0J
+0tXI33prPqgwJBaPj6tLigvwJiIyw6/AwVq/x6AvFYjWBvAIQTmU62Vg5R2/ptJF
+Mm2JjI4HS9lcc0gFayQaOI0JoyhWjG1u3qEdzeL5PZYmCTg9/OWWGfHgUQZVW3n3
+8dPrwbDXhKBWI2n7lmD6V4dZrZlWlkYgxYYXJK6RlX2hT4wO/Z9Ph9+Ghx3mwhIG
+24o5c3QZ6ytckVzZN8PqGy8MI5EbQjENyDv63bKCxBE85JN2/p014WQNWs8sqyxq
+q1FVhzHAxYOv1yLCpBJ+LheehRYVZ1rezh6U7+O3YC2IHWk+cvK/Pj6daLqnjWCB
+G8WKGT9JjhkJ3EUIVfWpuhFxpQRj0KEjr0beo4kyz+I/XnEMKqHxSgj8QzlV3BXw
+jvR5YUeopQlJnWbG+n2uBAbUV4uUgdiio/Q887T0ErDsR1QveSAeNlEbebSqbGJ2
+vunqCkzTV7TV2W3Essy98mkUI58XVfAFcaZK+i3s5MPCvR2GsZMrIEiwyQARAQAB
+tCBUaWxsIEjDtnBwbmVyIDx0aWxsQGhvZXBwbmVyLndzPokCNAQTAQoAHgUCVrPX
+qAIbAwMLCQcDFQoIAh4BAheAAxYCAQIZAQAKCRBNedttu4FzSfnuD/4u/VXRvggw
+JLyVzn90nLvXMnoRrsC26cKeIxCtKFDoBgKr1EItu1wDboL/EXznAGPYbISmnkrS
+47EDtcUbdUsTbmHHUrBK30uhR6QpVm0IMXBUlTNW4SEqK1q1E7+Ll/zQfUhieOyw
+7Gskar3uvcYWwC0ZD8yoyH1eWmxIb1klix9zDQy8nrwChk2GeU5LS6Iqs6wFzurM
+ePWE0HtgpghNO4+NYveVI5kc+/guD3cj01vvcP+huRmVbsrokMQnpvB1a1vk1ygS
+9vlAKdAWfUIZJHyjtRWgCnmIZTEUmD4CrMUduO+XBlesma6Wzk4BP1njYLSdvXp/
+2TJhg8sIeYGQ1DV8AI5Rdhket19xmIKwexCk9U7qmzLZf3EkSJQ7rHrY9xWwgLty
++oT6CXl8e0T1/ORKDu1Pw9dy6I2pReJ35KxrHS4lTmTGpQRpl1bnHbDMfQphJ3rv
+7sVXKFFjnVA6ISY8XXT1KAQiwzhExXkexaOxeKqNWf1SPxoa7gPWButSq+GdsYTy
+qNb9Jjrfc4WeL+JIOEUNE5mOmIQBXLtekrCnL2nULsQ4rCgMs0uhHtY0cYofxl7n
+wYXy+fXJZIIIXkCohswc17CnvxvSkI4MiqkEMbwE1PrXpX3jO9PLxw0skkD4WFz7
+9tL8BJgsN/HHtuyVh/8PDNcVMgGG3jeAALkBDQRWs9eoAQgAxwDVGhzQhP5PxKQR
+n+L+xseJR3X8YLcR6uSge6M0tykbA/MVyu7635GnG6sLpXcKQIxJObqZltw6cr0f
+9RzlytV5YztSQjKWLWGsE6BzJYIAy07pC7hTpERLssIqmAcJSX7pqR4vzt3uTA2U
+t6mlVa1KEUpMx20PBL3+nH0Q9pzQKRW0a5KF1Zy/Fyq0HXI58RTzHdZ6EMFuFT8P
+D51N2S7iKYmJUipSJxroHcjFDgqT+fyYX+xDS/J+Jo/EhSRgLPyal+PAeXMwrs91
+M8UgXs86LNdAhUQuFCCOatb23dCmK/RrnaGZpxFomnT04soTPrz5VDSoCmWJsfe9
+ZiKE2wARAQABiQNEBBgBCgAPBQJWs9eoBQkPCZwAAhsMASkJEE152227gXNJwF0g
+BBkBCgAGBQJWs9eoAAoJEBvFPxqa7V/hYHUH/0fsv2UqIaVHiVMsaP0kb4sR4NaG
+2EO0BnSPBfudNwLMouXaPQP1YsxciSNQnggPAAGKxnCFop/uv3YHOQkA7lO6f8kW
+Oyp9ov0KA6V/gEGPHzvuV3IaI1aFx0snFMxinIAI593Bmc3+u2WjkhrE51tZzHgY
+bys5vJ8eOfQY0Gv39IguCTRhJwSXtH3HaoCH7UvbDEs8479AQAJHP1Ug6LB75bj1
+ApktZ0k65+4fwShHRdqRsPoBq4YXAhHrOeJNjJ4jgdlBXj42gQvEaFnhTozwKRxa
+JsK5n/4JtyhJQw/jJ8m/plRrxdDFQc/cmB2eP9/gvD3+FiO66rYIhzOHLaPYhw//
+YRsU07mOGO2IxdEWxMIikWdWlO+/QHCqXKHQWHSx/DtpNn8GDl/O2pvzwvZMOdlP
+qB5nQ/Fuer2HpWgAo+N9cEbo+n4kbtcQCG69s+nqU85R3bpiVvg8MR6lfqjKoAsz
+jsNhK9HoA4ydo4/dBuvjAvjOuDM7OWzolxRWrgDIndtl2NJaXy1T7hL1SNgw+rXc
+BvRK62/YvC+V+NfV03qMJijPAJCyeFvqIZzQbrUy3bsIi756p9xQ+1jroHgc8+uh
+yr7vLWUmCD8R6Nueq2iz8i6hueMp6PFrpAI9Hxz4tmTYG7QkFc0T3RViv+6Z+GAT
+11iGhvidaYzP2KCf30XKhcvpQ6d8DbbPtbm/m2pmZWRJe4McJ/KPcRbkadLJviig
+db2tABU+7XyQ7wQgbkEQ4DGtu+89DWi1KKbAzHi6i+WgUQCnRZs47SMejrKHh6Ll
+hf4WvxlETH5VIQzWczYJQftsC66ZtPy7KvYQr0RozjgSihOwxJHTsTC0KC1qbo01
+8DmIC+/t2jIRn2xwxkl1gBmUQuL/17vSPA/Km73RtwwTRqsQO1RruZSG5FaE3RpU
+RmL+uXecN702KoBVM5ZO4tBUT5515Kevm0r6NfXUhiQpJHjbfA8EVhdxXfaySlXs
+VwvwOiKqXmursB0Z8ijTYmjOQVVdKq8GtR8djT+TVHS5AQ0EVrPXqAEIAKyKjFwN
+59K3nUM43T+it3nvQR4rfNvGqPSwdsEKiwy/QXmwOnOnjva1onztsIgj5XURfYU0
+5hTP/Dy1WBbqpfidtKr43SowN+SWE6/MJfOUyNjG82FV8c1uJZjH+I+EWYoWFsdS
+R5cattyKv+vNU6ALvV61FXq6oZIeD0bJ2pgYr9h9b1QNhBTiqo/IgaapujSs13kd
+F4V5etvIX8UVG6vZL9V95KcAmoy2xpoMKhID7O4OdCJ98+jgguOsxOXXmnkWSTdE
+Zt756IlnUZvgeQhCGNjTy7LV7vzZiSm/eoe17mBj91TM5aPUDGAOGTq883Lybvew
+yKauMP9whdB8P00AEQEAAYkDRAQYAQoADwUCVrPXqAUJDwmcAAIbIgEpCRBNedtt
+u4FzScBdIAQZAQoABgUCVrPXqAAKCRDQ6RnifYkVFzGlB/9F1tR1Wchpa42kjEsJ
+nYFxKKOLUd6Kb6+G9r+W4EpTpsBnLPtG++NMUtKJeokFVgjgpwX45BJ2HFdt4De+
+zT4uPLT/hoLPDwmRKLAHs48Z1yJTIhfmXIe40LXFBjEF78D3CVtSO91Tdb0xP8j0
+c0LuL2X3G8X1Fq/G0YG1aEVNfNJ23OrWLejnty4rQH40PA2ZtyBDVhMlB6fQl2mG
+XkzWfZewjer5ktj7y3e5cQd5xza/UBpE3rcHDyASGT4ZMFdsdqCcYqo12K//5qHk
+d6DTeTE7O2ufe23XU4VKwS9q5Vq1TWmDcpVAZzX+qj9V9T/kNpwWVWXKhwU1nicQ
+0qXbXlQQAM24sZK9w3nc+cO570r2w8qee7/z/JeMp/ff7fcZiYYslCBXWYXmRqge
+FlydB3ZR4CCOiQ36zm65EepsmhYZjHAQcXxgT36j+WMwZ9Aq4w4GfibyZsLX8ihY
+BaxWtppsDbcNNVLIfcWWKTVTpYbxLBecAp3TN94tcTdr9RCSFRnx6Ok2rk09/qNG
+3HH7H1lLCGiNuhWcDP+/IBZRIv6Wgi/SIpdm7viSxF/0PwQOzicxuzaGT0JfcMqq
+/W5ysy31xwBROvoH3Ur3cPpJ2YaVhoAE9B95NXoCj3lbkLMdyO/QKvszUmJ375cJ
+u84lOEV2v/naT/WzrHTMczvpRnIWDhq47jyYOU8o5pPLuYG7W/a4cVCMxvZGBg4X
+xwqwWE5gieX3JWRZ9K4VsOm1LDVDJheanF9OBHWW8hM6M9olSEAKOMUR5V/hr8bH
+GEroPGiVUft83GkaYsTDr/GHuYQl2Mx2z4RmY4E8JDk+aHKy0Enqnf4BDa7PWBWw
+aF1dxN+GUrtpie4E8yEoFMGvY5pV3YPn5mJkevneJr3IxyNGD662IWjmRGDv/DiJ
+Q2p0dhxM2zar0IrUNmMpZiERmV/s7aoSapB/EFVEtdpa6AjV91Iwy3c/SlbQR+qc
+McVF7p7OaPwqWrpiyvUA510k2XghXZb/Tbml557xDpIaubPDlTcKuQINBFcVTowB
+EACWlRSVk9/N6+QOTkYEumhzPUgTbNqjaQDLdf8o3vYwKe990EHy+Nj9rJ3YvY/M
+WOp/9FAT4Rig/KdFOaDV11lyDoY1XWZLNHPSgIBNdn6esG6fj66WgbrryhcklQ2i
+pdBMLnnudY9WD+65cWcbCFWxJ9w9ylLij6ZcS7Rr9ITFKL0RuHlgfG+JmTMlsVAf
+ClLXOkAwK+rmP7+LIg+mfJxsxNoXudWSBkZeM5bXRYUebjO6/ReC5ouDtjUvFiR/
+mvQAve3g9nAA7csYHAaMs9Fan/7oZOTq/SGwBHTmllvIjKuUgayzOKO6IdwZWdXi
+xlrS6ogDmU/Uy6QWHaR40O6vbYNuc4W3ZvVsODtkojYI8Tw2Iw35ceKRKMAegWrx
+eucCPff9rtdyv1460J5cGb0SqdrLBKWdZh7BZPSJP3GQvT1bn1FACevbUMgkkLBL
+hbtrQ3+Vysz8i0vcZSSKmfu+j7TnskR88efOl/t8ZDi5IiZ9ClljuiJpNmrMT519
+YQsbK1HClBE/trvDLDRKXZ0J1ow6VmKoLvD7cDWGN9O5ESpf6PaIGYmmZmSoBmnC
+pqEgw0RPF7GWp/aPBW+f/+6fL/Tvx/l5zZ8OUpstXPt5tzitgPkBlEtHpKvHjidg
+xSDnImwFJqZPtGzKtxk2mvbRdjnkYokblKIL/D9/z9f3twARAQABiQREBBgBCAAP
+BQJXFU6MAhsCBQklmAYAAikJEE152227gXNJwV0gBBkBCAAGBQJXFU6MAAoJEGoT
+MnIlvlH2CIcP/31+3oB3prfzDR8j5IJAil69mi0Nven10o6tuCl/WWxBFa/RLVUT
+gj1WhhY0NF5HD0rXvnmW/7rh+xhEOEu2Wj+XrNH6uWXuHm5nZFP+fv+MhOOgjamI
+wfgAtGW4CNWIizaDlcb7XbRhUmso+r6Rg+TxIGamBVJbcpYeiSQeYLTBRtEGN4+C
+yVs4jXkg6UhILYZ37FlW26aOrp8imbubrM7Jk22/QCdBrlt0781Eb+Yl7E/qzP6S
+iBW2fz4HPq+rEW0LFMaKv1xAZyoh/vMtwG+O/XZcX6O5eX+HAR/nVK6dqnY5nZxC
+aDxPURdECBFBzZ1/QYYT9s6sBHPQLr6Osh+toMD4jA/gem7Fw+5pzcMd2+rB1UHm
+tX/vpHjJfdHzZrL94csxkZLGlf3FQKNoaUf205NTPlMw6VQH8IRnpMqeisQPkrIZ
+6glduViV8jDZhUxmRQGq/DFU9NDqDcaggI9JHV8fkko6mmQ6lgarU7g10bbWXISf
+D/7yravx8vZ3F4AMwjCEgKgRW7JSE0UTRShyY+JGfrXQeTJTeovli0VEma5Lmub0
+4O68Rpu3aCjAt8zfe4KMp9fUfBDnmjDMPH7ISOwxd9FEQuFjHHMFghfpdLbfU+4O
+eSxOAFcH8ry3d98AGBSxHgz9igZV9CxNsfaisA3yeSKwYSDhg4CQny7j1H8P/120
+HW1kwhnSPHOa98l8rDUkhxyqx2Z1tdJFsrPiwgocaJoasEGKBS+dlPUeKtM4TU91
+rbKQDYRmB9IQ2DqarpyeD3BryB9vOv2UnZpKmJUHvS6V4igXLvr2vzWj4xarlhd6
+e5KdKaCoKi8VYWm+Jw7fLKsTh6owU1imWCL8QtbqBPRNsxNfB1pLx3EDHQn6P72d
+lzKiPZxLB8ES4m2khmjOYhVRxrI93Mj4TC32rsnQmAySYQERix9Z8hI7wsy+kNjc
+gS9oBqxIS9hg3kxy3WA8rJL3joq1qMaEKrxb85V1MVSJhaSc71Q+bIVqtizJeeCb
+wEbjXYIRwJonUG1wcFuR85CuaPczI1UKHw/tsWTUw9iwpMZBy/jDXSFYMvG6Nxly
+1BrVVwrI+xJSbD4Lv0YkD0DnRiIQx8QBycM+p04C1dpOLQxm/vCvydBvk/BnZjDu
+wQeDAhoP3M6V3kQa7U193cyXykA5DZlyYWq6hRbtbrwsE+lmCQZe/5tt9YirpnYa
+fg74qfIXBeZzldDjQegFxirc4Um5X1Hd46f/pOUHjUgptbsrq5quFsqxg9sbFsoq
+iCKmeLPFqz1HxbRcxNHJeqMI2IOLRG6Fzzds0kojn7fKuTK0OJ0Q9YnZK0WoKhET
+PYlxffxSeiu+q09NhlUdkY5aG/cWQ4QOcPhoFAQw
+=ZkCc
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/images/backup/restore.yml b/images/backup/restore.yml
new file mode 100644
index 0000000..6640b26
--- /dev/null
+++ b/images/backup/restore.yml
@@ -0,0 +1,16 @@
+version: '3'
+
+services:
+ backup:
+ env_file:
+ - config.env
+ build: ./duplicity
+ command: /bin/sh /restore.sh
+ hostname: duplicity
+ restart: "no"
+ volumes:
+ - ./restored:/data
+ - ./gpg_keys:/gpg_keys
+
+volumes:
+ cache: