From 6e4fc5c205c5ab2d733137d94ecdd4d21a426419 Mon Sep 17 00:00:00 2001
From: Michiel de Jong <michiel@unhosted.org>
Date: Tue, 4 Nov 2014 14:27:07 +0000
Subject: [PATCH] merge backups branch

---
 deploy/add-site.sh           | 17 +++++++++--------
 deploy/onServer.sh           |  2 +-
 doc/deploying-a-server.md    | 14 +++++++++++++-
 importers/backup-init.sh     | 20 ++++++++++++++++++++
 importers/backup-snapshot.sh | 30 ++++++++++++++++++++++++++++++
 unit-files/backup@.service   |  8 ++++++++
 unit-files/backup@.timer     |  8 ++++++++
 unit-files/mysql@.service    |  2 ++
 8 files changed, 91 insertions(+), 10 deletions(-)
 create mode 100755 importers/backup-init.sh
 create mode 100755 importers/backup-snapshot.sh
 create mode 100644 unit-files/backup@.service
 create mode 100644 unit-files/backup@.timer

diff --git a/deploy/add-site.sh b/deploy/add-site.sh
index 882b64f..2afb641 100755
--- a/deploy/add-site.sh
+++ b/deploy/add-site.sh
@@ -1,21 +1,22 @@
 #!/bin/sh
-if [ $# -ge 4 ]; then
+if [ $# -ge 5 ]; then
   SERVER=$1
   DOMAIN=$2
   PEMFILE=$3
-  GITREPO=$4
+  IMAGE=$4
+  GITREPO=$5
 else
-  echo "Usage: sh ./deploy/add-site.sh server domain pemfile gitrepo [user]"
+  echo "Usage: sh ./deploy/add-site.sh server domain pemfile image gitrepo [user]"
   exit 1
 fi
-if [ $# -ge 5 ]; then
-  USER=$5
+if [ $# -ge 6 ]; then
+  USER=$6
 else
   USER="core"
 fi
-echo "Adding $DOMAIN to $SERVER with cert from $PEMFILE"
+echo "Adding $DOMAIN to $SERVER, running $IMAGE behind $PEMFILE and pulling from $GITREPO"
 echo "Remote user is $USER"
 
-ssh $USER@$SERVER sudo mkdir -p /data/per-user/$DOMAIN/nginx/data
+ssh $USER@$SERVER sudo mkdir -p /data/per-user/$DOMAIN/$IMAGE/data
 scp $PEMFILE $USER@$SERVER:/data/server-wide/haproxy/approved-certs/$DOMAIN.pem
-ssh $USER@$SERVER sudo sh /data/indiehosters/scripts/activate-user.sh $DOMAIN nginx $GITREPO
+ssh $USER@$SERVER sudo sh /data/indiehosters/scripts/activate-user.sh $DOMAIN $IMAGE $GITREPO
diff --git a/deploy/onServer.sh b/deploy/onServer.sh
index 4642278..95f0283 100755
--- a/deploy/onServer.sh
+++ b/deploy/onServer.sh
@@ -4,7 +4,7 @@ echo Starting etcd:
 /usr/bin/coreos-cloudinit --from-file=/var/lib/coreos-install/user_data
 
 echo Cloning the indiehosters repo into /data/indiehosters:
-mkdir /data
+mkdir -p /data
 cd /data
 git clone https://github.com/indiehosters/indiehosters.git
 cd indiehosters
diff --git a/doc/deploying-a-server.md b/doc/deploying-a-server.md
index 88c4471..6d47c58 100644
--- a/doc/deploying-a-server.md
+++ b/doc/deploying-a-server.md
@@ -18,6 +18,12 @@ Make sure you read [getting started](getting-started-as-a-hoster.md) first.
 * Add the default site by following the 'Adding a website to your server' instructions below with domain name k3 instead of example.com
 * The rest should be automatic!
 
+### Preparing backups
+
+* ssh into your server, and run `ssh-keygen -t rsa`
+* set up a backups server at an independent location (at least a different data center, but preferably also a different IaaS provider, the bu25 plan of https://securedragon.net/ is a good option at 3 dollars per month).
+* set up a git server with one private git repo per domain by following http://www.git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-the-Server (instead of 'project.git' you can use 'domainname.com.git')
+
 ### Adding a website to your server
 * For each site you want to deploy on the server, e.g. example.com, do the following:
   * Does example.com already exist as a domain name?
@@ -38,8 +44,14 @@ Make sure you read [getting started](getting-started-as-a-hoster.md) first.
     (from StartSSL or elswhere) for example.com and concatenate the certificate
     and its unencrypted private key into `indiehosters/user-data/example.com/tls.pem`
   * Make sure the TLS certificate is valid (use `scripts/check-cert.sh` for this).
-  * Now run `deploy/add-site.sh k3 example.com ../hoster-data/TLS/example.com.pem https://github.com/someone/example.com.git root`.
+  * Now run `deploy/add-site.sh k3 example.com ../hoster-data/TLS/example.com.pem nginx https://github.com/someone/example.com.git root`.
     It will make sure the server is in the correct state, and git pull and scp the user data and the
     approved cert into place, start a container running the image requested, update haproxy config, and restart the haproxy container.
+  * set up a git repo for the new site on the backup server (see http://www.git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-the-Server again), and for instance if you called the backup repo example.com.git and your backup server is in /etc/hosts on k3 as 'bu25', ssh into k3 and run:
+
+    echo "git@bu25:/opt/git/example.com.git" > /data/per-user/example.com/backup/BACKUPDEST
+    USER=example.com
+    /data/indiehosters/importers/backup-init.sh
+
   * Test the site using your /etc/hosts. You should see the data from the git repo on both http and https.
   * Switch DNS and monitoring.
diff --git a/importers/backup-init.sh b/importers/backup-init.sh
new file mode 100755
index 0000000..2ee2ab9
--- /dev/null
+++ b/importers/backup-init.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+echo initializing backups for $USER
+mkdir -p /data/per-user/$USER/backup/mysql
+mkdir -p /data/per-user/$USER/backup/www
+git config --global user.email "backups@`hostname`"
+git config --global user.name "`hostname` hourly backups"
+git config --global push.default simple
+
+cd /data/per-user/$USER/backup/
+git init
+echo "backups of $USER at IndieHosters server `hostname`" > README.md
+git add README.md
+git commit -m"initial commit"
+
+if [ -e /data/per-user/$USER/backup/BACKUPDEST ]; then
+  cd /data/per-user/$USER/backup/
+  git remote add destination `cat /data/per-user/$USER/backup/BACKUPDEST`
+  git push -u destination master
+fi
diff --git a/importers/backup-snapshot.sh b/importers/backup-snapshot.sh
new file mode 100755
index 0000000..481cf56
--- /dev/null
+++ b/importers/backup-snapshot.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+if [ -e /data/per-user/$USER/mysql ]; then
+  echo backing up mysql databases for $USER
+  mkdir -p /data/per-user/$USER/backup/mysql/
+  cp /data/per-user/$USER/mysql/.env /data/per-user/$USER/backup/mysql/.env
+  /usr/bin/docker run --link mysql-$USER:db\
+     --env-file /data/per-user/$USER/mysql/.env \
+     indiehosters/mysql mysqldump --all-databases --events -u admin \
+     -p$(cat /data/per-user/$USER/mysql/.env | cut -d'=' -f2) \
+     -h db > /data/per-user/$USER/backup/mysql/dump.sql
+fi
+
+if [ -e /data/per-user/$USER/wordpress-subdir ]; then
+  echo backing up www from wordpress-subdir for $USER
+  mkdir -p /data/per-user/$USER/backup/www/wordpress-subdir/
+  cp /data/per-user/$USER/wordpress-subdir/.env /data/per-user/$USER/backup/www/wordpress-subdir/.env
+  rsync -r /data/per-user/$USER/wordpress-subdir/data/wp-content /data/per-user/$USER/backup/www/wordpress-subdir/wp-content
+  if [ -e /data/per-user/$USER/wordpress-subdir/data/GITURL ]; then
+    cp /data/per-user/$USER/wordpress-subdir/data/GITURL /data/per-user/$USER/backup/www/wordpress-subdir/GITURL
+  fi
+fi
+
+cd /data/per-user/$USER/backup/
+git add *
+git commit -m"backup $USER @ `hostname` - `date`"
+if [ -e /data/per-user/$USER/backup/BACKUPDEST ]; then
+  git pull --rebase
+  git push
+fi
diff --git a/unit-files/backup@.service b/unit-files/backup@.service
new file mode 100644
index 0000000..2b9175d
--- /dev/null
+++ b/unit-files/backup@.service
@@ -0,0 +1,8 @@
+[Unit]
+Description= Back up mysql and www data to a git repo and optionally push it out
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+Environment=USER=%i
+ExecStart=/data/indiehosters/importers/backup-snapshot.sh
diff --git a/unit-files/backup@.timer b/unit-files/backup@.timer
new file mode 100644
index 0000000..7a91ced
--- /dev/null
+++ b/unit-files/backup@.timer
@@ -0,0 +1,8 @@
+[Unit]
+Description=Hourly backup of www and mysql content to a git repo
+
+[Timer]
+OnUnitActiveSec=1h
+
+[Install]
+WantedBy=timers.target
diff --git a/unit-files/mysql@.service b/unit-files/mysql@.service
index f1d6da9..ec7a927 100644
--- a/unit-files/mysql@.service
+++ b/unit-files/mysql@.service
@@ -4,10 +4,12 @@ Description=%p-%i
 # Requirements
 Requires=docker.service
 Requires=%p-importer@%i.service
+Requires=%p-dump@%i.timer
 
 # Dependency ordering
 After=docker.service
 After=%p-importer@%i.service
+Before=%p-dump@%i.timer
 
 [Service]
 Restart=always
-- 
GitLab