From 472ac25617d58f56827c09ad05b74b0e5b3c821e Mon Sep 17 00:00:00 2001 From: Derek Smith Date: Sat, 8 Oct 2022 12:44:46 -0400 Subject: [PATCH] Backup/Restore kinda working. --- defaults.sh | 2 +- deploy.sh | 23 +++---- deployment/www/backup_path.sh | 32 ++------- deployment/www/go.sh | 22 ++----- deployment/www/restore.sh | 19 ------ deployment/www/restore_path.sh | 28 ++++++++ deployment/www/stop_docker_stacks.sh | 35 +++++++++- deployment/www/stub/ghost_yml.sh | 12 +++- deployment/www/stub/gitea_yml.sh | 8 +-- deployment/www/stub/nextcloud_yml.sh | 6 +- deployment/www/stub/nginx_config.sh | 98 ++++++++++++++++++---------- deployment/www/stub/nginx_yml.sh | 26 +++++--- domain_env.sh | 3 + reset_env.sh | 2 +- 14 files changed, 183 insertions(+), 133 deletions(-) delete mode 100755 deployment/www/restore.sh create mode 100755 deployment/www/restore_path.sh diff --git a/defaults.sh b/defaults.sh index e3ef5ea..6190325 100755 --- a/defaults.sh +++ b/defaults.sh @@ -7,7 +7,7 @@ export WWW_SERVER_MAC_ADDRESS= export DEPLOY_BTCPPAY_SERVER=false export DEPLOY_GHOST=true -export DEPLOY_NOSTR=false +export DEPLOY_NOSTR_RELAY=false export DEPLOY_ONION_SITE=false export DEPLOY_NEXTCLOUD=false export DEPLOY_GITEA=false diff --git a/deploy.sh b/deploy.sh index 8529bc3..7ac22a9 100755 --- a/deploy.sh +++ b/deploy.sh @@ -27,16 +27,14 @@ fi DOMAIN_NAME= RESTORE_ARCHIVE= VPS_HOSTING_TARGET=lxd -RUN_CERT_RENEWAL=false - +RUN_CERT_RENEWAL=true RESTORE_WWW=false -BACKUP_CERTS=true -BACKUP_GHOST=true -RESTORE_BTCPAY=false +BACKUP_CERTS=false +BACKUP_APPS=false BACKUP_BTCPAY=false +RESTORE_BTCPAY=false MIGRATE_WWW=false MIGRATE_BTCPAY=false - USER_SKIP_WWW=false USER_SKIP_BTCPAY=false UPDATE_BTCPAY=false @@ -53,13 +51,14 @@ for i in "$@"; do ;; --restore-www) RESTORE_WWW=true - BACKUP_GHOST=false + BACKUP_APPS=false RUN_CERT_RENEWAL=false shift ;; --restore-btcpay) RESTORE_BTCPAY=true BACKUP_BTCPAY=false + RUN_CERT_RENEWAL=false shift ;; --backup-certs) @@ -87,7 +86,7 @@ for i in "$@"; do shift ;; --backup-ghost) - BACKUP_GHOST=true + BACKUP_APPS=true shift ;; --backup-btcpay) @@ -130,7 +129,7 @@ export RESTORE_ARCHIVE="$RESTORE_ARCHIVE" export RESTORE_WWW="$RESTORE_WWW" export BACKUP_CERTS="$BACKUP_CERTS" -export BACKUP_GHOST="$BACKUP_GHOST" +export BACKUP_APPS="$BACKUP_APPS" export RESTORE_BTCPAY="$RESTORE_BTCPAY" export BACKUP_BTCPAY="$RESTORE_BTCPAY" export MIGRATE_WWW="$MIGRATE_WWW" @@ -426,15 +425,13 @@ function stub_site_definition { export DOMAIN_NAME="${DOMAIN_NAME}" export SITE_LANGUAGE_CODES="en" export DUPLICITY_BACKUP_PASSPHRASE="$(new_pass)" -# AWS only -#export DDNS_PASSWORD= #export BTCPAY_HOSTNAME_IN_CERT="store" export DEPLOY_GHOST=true export DEPLOY_NEXTCLOUD=true -export DEPLOY_NOSTR=false +export DEPLOY_NOSTR_RELAY=false export NOSTR_ACCOUNT_PUBKEY="CHANGE_ME" export DEPLOY_GITEA=false -export DEPLOY_ONION_SITE=false +#export DEPLOY_ONION_SITE=false export GHOST_MYSQL_PASSWORD="$(new_pass)" export GHOST_MYSQL_ROOT_PASSWORD="$(new_pass)" export NEXTCLOUD_MYSQL_PASSWORD="$(new_pass)" diff --git a/deployment/www/backup_path.sh b/deployment/www/backup_path.sh index 4e07848..a797f87 100755 --- a/deployment/www/backup_path.sh +++ b/deployment/www/backup_path.sh @@ -3,53 +3,29 @@ set -eux cd "$(dirname "$0")" - -#$1 should be the app path (ghost,nextcloud,gitea) -#$2 should be the domain to backup - -if [ -z "$1" ]; then - echo "ERROR: the app path was not specified." - exit 1 -fi - # TODO: We are using extra space on the remote VPS at the moment for the duplicity backup files. # we could eliminate that and simply save duplicity backups to the management machine running the script # this could be done by using a local path and mounting it on the remote VPS. # maybe something like https://superuser.com/questions/616182/how-to-mount-local-directory-to-remote-like-sshfs -REMOTE_BACKUP_PATH="$REMOTE_HOME/backups/www/$DOCKER_STACK_SUFFIX-$LANGUAGE_CODE" -REMOTE_BACKUP_LOCATION="$REMOTE_BACKUP_PATH/$1/$DOMAIN_NAME" - # step 1: run duplicity on the remote system to backup all files to the remote system. # --allow-source-mismatch -REMOTE_SOURCE_BACKUP_PATH="$REMOTE_HOME/$1/$DOMAIN_NAME" # if the source files to backup don't exist on the remote host, we return. -if ! ssh "$PRIMARY_WWW_FQDN" "[ -d $REMOTE_SOURCE_BACKUP_PATH"; then +if ! ssh "$PRIMARY_WWW_FQDN" "[ -d $REMOTE_SOURCE_BACKUP_PATH ]"; then echo "INFO: The path to backup does not exist. There's nothing to backup! That's ok, execution will continue." exit 0 fi -ssh "$PRIMARY_WWW_FQDN" sudo PASSPHRASE="$DUPLICITY_BACKUP_PASSPHRASE" duplicity "$REMOTE_SOURCE_BACKUP_PATH" "file://$REMOTE_BACKUP_LOCATION" -ssh "$PRIMARY_WWW_FQDN" sudo chown -R ubuntu:ubuntu "$REMOTE_BACKUP_LOCATION" - +ssh "$PRIMARY_WWW_FQDN" sudo PASSPHRASE="$DUPLICITY_BACKUP_PASSPHRASE" duplicity "$REMOTE_SOURCE_BACKUP_PATH" "file://$REMOTE_BACKUP_PATH" +ssh "$PRIMARY_WWW_FQDN" sudo chown -R ubuntu:ubuntu "$REMOTE_BACKUP_PATH" SSHFS_PATH="/tmp/sshfs_temp" mkdir -p "$SSHFS_PATH" # now let's pull down the latest files from the backup directory. # create a temp directory to serve as the mountpoint for the remote machine backups directory -sshfs "$PRIMARY_WWW_FQDN:$REMOTE_BACKUP_LOCATION" "$SSHFS_PATH" - -# ensure our local backup path exists so we can pull down the duplicity archive to the management machine. -LOCAL_BACKUP_PATH="$SITE_PATH/backups/www/$BACKUP_TIMESTAMP" -if [ "$1" = letsencrypt ]; then - LOCAL_BACKUP_PATH="$SITE_PATH/backups/www/letsencrypt" -fi - -if [ ! -d "$LOCAL_BACKUP_PATH" ]; then - mkdir -p "$LOCAL_BACKUP_PATH" -fi +sshfs "$PRIMARY_WWW_FQDN:$REMOTE_BACKUP_PATH" "$SSHFS_PATH" # rsync the files from the remote server to our local backup path. rsync -av "$SSHFS_PATH/" "$LOCAL_BACKUP_PATH/" diff --git a/deployment/www/go.sh b/deployment/www/go.sh index 6eaba49..41744e8 100755 --- a/deployment/www/go.sh +++ b/deployment/www/go.sh @@ -55,7 +55,7 @@ for DOMAIN_NAME in ${DOMAIN_LIST//,/ }; do fi fi - if [ "$DEPLOY_NOSTR" = true ]; then + if [ "$DEPLOY_NOSTR_RELAY" = true ]; then if [ -z "$NOSTR_ACCOUNT_PUBKEY" ]; then echo "ERROR: Ensure NOSTR_ACCOUNT_PUBKEY is configured in your site_definition." exit 1 @@ -85,24 +85,10 @@ for DOMAIN_NAME in ${DOMAIN_LIST//,/ }; do TOR_CONFIG_PATH= - if [ "$DEPLOY_NEXTCLOUD" = true ]; then - ssh "$PRIMARY_WWW_FQDN" "mkdir -p $REMOTE_NEXTCLOUD_PATH/db/data" - ssh "$PRIMARY_WWW_FQDN" "mkdir -p $REMOTE_NEXTCLOUD_PATH/db/logs" - ssh "$PRIMARY_WWW_FQDN" "mkdir -p $REMOTE_NEXTCLOUD_PATH/html" - fi - - done ./stop_docker_stacks.sh -if [ "$RESTORE_WWW" = true ]; then - # Generally speaking we try to restore data. But if the BACKUP directory was - # just created, we know that we'll deploy fresh. - ./restore.sh -fi - - if [ "$DEPLOY_ONION_SITE" = true ]; then # ensure the tor image is built docker build -t tor:latest ./tor @@ -129,7 +115,13 @@ if [ "$DEPLOY_ONION_SITE" = true ]; then fi bash -c ./stub/nginx_yml.sh + +sleep 3 + bash -c ./stub/ghost_yml.sh + +sleep 3 + bash -c ./stub/gitea_yml.sh diff --git a/deployment/www/restore.sh b/deployment/www/restore.sh deleted file mode 100755 index 3c6e65b..0000000 --- a/deployment/www/restore.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -set -exu - -# first, this is a restore operation. We need to ask the administrator -# if they want to continue because it results in data loss. -# indeed, our first step is the delete the home directory on the remote server. - -# delete the home directory so we know we are restoring all files from the duplicity archive. -ssh "$PRIMARY_WWW_FQDN" sudo rm -rf "$REMOTE_HOME/*" - -# scp our local backup directory to the remote machine -ssh "$PRIMARY_WWW_FQDN" mkdir -p "$REMOTE_BACKUP_PATH" - -# TODO instead of scp the files up there, lets' mount the local backup folder to a remote folder then just run a duplicity restore. -scp -r "$LOCAL_BACKUP_PATH" "$PRIMARY_WWW_FQDN:$REMOTE_BACKUP_PATH" - -# now we run duplicity to restore the archive. -ssh "$PRIMARY_WWW_FQDN" sudo PASSPHRASE="$DUPLICITY_BACKUP_PASSPHRASE" duplicity --force restore "file://$REMOTE_BACKUP_PATH/$BACKUP_TIMESTAMP" "$REMOTE_HOME/" diff --git a/deployment/www/restore_path.sh b/deployment/www/restore_path.sh new file mode 100755 index 0000000..82d116e --- /dev/null +++ b/deployment/www/restore_path.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +set -eux +cd "$(dirname "$0")" + +FILE_COUNT="$(find "$LOCAL_BACKUP_PATH" -type f | wc -l)" +if [ "$FILE_COUNT" = 0 ]; then + echo "ERROR: there are no files in the local backup path '$LOCAL_BACKUP_PATH'." + echo "We're going to continue with execution." + exit 0 +fi + +RESPONSE= +read -r -p "Are you sure you want to restore the local path '$LOCAL_BACKUP_PATH' to the remote server at '$PRIMARY_WWW_FQDN' (y/n)": RESPONSE +if [ "$RESPONSE" != y ]; then + echo "STOPPING." + exit 0 +fi + +# delete the target backup path so we can push restoration files from the management machine. +ssh "$PRIMARY_WWW_FQDN" sudo rm -rf "$REMOTE_SOURCE_BACKUP_PATH" + +# scp our local backup directory to the remote machine +ssh "$PRIMARY_WWW_FQDN" "sudo mkdir -p $REMOTE_BACKUP_PATH && sudo chown ubuntu:ubuntu $REMOTE_BACKUP_PATH" +scp -r "$LOCAL_BACKUP_PATH" "$PRIMARY_WWW_FQDN:$REMOTE_BACKUP_PATH" + +# now we run duplicity to restore the archive. +ssh "$PRIMARY_WWW_FQDN" sudo PASSPHRASE="$DUPLICITY_BACKUP_PASSPHRASE" duplicity --force restore "file://$REMOTE_BACKUP_PATH/$BACKUP_TIMESTAMP" "$REMOTE_HOME/" diff --git a/deployment/www/stop_docker_stacks.sh b/deployment/www/stop_docker_stacks.sh index a11caad..4be9d5d 100755 --- a/deployment/www/stop_docker_stacks.sh +++ b/deployment/www/stop_docker_stacks.sh @@ -24,7 +24,26 @@ for DOMAIN_NAME in ${DOMAIN_LIST//,/ }; do sleep 2 fi - ./backup_path.sh "$APP" + # these variable are used by both backup/restore scripts. + export APP="$APP" + export REMOTE_BACKUP_PATH="$REMOTE_HOME/backups/www/$APP/$DOCKER_STACK_SUFFIX-$LANGUAGE_CODE" + export REMOTE_SOURCE_BACKUP_PATH="$REMOTE_HOME/$APP/$DOMAIN_NAME" + + # ensure our local backup path exists so we can pull down the duplicity archive to the management machine. + export LOCAL_BACKUP_PATH="$SITE_PATH/backups/www/$APP/$BACKUP_TIMESTAMP" + + # ensure our local backup path exists. + if [ ! -d "$LOCAL_BACKUP_PATH" ]; then + mkdir -p "$LOCAL_BACKUP_PATH" + fi + + if [ "$RESTORE_WWW" = true ]; then + ./restore_path.sh + + elif [ "$BACKUP_APPS" = true ]; then + # if we're not restoring, then we may or may not back up. + ./backup_path.sh + fi done done done @@ -36,6 +55,8 @@ if docker stack list --format "{{.Name}}" | grep -q reverse-proxy; then # wait for all docker containers to stop. # TODO see if there's a way to check for this. sleep 10 + + docker system prune -f fi # generate the certs and grab a backup @@ -54,7 +75,15 @@ if [ "$BACKUP_CERTS" = true ]; then source "$SITE_PATH/site_definition" source ../../domain_env.sh - ./backup_path.sh "letsencrypt" - done + # these variable are used by both backup/restore scripts. + export APP="letsencrypt" + export REMOTE_BACKUP_PATH="$REMOTE_HOME/backups/www/$APP/$DOCKER_STACK_SUFFIX" + export REMOTE_SOURCE_BACKUP_PATH="$REMOTE_HOME/$APP/$DOMAIN_NAME" + # ensure our local backup path exists so we can pull down the duplicity archive to the management machine. + export LOCAL_BACKUP_PATH="$SITE_PATH/backups/www/$APP/$BACKUP_TIMESTAMP" + mkdir -p "$LOCAL_BACKUP_PATH" + + ./backup_path.sh + done fi diff --git a/deployment/www/stub/ghost_yml.sh b/deployment/www/stub/ghost_yml.sh index 779f1e5..a603d60 100755 --- a/deployment/www/stub/ghost_yml.sh +++ b/deployment/www/stub/ghost_yml.sh @@ -47,9 +47,17 @@ EOL - ${REMOTE_HOME}/ghost/${DOMAIN_NAME}/${LANGUAGE_CODE}/ghost:/var/lib/ghost/content environment: EOL - - cat >>"$DOCKER_YAML_PATH" <>"$DOCKER_YAML_PATH" <>"$DOCKER_YAML_PATH" <>"$DOCKER_YAML_PATH" <>"$NGINX_CONF_PATH" <>"$NGINX_CONF_PATH" <>"$NGINX_CONF_PATH" <>"$NGINX_CONF_PATH" <>"$NGINX_CONF_PATH" <>"$NGINX_CONF_PATH" <>"$NGINX_CONF_PATH" <>"$NGINX_CONF_PATH" < 1 )); then + # we only need this clause if we know there is more than once lanuage being rendered. + cat >>"$NGINX_CONF_PATH" <>"$NGINX_CONF_PATH" <>"$NGINX_CONF_PATH" <>"$NGINX_CONF_PATH" <>"$NGINX_CONF_PATH" <> "$DOCKER_YAML_PATH" <> "$DOCKER_YAML_PATH" <> "$DOCKER_YAML_PATH" <> "$DOCKER_YAML_PATH" <> "$DOCKER_YAML_PATH" <