diff --git a/.gitignore b/.gitignore index 9f0fc34..0fe5335 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ env clear_lxd.sh -publish_tag.sh \ No newline at end of file +publish_tag.sh diff --git a/.vscode/settings.json b/.vscode/settings.json index db1f572..601c1df 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,8 +13,9 @@ "shellcheck.customArgs": [], "shellcheck.ignorePatterns": {}, "shellcheck.exclude": [ - "1090", - "1091" + "SC1090", + "SC1091", + "SC2029" ], "terminal.integrated.fontFamily": "monospace", "workbench.colorCustomizations": { diff --git a/README.md b/README.md index e3e9da8..2670ba4 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # Documentation -All documentation for this project can be found at the [sovereign-stack.org](https://www.sovereign-stack.org). [Click here](https://www.sovereign-stack.org/about) if you are new to Sovereign Stack? \ No newline at end of file +All documentation for this project can be found at the [sovereign-stack.org](https://www.sovereign-stack.org). \ No newline at end of file diff --git a/cluster.sh b/cluster.sh index 6709183..21ef41e 100755 --- a/cluster.sh +++ b/cluster.sh @@ -1,51 +1,50 @@ #!/bin/bash -set -ex +set -eux +cd "$(dirname "$0")" # NOTE This script is meant to be executed on your LXD bare metal servers. This script # ensures that the LXD daemon is installed via snap package, then initialize the daemon # to operate in clustered mode -COMMAND="$1" +COMMAND="${1:-}" DATA_PLANE_MACVLAN_INTERFACE= DISK_TO_USE=loop if [ "$COMMAND" = create ]; then # override the cluster name. - CLUSTER_NAME="$2" + CLUSTER_NAME="${2:-}" if [ -z "$CLUSTER_NAME" ]; then echo "ERROR: The cluster name was not provided." exit 1 fi + #shellcheck disable=SC1091 source ./defaults.sh - export LXD_REMOTE_PATH="$CLUSTERS_DIR/$CLUSTER_NAME" - CLUSTER_DEFINITION="$LXD_REMOTE_PATH/cluster_definition" + export CLUSTER_PATH="$CLUSTERS_DIR/$CLUSTER_NAME" + CLUSTER_DEFINITION="$CLUSTER_PATH/cluster_definition" export CLUSTER_DEFINITION="$CLUSTER_DEFINITION" - mkdir -p "$LXD_REMOTE_PATH" + mkdir -p "$CLUSTER_PATH" if [ ! -f "$CLUSTER_DEFINITION" ]; then # stub out a cluster_definition. cat >"$CLUSTER_DEFINITION" <"$CLUSTER_MASTER_LXD_INIT" <> "$LXD_REMOTE_PATH/authorized_keys" - echo "INFO: Sovereign Stack just stubbed out '$LXD_REMOTE_PATH/authorized_keys'. Go update it." +if [ ! -f "$CLUSTER_PATH/authorized_keys" ]; then + cat "$SSH_HOME/id_rsa.pub" >> "$CLUSTER_PATH/authorized_keys" + echo "INFO: Sovereign Stack just stubbed out '$CLUSTER_PATH/authorized_keys'. Go update it." echo " Add ssh pubkeys for your various management machines, if any. We've stubbed it out" echo " with your ssh pubkey at '$HOME/.ssh/id_rsa.pub'." exit 1 fi if [ "$VPS_HOSTING_TARGET" = lxd ]; then - CLUSTER_DEFINITION="$LXD_REMOTE_PATH/cluster_definition" + CLUSTER_DEFINITION="$CLUSTER_PATH/cluster_definition" export CLUSTER_DEFINITION="$CLUSTER_DEFINITION" ######################################### @@ -127,7 +156,7 @@ if [ "$VPS_HOSTING_TARGET" = lxd ]; then # recommended to run a registry cache on your management machine though. if [ -n "$REGISTRY_URL" ]; then -cat > "$LXD_REMOTE_PATH/registry.yml" < "$CLUSTER_PATH/registry.yml" < "$dbdump_path" + echo "✅ Database dump done." +} || { + echo "🚨 Dumping failed. Please check the error message above." + exit 1 +} + +printf "\nℹ️ Stopping BTCPay Server …\n\n" +btcpay_down + +printf "\n" +cd $docker_dir +echo "ℹ️ Archiving files in $(pwd)…" + +{ + tar \ + --exclude="volumes/backup_datadir" \ + --exclude="volumes/generated_bitcoin_datadir/blocks" \ + --exclude="volumes/generated_bitcoin_datadir/chainstate" \ + --exclude="volumes/generated_bitcoin_datadir/debug.log" \ + --exclude="volumes/generated_litecoin_datadir/blocks" \ + --exclude="volumes/generated_litecoin_datadir/chainstate" \ + --exclude="volumes/generated_litecoin_datadir/debug.log" \ + --exclude="volumes/generated_postgres_datadir" \ + --exclude="volumes/generated_clightning_bitcoin_datadir/_data/lightning-rpc" \ + --exclude="**/logs/*" \ + -cvzf "$backup_path" "$dbdump_name" volumes/generated_* + echo "✅ Archive done." + + if [ ! -z "$BTCPAY_BACKUP_PASSPHRASE" ]; then + printf "\n" + echo "🔐 BTCPAY_BACKUP_PASSPHRASE is set, the backup will be encrypted." + { + gpg -o "$backup_path.gpg" --batch --yes -c --passphrase "$BTCPAY_BACKUP_PASSPHRASE" $backup_path + rm "$backup_path" + backup_path="$backup_path.gpg" + echo "✅ Encryption done." + } || { + echo "🚨 Encrypting failed. Please check the error message above." + printf "\nℹ️ Restarting BTCPay Server …\n\n" + cd "$btcpay_dir" + #btcpay_up + exit 1 + } + fi +} || { + echo "🚨 Archiving failed. Please check the error message above." + printf "\nℹ️ Restarting BTCPay Server …\n\n" + cd $btcpay_dir + #btcpay_up + exit 1 +} + +printf "\nℹ️ Restarting BTCPay Server …\n\n" +cd $btcpay_dir +#btcpay_up + +printf "\nℹ️ Cleaning up …\n\n" +rm $dbdump_path + +printf "✅ Backup done => $backup_path\n\n" diff --git a/deployment/btcpayserver/btcpay-restore.sh b/deployment/btcpayserver/btcpay-restore.sh new file mode 100644 index 0000000..79e2d20 --- /dev/null +++ b/deployment/btcpayserver/btcpay-restore.sh @@ -0,0 +1,134 @@ +#!/bin/bash -e + +set -o pipefail -o errexit -x + +if [ "$(id -u)" != "0" ]; then + printf "\n🚨 This script must be run as root.\n" + printf "➡️ Use the command 'sudo su -' (include the trailing hypen) and try again.\n\n" + exit 1 +fi + +backup_path=$1 +if [ -z "$backup_path" ]; then + printf "\nℹ️ Usage: btcpay-restore.sh /path/to/backup.tar.gz\n\n" + exit 1 +fi + +if [ ! -f "$backup_path" ]; then + printf "\n🚨 $backup_path does not exist.\n\n" + exit 1 +fi + +if [[ "$backup_path" == *.gpg && -z "$BTCPAY_BACKUP_PASSPHRASE" ]]; then + printf "\n🔐 $backup_path is encrypted. Please provide the passphrase to decrypt it." + printf "\nℹ️ Usage: BTCPAY_BACKUP_PASSPHRASE=t0pSeCrEt btcpay-restore.sh /path/to/backup.tar.gz.gpg\n\n" + exit 1 +fi + +# preparation +docker_dir=$(docker volume inspect generated_btcpay_datadir --format="{{.Mountpoint}}" | sed -e "s%/volumes/.*%%g") +restore_dir="$docker_dir/volumes/backup_datadir/_data/restore" +dbdump_name=postgres.sql.gz +btcpay_dir="$BTCPAY_BASE_DIRECTORY/btcpayserver-docker" + +# ensure clean restore dir +printf "\nℹ️ Cleaning restore directory $restore_dir …\n\n" +rm -rf $restore_dir +mkdir -p $restore_dir + +if [[ "$backup_path" == *.gpg ]]; then + echo "🔐 Decrypting backup file …" + { + gpg -o "${backup_path%.*}" --batch --yes --passphrase "$BTCPAY_BACKUP_PASSPHRASE" -d $backup_path + backup_path="${backup_path%.*}" + printf "✅ Decryption done.\n\n" + } || { + echo "🚨 Decryption failed. Please check the error message above." + exit 1 + } +fi + +cd $restore_dir + +echo "ℹ️ Extracting files in $(pwd) …" +tar -xvf $backup_path -C $restore_dir + +# basic control checks +if [ ! -f "$dbdump_name" ]; then + printf "\n🚨 $dbdump_name does not exist.\n\n" + exit 1 +fi + +if [ ! -d "volumes" ]; then + printf "\n🚨 volumes directory does not exist.\n\n" + exit 1 +fi + +cd $btcpay_dir +. helpers.sh + +printf "\nℹ️ Stopping BTCPay Server …\n\n" +btcpay_down + +cd $restore_dir + +{ + printf "\nℹ️ Restoring volumes …\n" + # ensure volumes dir exists + if [ ! -d "$docker_dir/volumes" ]; then + mkdir -p $docker_dir/volumes + fi + # copy volume directories over + cp -r volumes/* $docker_dir/volumes/ + # ensure datadirs excluded in backup exist + mkdir -p $docker_dir/volumes/generated_postgres_datadir/_data + echo "✅ Volume restore done." +} || { + echo "🚨 Restoring volumes failed. Please check the error message above." + printf "\nℹ️ Restarting BTCPay Server …\n\n" + cd $btcpay_dir + btcpay_up + exit 1 +} + +{ + printf "\nℹ️ Starting database container …\n" + docker-compose -f $BTCPAY_DOCKER_COMPOSE up -d postgres + dbcontainer=$(docker ps -a -q -f "name=postgres") + if [ -z "$dbcontainer" ]; then + echo "🚨 Database container could not be started or found." + printf "\nℹ️ Restarting BTCPay Server …\n\n" + cd $btcpay_dir + btcpay_up + exit 1 + fi +} || { + echo "🚨 Starting database container failed. Please check the error message above." + printf "\nℹ️ Restarting BTCPay Server …\n\n" + cd $btcpay_dir + btcpay_up + exit 1 +} + +cd $restore_dir + +{ + printf "\nℹ️ Restoring database …" + gunzip -c $dbdump_name | docker exec -i $dbcontainer psql -U postgres postgres -a + echo "✅ Database restore done." +} || { + echo "🚨 Restoring database failed. Please check the error message above." + printf "\nℹ️ Restarting BTCPay Server …\n\n" + cd $btcpay_dir + btcpay_up + exit 1 +} + +printf "\nℹ️ Restarting BTCPay Server …\n\n" +cd $btcpay_dir +btcpay_up + +printf "\nℹ️ Cleaning up …\n\n" +rm -rf $restore_dir + +printf "✅ Restore done\n\n" diff --git a/deployment/btcpayserver/go.sh b/deployment/btcpayserver/go.sh index 99cc796..043aaeb 100755 --- a/deployment/btcpayserver/go.sh +++ b/deployment/btcpayserver/go.sh @@ -3,55 +3,43 @@ set -eux cd "$(dirname "$0")" -if [ "$RUN_BACKUP" = true ]; then - # shellcheck disable=SC2029 - ssh "$FQDN" "cd $REMOTE_HOME/btcpayserver-docker/; sudo bash -c ./btcpay-down.sh" -fi - -# we will re-run the btcpay provisioning scripts if directed to do so. +# we will re-run the btcpayserver provisioning scripts if directed to do so. # if an update does occur, we grab another backup. if [ "$UPDATE_BTCPAY" = true ]; then - - if [ "$RUN_BACKUP" = true ]; then - # grab a backup PRIOR to update - ./backup.sh "before-update-$UNIX_BACKUP_TIMESTAMP" - fi - # run the update. - # shellcheck disable=SC2029 - ssh "$FQDN" "cd $REMOTE_HOME/btcpayserver-docker/; sudo bash -c ./btcpay-update.sh" + ssh "$FQDN" "bash -c $BTCPAY_SERVER_APPPATH/btcpay-down.sh" -else - if [ "$RUN_BACKUP" = true ]; then - # we just grab a regular backup - ./backup.sh "regular-backup-$UNIX_BACKUP_TIMESTAMP" - fi -fi + # btcpay-update.sh brings services back up, but does not take them down. + ssh "$FQDN" "sudo bash -c $BTCPAY_SERVER_APPPATH/btcpay-update.sh" -# run a restoration if specified. -if [ "$RUN_RESTORE" = true ]; then - # shellcheck disable=SC2029 - ssh "$FQDN" "cd $REMOTE_HOME/btcpayserver-docker/; sudo bash -c ./btcpay-down.sh" - #./restore.sh -fi +elif [ "$RESTORE_BTCPAY" = true ]; then + ./restore.sh -# the administrator may have indicated a reconfig; if so, re-run the setup (useful for adding alternative names to TLS) -if [ "$RECONFIGURE_BTCPAY_SERVER" = true ]; then - # re-run the setup script. + RUN_BACKUP=false + +elif [ "$RECONFIGURE_BTCPAY_SERVER" == true ]; then + # the administrator may have indicated a reconfig; + # if so, we re-run setup script. ./run_setup.sh + exit fi -if [ "$MIGRATE_VPS" = false ]; then +# if the script gets this far, then we grab a regular backup. +if [ "$RUN_BACKUP" = true ]; then + # we just grab a regular backup + ./backup.sh "$UNIX_BACKUP_TIMESTAMP" +fi + +if [ "$RUN_SERVICES" = true ]; then # The default is to resume services, though admin may want to keep services off (eg., for a migration) # we bring the services back up by default. - # shellcheck disable=SC2029 - ssh "$FQDN" "cd $REMOTE_HOME/btcpayserver-docker/; bash -c ./btcpay-up.sh" + ssh "$FQDN" "bash -c $BTCPAY_SERVER_APPPATH/btcpay-up.sh" # we wait for lightning to comone line too. - wait-for-it -t -60 "$FQDN:80" + wait-for-it -t 60 "$FQDN:443" + + xdg-open "https://$FQDN" - xdg-open "http://$FQDN" else - echo "WARNING: The '--migrate' flag was specified. BTCPay Server services HAVE NOT BEEN TURNED ON!" - echo "NOTE: You can restore your latest backup to a new host that has BTCPay Server installed." + echo "WARNING: BTCPAY Server services NOT started. This is probably on purpose." fi diff --git a/deployment/btcpayserver/restore.sh b/deployment/btcpayserver/restore.sh index 09d6feb..5f8abba 100755 --- a/deployment/btcpayserver/restore.sh +++ b/deployment/btcpayserver/restore.sh @@ -1,18 +1,31 @@ #!/bin/bash -# this scripts ASSUMES services have already been taken down. +set -ex +cd "$(dirname "$0")" + +#ssh "$FQDN" "sudo bash -c $BTCPAY_SERVER_APPPATH/btcpay-down.sh" # first let's ask the user for the absolute path to the backup file that we want to restore. -FILE_PATH= -read -r -p "Please enter the absolute path of the backup file you want to restore: ": FILE_PATH -if [ -f "$FILE_PATH" ]; then - # then we grab a backup of the existing stuff BEFORE the restoration attempt - ./btcpayserver/backup.sh "before-restore-$UNIX_BACKUP_TIMESTAMP" +BTCPAY_SERVER_ARCHIVE="$LOCAL_BACKUP_PATH/$UNIX_BACKUP_TIMESTAMP.tar.gz" +if [ ! -f "$BTCPAY_SERVER_ARCHIVE" ]; then + BTCPAY_SERVER_ARCHIVE="$RESTORE_ARCHIVE" +fi - echo "INFO: Restoring BTCPAY Server: $FILE_PATH" +if [ -f "$BTCPAY_SERVER_ARCHIVE" ]; then + # push the restoration archive to the remote server + echo "INFO: Restoring BTCPAY Server: $BTCPAY_SERVER_ARCHIVE" ssh "$FQDN" mkdir -p "$REMOTE_BACKUP_PATH" - scp "$FILE_PATH" "$FQDN:$REMOTE_BACKUP_PATH/btcpay.tar.gz" - ssh "$FQDN" "cd /; sudo tar -xzvf $REMOTE_BACKUP_PATH/btcpay.tar.gz" + REMOTE_BTCPAY_ARCHIVE_PATH="$REMOTE_HOME/backups/btcpay.tar.gz" + scp "$BTCPAY_SERVER_ARCHIVE" "$FQDN:$REMOTE_BTCPAY_ARCHIVE_PATH" + + # take down services, if any. + ssh "$FQDN" "cd $REMOTE_HOME/; sudo BTCPAY_BASE_DIRECTORY=$REMOTE_HOME bash -c $BTCPAY_SERVER_APPPATH/btcpay-down.sh" + + # push the modified restore script to the remote directory, set permissions, and execute. + scp ./btcpay-restore.sh "$FQDN:$REMOTE_HOME/btcpay-restore.sh" + ssh "$FQDN" "sudo mv $REMOTE_HOME/btcpay-restore.sh $BTCPAY_SERVER_APPPATH/btcpay-restore.sh && sudo chmod 0755 $BTCPAY_SERVER_APPPATH/btcpay-restore.sh" + ssh "$FQDN" "cd $REMOTE_HOME/; sudo BTCPAY_BASE_DIRECTORY=$REMOTE_HOME BTCPAY_DOCKER_COMPOSE=$REMOTE_HOME/btcpayserver-docker/Generated/docker-compose.generated.yml bash -c '$BTCPAY_SERVER_APPPATH/btcpay-restore.sh $REMOTE_BTCPAY_ARCHIVE_PATH'" + else echo "ERROR: File does not exist." exit 1 diff --git a/deployment/btcpayserver/run_setup.sh b/deployment/btcpayserver/run_setup.sh index da617f8..2b66b41 100755 --- a/deployment/btcpayserver/run_setup.sh +++ b/deployment/btcpayserver/run_setup.sh @@ -1,6 +1,7 @@ #!/bin/bash -set -e +set -ex +cd "$(dirname "$0")" # export BTCPAY_FASTSYNC_ARCHIVE_FILENAME="utxo-snapshot-bitcoin-testnet-1445586.tar" # BTCPAY_REMOTE_RESTORE_PATH="/var/lib/docker/volumes/generated_bitcoin_datadir/_data" @@ -11,27 +12,29 @@ cat > "$SITE_PATH/btcpay.sh" < $dbdump_path + echo "✅ Database dump done." +} || { + echo "🚨 Dumping failed. Please check the error message above." + exit 1 +} + +printf "\nℹ️ Stopping BTCPay Server …\n\n" +btcpay_down + +printf "\n" +cd $docker_dir +echo "ℹ️ Archiving files in $(pwd)…" + +{ + tar \ + --exclude="volumes/backup_datadir" \ + --exclude="volumes/generated_bitcoin_datadir/blocks" \ + --exclude="volumes/generated_bitcoin_datadir/chainstate" \ + --exclude="volumes/generated_bitcoin_datadir/debug.log" \ + --exclude="volumes/generated_litecoin_datadir/blocks" \ + --exclude="volumes/generated_litecoin_datadir/chainstate" \ + --exclude="volumes/generated_litecoin_datadir/debug.log" \ + --exclude="volumes/generated_postgres_datadir" \ + --exclude="volumes/generated_clightning_bitcoin_datadir/_data/lightning-rpc" \ + --exclude="**/logs/*" \ + -cvzf $backup_path $dbdump_name volumes/generated_* + echo "✅ Archive done." + + if [ ! -z "$BTCPAY_BACKUP_PASSPHRASE" ]; then + printf "\n" + echo "🔐 BTCPAY_BACKUP_PASSPHRASE is set, the backup will be encrypted." + { + gpg -o "$backup_path.gpg" --batch --yes -c --passphrase "$BTCPAY_BACKUP_PASSPHRASE" $backup_path + rm $backup_path + backup_path="$backup_path.gpg" + echo "✅ Encryption done." + } || { + echo "🚨 Encrypting failed. Please check the error message above." + printf "\nℹ️ Restarting BTCPay Server …\n\n" + cd $btcpay_dir + btcpay_up + exit 1 + } + fi +} || { + echo "🚨 Archiving failed. Please check the error message above." + printf "\nℹ️ Restarting BTCPay Server …\n\n" + cd $btcpay_dir + btcpay_up + exit 1 +} + +printf "\nℹ️ Restarting BTCPay Server …\n\n" +cd $btcpay_dir +btcpay_up + +printf "\nℹ️ Cleaning up …\n\n" +rm $dbdump_path + +printf "✅ Backup done => $backup_path\n\n" diff --git a/deployment/btcpayserver/scripts/btcpay-restore.sh b/deployment/btcpayserver/scripts/btcpay-restore.sh new file mode 100644 index 0000000..214b5c6 --- /dev/null +++ b/deployment/btcpayserver/scripts/btcpay-restore.sh @@ -0,0 +1,135 @@ +#!/bin/bash -e + +set -o pipefail -o errexit + +if [ "$(id -u)" != "0" ]; then + printf "\n🚨 This script must be run as root.\n" + printf "➡️ Use the command 'sudo su -' (include the trailing hypen) and try again.\n\n" + exit 1 +fi + +backup_path=$1 +if [ -z "$backup_path" ]; then + printf "\nℹ️ Usage: btcpay-restore.sh /path/to/backup.tar.gz\n\n" + exit 1 +fi + +if [ ! -f "$backup_path" ]; then + printf "\n🚨 $backup_path does not exist.\n\n" + exit 1 +fi + +if [[ "$backup_path" == *.gpg && -z "$BTCPAY_BACKUP_PASSPHRASE" ]]; then + printf "\n🔐 $backup_path is encrypted. Please provide the passphrase to decrypt it." + printf "\nℹ️ Usage: BTCPAY_BACKUP_PASSPHRASE=t0pSeCrEt btcpay-restore.sh /path/to/backup.tar.gz.gpg\n\n" + exit 1 +fi + +# preparation +docker_dir=$(docker volume inspect generated_btcpay_datadir --format="{{.Mountpoint}}" | sed -e "s%/volumes/.*%%g") +restore_dir="$docker_dir/volumes/backup_datadir/_data/restore" +dbdump_name=postgres.sql.gz +btcpay_dir="$BTCPAY_BASE_DIRECTORY/btcpayserver-docker" + +# ensure clean restore dir +printf "\nℹ️ Cleaning restore directory $restore_dir …\n\n" +rm -rf $restore_dir +mkdir -p $restore_dir + +if [[ "$backup_path" == *.gpg ]]; then + echo "🔐 Decrypting backup file …" + { + gpg -o "${backup_path%.*}" --batch --yes --passphrase "$BTCPAY_BACKUP_PASSPHRASE" -d $backup_path + backup_path="${backup_path%.*}" + printf "✅ Decryption done.\n\n" + } || { + echo "🚨 Decryption failed. Please check the error message above." + exit 1 + } +fi + +cd $restore_dir + +echo "ℹ️ Extracting files in $(pwd) …" +tar -xvf $backup_path -C $restore_dir + +# basic control checks +if [ ! -f "$dbdump_name" ]; then + printf "\n🚨 $dbdump_name does not exist.\n\n" + exit 1 +fi + +if [ ! -d "volumes" ]; then + printf "\n🚨 volumes directory does not exist.\n\n" + exit 1 +fi + +cd $btcpay_dir +. helpers.sh + +printf "\nℹ️ Stopping BTCPay Server …\n\n" +btcpay_down + +cd $restore_dir + +{ + printf "\nℹ️ Restoring volumes …\n" + # ensure volumes dir exists + if [ ! -d "$docker_dir/volumes" ]; then + mkdir -p $docker_dir/volumes + fi + # copy volume directories over + cp -r volumes/* $docker_dir/volumes/ + # ensure datadirs excluded in backup exist + mkdir -p $docker_dir/volumes/generated_postgres_datadir/_data + echo "✅ Volume restore done." +} || { + echo "🚨 Restoring volumes failed. Please check the error message above." + printf "\nℹ️ Restarting BTCPay Server …\n\n" + cd $btcpay_dir + btcpay_up + exit 1 +} + +{ + printf "\nℹ️ Starting database container …\n" + docker-compose -f $BTCPAY_DOCKER_COMPOSE up -d postgres + sleep 10 + dbcontainer=$(docker ps -a -q -f "name=postgres") + if [ -z "$dbcontainer" ]; then + echo "🚨 Database container could not be started or found." + printf "\nℹ️ Restarting BTCPay Server …\n\n" + cd $btcpay_dir + btcpay_up + exit 1 + fi +} || { + echo "🚨 Starting database container failed. Please check the error message above." + printf "\nℹ️ Restarting BTCPay Server …\n\n" + cd $btcpay_dir + btcpay_up + exit 1 +} + +cd $restore_dir + +{ + printf "\nℹ️ Restoring database …" + gunzip -c $dbdump_name | docker exec -i $dbcontainer psql -U postgres postgres -a + echo "✅ Database restore done." +} || { + echo "🚨 Restoring database failed. Please check the error message above." + printf "\nℹ️ Restarting BTCPay Server …\n\n" + cd $btcpay_dir + btcpay_up + exit 1 +} + +printf "\nℹ️ Restarting BTCPay Server …\n\n" +cd $btcpay_dir +btcpay_up + +printf "\nℹ️ Cleaning up …\n\n" +rm -rf $restore_dir + +printf "✅ Restore done\n\n" diff --git a/deployment/btcpayserver/scripts/btcpay-setup.sh b/deployment/btcpayserver/scripts/btcpay-setup.sh new file mode 100644 index 0000000..c3b008f --- /dev/null +++ b/deployment/btcpayserver/scripts/btcpay-setup.sh @@ -0,0 +1,565 @@ +#!/bin/bash + +set +x + +if [[ "$0" = "$BASH_SOURCE" ]]; then + echo "This script must be sourced \". btcpay-setup.sh\"" + exit 1 +fi + +if [[ "$OSTYPE" == "darwin"* ]]; then + # Mac OS + + if [[ $EUID -eq 0 ]]; then + # Running as root is discouraged on Mac OS. Run under the current user instead. + echo "This script should not be run as root." + return + fi + + BASH_PROFILE_SCRIPT="$HOME/btcpay-env.sh" + + # Mac OS doesn't use /etc/profile.d/xxx.sh. Instead we create a new file and load that from ~/.bash_profile + if [[ ! -f "$HOME/.bash_profile" ]]; then + touch "$HOME/.bash_profile" + fi + if [[ -z $(grep ". \"$BASH_PROFILE_SCRIPT\"" "$HOME/.bash_profile") ]]; then + # Line does not exist, add it + echo ". \"$BASH_PROFILE_SCRIPT\"" >> "$HOME/.bash_profile" + fi + +else + # Root user is not needed for Mac OS + BASH_PROFILE_SCRIPT="/etc/profile.d/btcpay-env.sh" + + if [[ $EUID -ne 0 ]]; then + echo "This script must be run as root after running \"sudo su -\"" + return + fi +fi + +# Verify we are in right folder. If we are not, let's go in the parent folder of the current docker-compose. +if ! git rev-parse --git-dir &> /dev/null || [ ! -d "Generated" ]; then + if [[ ! -z $BTCPAY_DOCKER_COMPOSE ]]; then + cd $(dirname $BTCPAY_DOCKER_COMPOSE) + cd .. + fi + if ! git rev-parse || [[ ! -d "Generated" ]]; then + echo "You must run this script inside the git repository of btcpayserver-docker" + return + fi +fi + +function display_help () { +cat <<-END +Usage: +------ + +Install BTCPay on this server +This script must be run as root, except on Mac OS + + -i : Run install and start BTCPay Server + --install-only: Run install only + --docker-unavailable: Same as --install-only, but will also skip install steps requiring docker + --no-startup-register: Do not register BTCPayServer to start via systemctl or upstart + --no-systemd-reload: Do not reload systemd configuration + +This script will: + +* Install Docker +* Install Docker-Compose +* Setup BTCPay settings +* Make sure it starts at reboot via upstart or systemd +* Add BTCPay utilities in /usr/bin +* Start BTCPay + +You can run again this script if you desire to change your configuration. +Except BTC and LTC, other crypto currencies are maintained by their own community. Run at your own risk. + +Make sure you own a domain with DNS record pointing to your website. +If you want HTTPS setup automatically with Let's Encrypt, leave REVERSEPROXY_HTTP_PORT at it's default value of 80 and make sure this port is accessible from the internet. +Or, if you want to offload SSL because you have an existing web proxy, change REVERSEPROXY_HTTP_PORT to any port you want. You can then forward the traffic. Just don't forget to pass the X-Forwarded-Proto header. + +Environment variables: + BTCPAY_HOST: The hostname of your website (eg. btcpay.example.com) + REVERSEPROXY_HTTP_PORT: The port the reverse proxy binds to for public HTTP requests. Default: 80 + REVERSEPROXY_HTTPS_PORT: The port the reverse proxy binds to for public HTTPS requests. Default: 443 + REVERSEPROXY_DEFAULT_HOST: Optional, if using a reverse proxy nginx, specify which website should be presented if the server is accessed by its IP. + LETSENCRYPT_EMAIL: A mail will be sent to this address if certificate expires and fail to renew automatically (eg. me@example.com) + NBITCOIN_NETWORK: The type of network to use (eg. mainnet, testnet or regtest. Default: mainnet) + LIGHTNING_ALIAS: An alias for your lightning network node if used + BTCPAYGEN_CRYPTO1: First supported crypto currency (eg. btc, ltc, btx, btg, grs, ftc, via, doge, mona, dash, none. Default: btc) + BTCPAYGEN_CRYPTO2: Second supported crypto currency (Default: empty) + BTCPAYGEN_CRYPTON: N th supported crypto currency where N is maximum at maximum 9. (Default: none) + BTCPAYGEN_REVERSEPROXY: Whether to use or not a reverse proxy. NGinx setup HTTPS for you. (eg. nginx, traefik, none. Default: nginx) + BTCPAYGEN_LIGHTNING: Lightning network implementation to use (eg. clightning, lnd, none) + BTCPAYGEN_ADDITIONAL_FRAGMENTS: Semi colon separated list of additional fragments you want to use (eg. opt-save-storage) + ACME_CA_URI: The API endpoint to ask for HTTPS certificate (default: production) + BTCPAY_ENABLE_SSH: Optional, gives BTCPay Server SSH access to the host by allowing it to edit authorized_keys of the host, it can be used for managing the authorized_keys or updating BTCPay Server directly through the website. (Default: false) + BTCPAYGEN_DOCKER_IMAGE: Allows you to specify a custom docker image for the generator (Default: btcpayserver/docker-compose-generator) + BTCPAY_IMAGE: Allows you to specify the btcpayserver docker image to use over the default version. (Default: current stable version of btcpayserver) + BTCPAY_PROTOCOL: Allows you to specify the external transport protocol of BTCPayServer. (Default: https) + BTCPAY_ADDITIONAL_HOSTS: Allows you to specify additional domains to your BTCPayServer with https support if enabled. (eg. example2.com,example3.com) +Add-on specific variables: + LIBREPATRON_HOST: If libre patron is activated with opt-add-librepatron, the hostname of your libre patron website (eg. librepatron.example.com) + ZAMMAD_HOST: If zammad is activated with opt-add-zammad, the hostname of your zammad website (eg. zammad.example.com) + WOOCOMMERCE_HOST: If woocommerce is activated with opt-add-woocommerce, the hostname of your woocommerce website (eg. store.example.com) + BTCPAYGEN_EXCLUDE_FRAGMENTS: Semicolon-separated list of fragments you want to forcefully exclude (eg. litecoin-clightning) + BTCTRANSMUTER_HOST: If btc transmuter is activated with opt-add-btctransmuter, the hostname of your btc transmuter website (eg. store.example.com) + TOR_RELAY_NICKNAME: If tor relay is activated with opt-add-tor-relay, the relay nickname + TOR_RELAY_EMAIL: If tor relay is activated with opt-add-tor-relay, the email for Tor to contact you regarding your relay + CHATWOOT_HOST: If chatwoot is activated with opt-add-chatwoot, the hostname of your chatwoot website (eg. store.example.com) + FIREFLY_HOST: If fireflyiii is activated with opt-add-fireflyiii, the hostname of your libre patron website (eg. firefly.example.com) + CLOUDFLARE_TUNNEL_TOKEN: Used to expose your instance to clearnet with a Cloudflare Argo Tunnel +END +} +START="" +HAS_DOCKER=true +STARTUP_REGISTER=true +SYSTEMD_RELOAD=true +while (( "$#" )); do + case "$1" in + -i) + START=true + shift 1 + ;; + --install-only) + START=false + shift 1 + ;; + --docker-unavailable) + START=false + HAS_DOCKER=false + shift 1 + ;; + --no-startup-register) + STARTUP_REGISTER=false + shift 1 + ;; + --no-systemd-reload) + SYSTEMD_RELOAD=false + shift 1 + ;; + --) # end argument parsing + shift + break + ;; + -*|--*=) # unsupported flags + echo "Error: Unsupported flag $1" >&2 + display_help + return + ;; + *) # preserve positional arguments + PARAMS="$PARAMS $1" + shift + ;; + esac +done + +# If start does not have a value, stop here +if ! [[ "$START" ]]; then + display_help + return +fi + +if [[ -z "$BTCPAYGEN_CRYPTO1" ]]; then + if [[ "$OSTYPE" != "darwin"* ]]; then + # Not Mac OS - Mac OS uses it's own env file + if [[ -f "$BASH_PROFILE_SCRIPT" ]]; then + echo "This script must be run as root after running \"sudo su -\"" + else + echo "BTCPAYGEN_CRYPTO1 should not be empty" + fi + return + fi +fi + +if [ ! -z "$BTCPAY_ADDITIONAL_HOSTS" ] && [[ "$BTCPAY_ADDITIONAL_HOSTS" == *[';']* ]]; then + echo "$BTCPAY_ADDITIONAL_HOSTS should be separated by a , not ;" + return; +fi + +if [ ! -z "$BTCPAY_ADDITIONAL_HOSTS" ] && [[ "$BTCPAY_ADDITIONAL_HOSTS" == .onion* ]]; then + echo "$BTCPAY_ADDITIONAL_HOSTS should not contain onion hosts, additional hosts is only for getting https certificates, those are not available to tor addresses" + return; +fi +######### Migration: old pregen environment to new environment ############ +if [[ ! -z $BTCPAY_DOCKER_COMPOSE ]] && [[ ! -z $DOWNLOAD_ROOT ]] && [[ -z $BTCPAYGEN_OLD_PREGEN ]]; then + echo "Your deployment is too old, you need to migrate by following instructions on this link https://docs.btcpayserver.org/Docker/#i-deployed-before-btcpay-setup-sh-existed-before-may-17-2018-can-i-migrate-to-this-new-system" + return +fi +######################################################### + +[[ $LETSENCRYPT_EMAIL == *@example.com ]] && echo "LETSENCRYPT_EMAIL ends with @example.com, setting to empty email instead" && LETSENCRYPT_EMAIL="" + +: "${LETSENCRYPT_EMAIL:=}" +: "${BTCPAYGEN_OLD_PREGEN:=false}" +: "${NBITCOIN_NETWORK:=mainnet}" +: "${BTCPAYGEN_CRYPTO1:=btc}" +: "${BTCPAYGEN_REVERSEPROXY:=nginx}" +: "${BTCPAYGEN_LIGHTNING:=none}" +: "${REVERSEPROXY_DEFAULT_HOST:=none}" +: "${ACME_CA_URI:=production}" +: "${BTCPAY_PROTOCOL:=https}" +: "${BTCPAY_ADDITIONAL_HOSTS:=}" +: "${REVERSEPROXY_HTTP_PORT:=80}" +: "${REVERSEPROXY_HTTPS_PORT:=443}" +: "${BTCPAY_ENABLE_SSH:=false}" +: "${PIHOLE_SERVERIP:=}" +: "${CLOUDFLARE_TUNNEL_TOKEN:=}" + +OLD_BTCPAY_DOCKER_COMPOSE="$BTCPAY_DOCKER_COMPOSE" +ORIGINAL_DIRECTORY="$(pwd)" +BTCPAY_BASE_DIRECTORY="$(dirname "$(pwd)")" + +if [[ "$BTCPAYGEN_OLD_PREGEN" == "true" ]]; then + if [[ $(dirname $BTCPAY_DOCKER_COMPOSE) == *Production ]]; then + BTCPAY_DOCKER_COMPOSE="$(pwd)/Production/docker-compose.generated.yml" + elif [[ $(dirname $BTCPAY_DOCKER_COMPOSE) == *Production-NoReverseProxy ]]; then + BTCPAY_DOCKER_COMPOSE="$(pwd)/Production-NoReverseProxy/docker-compose.generated.yml" + else + BTCPAY_DOCKER_COMPOSE="$(pwd)/Production/docker-compose.generated.yml" + fi +else # new deployments must be in Generated + BTCPAY_DOCKER_COMPOSE="$(pwd)/Generated/docker-compose.generated.yml" +fi + +BTCPAY_ENV_FILE="$BTCPAY_BASE_DIRECTORY/.env" + +BTCPAY_SSHKEYFILE="" +BTCPAY_SSHTRUSTEDFINGERPRINTS="" +use_ssh=false + +if $BTCPAY_ENABLE_SSH && ! [[ "$BTCPAY_HOST_SSHAUTHORIZEDKEYS" ]]; then + BTCPAY_HOST_SSHAUTHORIZEDKEYS=~/.ssh/authorized_keys + BTCPAY_HOST_SSHKEYFILE="" +fi + +if [[ -f "$BTCPAY_HOST_SSHKEYFILE" ]]; then + echo -e "\033[33mWARNING: BTCPAY_HOST_SSHKEYFILE is now deprecated, use instead BTCPAY_ENABLE_SSH=true and run again '. btcpay-setup.sh -i'\033[0m" + BTCPAY_SSHKEYFILE="/datadir/id_rsa" + use_ssh=true +fi + +if $BTCPAY_ENABLE_SSH && [[ "$BTCPAY_HOST_SSHAUTHORIZEDKEYS" ]]; then + if ! [[ -f "$BTCPAY_HOST_SSHAUTHORIZEDKEYS" ]]; then + mkdir -p "$(dirname $BTCPAY_HOST_SSHAUTHORIZEDKEYS)" + touch $BTCPAY_HOST_SSHAUTHORIZEDKEYS + fi + BTCPAY_SSHAUTHORIZEDKEYS="/datadir/host_authorized_keys" + BTCPAY_SSHKEYFILE="/datadir/host_id_ed25519" + use_ssh=true +fi + +# Do not set BTCPAY_SSHTRUSTEDFINGERPRINTS in the setup, since we connect from inside the docker container to the host, this is fine +BTCPAY_SSHTRUSTEDFINGERPRINTS="" + +if [[ "$BTCPAYGEN_REVERSEPROXY" == "nginx" ]] && [[ "$BTCPAY_HOST" ]]; then + DOMAIN_NAME="$(echo "$BTCPAY_HOST" | grep -E '^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$')" + if [[ ! "$DOMAIN_NAME" ]]; then + echo "BTCPAYGEN_REVERSEPROXY is set to nginx, so BTCPAY_HOST must be a domain name which point to this server, but the current value of BTCPAY_HOST ('$BTCPAY_HOST') is not a valid domain name." + return + fi + BTCPAY_HOST="$DOMAIN_NAME" +fi + +# Since opt-txindex requires unpruned node, throw an error if both +# opt-txindex and opt-save-storage-* are enabled together +if [[ "${BTCPAYGEN_ADDITIONAL_FRAGMENTS}" == *opt-txindex* ]] && \ + [[ "${BTCPAYGEN_ADDITIONAL_FRAGMENTS}" == *opt-save-storage* ]];then + echo "Error: BTCPAYGEN_ADDITIONAL_FRAGMENTS contains both opt-txindex and opt-save-storage*" + echo "opt-txindex requires an unpruned node, so you cannot use opt-save-storage with it" + return +fi + +cd "$BTCPAY_BASE_DIRECTORY/btcpayserver-docker" +. helpers.sh +btcpay_expand_variables + +cd "$ORIGINAL_DIRECTORY" + +echo " +-------SETUP----------- +Parameters passed: +BTCPAY_PROTOCOL:$BTCPAY_PROTOCOL +BTCPAY_HOST:$BTCPAY_HOST +BTCPAY_ADDITIONAL_HOSTS:$BTCPAY_ADDITIONAL_HOSTS +REVERSEPROXY_HTTP_PORT:$REVERSEPROXY_HTTP_PORT +REVERSEPROXY_HTTPS_PORT:$REVERSEPROXY_HTTPS_PORT +REVERSEPROXY_DEFAULT_HOST:$REVERSEPROXY_DEFAULT_HOST +LIBREPATRON_HOST:$LIBREPATRON_HOST +ZAMMAD_HOST:$ZAMMAD_HOST +WOOCOMMERCE_HOST:$WOOCOMMERCE_HOST +BTCTRANSMUTER_HOST:$BTCTRANSMUTER_HOST +CHATWOOT_HOST:$CHATWOOT_HOST +BTCPAY_ENABLE_SSH:$BTCPAY_ENABLE_SSH +BTCPAY_HOST_SSHKEYFILE:$BTCPAY_HOST_SSHKEYFILE +LETSENCRYPT_EMAIL:$LETSENCRYPT_EMAIL +NBITCOIN_NETWORK:$NBITCOIN_NETWORK +LIGHTNING_ALIAS:$LIGHTNING_ALIAS +BTCPAYGEN_CRYPTO1:$BTCPAYGEN_CRYPTO1 +BTCPAYGEN_CRYPTO2:$BTCPAYGEN_CRYPTO2 +BTCPAYGEN_CRYPTO3:$BTCPAYGEN_CRYPTO3 +BTCPAYGEN_CRYPTO4:$BTCPAYGEN_CRYPTO4 +BTCPAYGEN_CRYPTO5:$BTCPAYGEN_CRYPTO5 +BTCPAYGEN_CRYPTO6:$BTCPAYGEN_CRYPTO6 +BTCPAYGEN_CRYPTO7:$BTCPAYGEN_CRYPTO7 +BTCPAYGEN_CRYPTO8:$BTCPAYGEN_CRYPTO8 +BTCPAYGEN_CRYPTO9:$BTCPAYGEN_CRYPTO9 +BTCPAYGEN_REVERSEPROXY:$BTCPAYGEN_REVERSEPROXY +BTCPAYGEN_LIGHTNING:$BTCPAYGEN_LIGHTNING +BTCPAYGEN_ADDITIONAL_FRAGMENTS:$BTCPAYGEN_ADDITIONAL_FRAGMENTS +BTCPAYGEN_EXCLUDE_FRAGMENTS:$BTCPAYGEN_EXCLUDE_FRAGMENTS +BTCPAY_IMAGE:$BTCPAY_IMAGE +ACME_CA_URI:$ACME_CA_URI +TOR_RELAY_NICKNAME: $TOR_RELAY_NICKNAME +TOR_RELAY_EMAIL: $TOR_RELAY_EMAIL +PIHOLE_SERVERIP: $PIHOLE_SERVERIP +FIREFLY_HOST: $FIREFLY_HOST +---------------------- +Additional exported variables: +BTCPAY_DOCKER_COMPOSE=$BTCPAY_DOCKER_COMPOSE +BTCPAY_BASE_DIRECTORY=$BTCPAY_BASE_DIRECTORY +BTCPAY_ENV_FILE=$BTCPAY_ENV_FILE +BTCPAYGEN_OLD_PREGEN=$BTCPAYGEN_OLD_PREGEN +BTCPAY_SSHKEYFILE=$BTCPAY_SSHKEYFILE +BTCPAY_SSHAUTHORIZEDKEYS=$BTCPAY_SSHAUTHORIZEDKEYS +BTCPAY_HOST_SSHAUTHORIZEDKEYS:$BTCPAY_HOST_SSHAUTHORIZEDKEYS +BTCPAY_SSHTRUSTEDFINGERPRINTS:$BTCPAY_SSHTRUSTEDFINGERPRINTS +BTCPAY_CRYPTOS:$BTCPAY_CRYPTOS +BTCPAY_ANNOUNCEABLE_HOST:$BTCPAY_ANNOUNCEABLE_HOST +---------------------- +" + +if [[ -z "$BTCPAYGEN_CRYPTO1" ]]; then + echo "BTCPAYGEN_CRYPTO1 should not be empty" + return +fi + +if [[ "$NBITCOIN_NETWORK" != "mainnet" ]] && [[ "$NBITCOIN_NETWORK" != "testnet" ]] && [[ "$NBITCOIN_NETWORK" != "regtest" ]]; then + echo "NBITCOIN_NETWORK should be equal to mainnet, testnet or regtest" +fi + + + +# Init the variables when a user log interactively +touch "$BASH_PROFILE_SCRIPT" +echo " +#!/bin/bash +export COMPOSE_HTTP_TIMEOUT=\"180\" +export BTCPAYGEN_OLD_PREGEN=\"$BTCPAYGEN_OLD_PREGEN\" +export BTCPAYGEN_CRYPTO1=\"$BTCPAYGEN_CRYPTO1\" +export BTCPAYGEN_CRYPTO2=\"$BTCPAYGEN_CRYPTO2\" +export BTCPAYGEN_CRYPTO3=\"$BTCPAYGEN_CRYPTO3\" +export BTCPAYGEN_CRYPTO4=\"$BTCPAYGEN_CRYPTO4\" +export BTCPAYGEN_CRYPTO5=\"$BTCPAYGEN_CRYPTO5\" +export BTCPAYGEN_CRYPTO6=\"$BTCPAYGEN_CRYPTO6\" +export BTCPAYGEN_CRYPTO7=\"$BTCPAYGEN_CRYPTO7\" +export BTCPAYGEN_CRYPTO8=\"$BTCPAYGEN_CRYPTO8\" +export BTCPAYGEN_CRYPTO9=\"$BTCPAYGEN_CRYPTO9\" +export BTCPAYGEN_LIGHTNING=\"$BTCPAYGEN_LIGHTNING\" +export BTCPAYGEN_REVERSEPROXY=\"$BTCPAYGEN_REVERSEPROXY\" +export BTCPAYGEN_ADDITIONAL_FRAGMENTS=\"$BTCPAYGEN_ADDITIONAL_FRAGMENTS\" +export BTCPAYGEN_EXCLUDE_FRAGMENTS=\"$BTCPAYGEN_EXCLUDE_FRAGMENTS\" +export BTCPAY_DOCKER_COMPOSE=\"$BTCPAY_DOCKER_COMPOSE\" +export BTCPAY_BASE_DIRECTORY=\"$BTCPAY_BASE_DIRECTORY\" +export BTCPAY_ENV_FILE=\"$BTCPAY_ENV_FILE\" +export BTCPAY_HOST_SSHKEYFILE=\"$BTCPAY_HOST_SSHKEYFILE\" +export BTCPAY_ENABLE_SSH=$BTCPAY_ENABLE_SSH +export PIHOLE_SERVERIP=\"$PIHOLE_SERVERIP\" +if cat \"\$BTCPAY_ENV_FILE\" &> /dev/null; then + while IFS= read -r line; do + ! [[ \"\$line\" == \"#\"* ]] && [[ \"\$line\" == *\"=\"* ]] && export \"\$line\" + done < \"\$BTCPAY_ENV_FILE\" +fi +" > ${BASH_PROFILE_SCRIPT} + +chmod +x ${BASH_PROFILE_SCRIPT} + +echo -e "BTCPay Server environment variables successfully saved in $BASH_PROFILE_SCRIPT\n" + + +btcpay_update_docker_env + +echo -e "BTCPay Server docker-compose parameters saved in $BTCPAY_ENV_FILE\n" + +. "$BASH_PROFILE_SCRIPT" + +if ! [[ -x "$(command -v docker)" ]] || ! [[ -x "$(command -v docker-compose)" ]]; then + if ! [[ -x "$(command -v curl)" ]]; then + apt-get update 2>error + apt-get install -y \ + curl \ + apt-transport-https \ + ca-certificates \ + software-properties-common \ + 2>error + fi + if ! [[ -x "$(command -v docker)" ]]; then + if [[ "$(uname -m)" == "x86_64" ]] || [[ "$(uname -m)" == "armv7l" ]] || [[ "$(uname -m)" == "aarch64" ]]; then + if [[ "$OSTYPE" == "darwin"* ]]; then + # Mac OS + if ! [[ -x "$(command -v brew)" ]]; then + # Brew is not installed, install it now + echo "Homebrew, the package manager for Mac OS, is not installed. Installing it now..." + /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" + fi + if [[ -x "$(command -v brew)" ]]; then + echo "Homebrew is installed, but Docker isn't. Installing it now using brew..." + # Brew is installed, install docker now + # This sequence is a bit strange, but it's what what needed to get it working on a fresh Mac OS X Mojave install + brew cask install docker + brew install docker + brew link docker + fi + else + # Not Mac OS + echo "Trying to install docker..." + curl -fsSL https://get.docker.com -o get-docker.sh + chmod +x get-docker.sh + sh get-docker.sh + rm get-docker.sh + fi + else + echo "Unsupported architecture $(uname -m)" + return + fi + fi + + docker_update + + if ! [[ -x "$(command -v docker-compose)" ]]; then + if ! [[ "$OSTYPE" == "darwin"* ]] && $HAS_DOCKER; then + echo "Trying to install docker-compose by using the btcpayserver/docker-compose ($(uname -m))" + ! [[ -d "dist" ]] && mkdir dist + docker run --rm -v "$(pwd)/dist:/dist" btcpayserver/docker-compose:1.28.6 + mv dist/docker-compose /usr/local/bin/docker-compose + chmod +x /usr/local/bin/docker-compose + rm -rf "dist" + fi + fi +fi + +if $HAS_DOCKER; then + if ! [[ -x "$(command -v docker)" ]]; then + echo "Failed to install 'docker'. Please install docker manually, then retry." + return + fi + + if ! [[ -x "$(command -v docker-compose)" ]]; then + echo "Failed to install 'docker-compose'. Please install docker-compose manually, then retry." + return + fi +fi + +# Generate the docker compose in BTCPAY_DOCKER_COMPOSE +if $HAS_DOCKER; then + if ! ./build.sh; then + echo "Failed to generate the docker-compose" + return + fi +fi + +if [[ "$BTCPAYGEN_OLD_PREGEN" == "true" ]]; then + cp Generated/docker-compose.generated.yml $BTCPAY_DOCKER_COMPOSE +fi + +# Schedule for reboot +if $STARTUP_REGISTER && [[ -x "$(command -v systemctl)" ]]; then + # Use systemd + if [[ -e "/etc/init/start_containers.conf" ]]; then + echo -e "Uninstalling upstart script /etc/init/start_containers.conf" + rm "/etc/init/start_containers.conf" + initctl reload-configuration + fi + echo "Adding btcpayserver.service to systemd" + echo " +[Unit] +Description=BTCPayServer service +After=docker.service network-online.target +Requires=docker.service network-online.target + +[Service] +Type=oneshot +RemainAfterExit=yes + +ExecStart=/bin/bash -c '. \"$BASH_PROFILE_SCRIPT\" && cd \"\$BTCPAY_BASE_DIRECTORY/btcpayserver-docker\" && . helpers.sh && btcpay_up' +ExecStop=/bin/bash -c '. \"$BASH_PROFILE_SCRIPT\" && cd \"\$BTCPAY_BASE_DIRECTORY/btcpayserver-docker\" && . helpers.sh && btcpay_down' +ExecReload=/bin/bash -c '. \"$BASH_PROFILE_SCRIPT\" && cd \"\$BTCPAY_BASE_DIRECTORY/btcpayserver-docker\" && . helpers.sh && btcpay_restart' + +[Install] +WantedBy=multi-user.target" > /etc/systemd/system/btcpayserver.service + + if ! [[ -f "/etc/docker/daemon.json" ]] && [ -w "/etc/docker" ]; then + echo "{ +\"log-driver\": \"json-file\", +\"log-opts\": {\"max-size\": \"5m\", \"max-file\": \"3\"} +}" > /etc/docker/daemon.json + echo "Setting limited log files in /etc/docker/daemon.json" + $SYSTEMD_RELOAD && $START && systemctl restart docker + fi + + echo -e "BTCPay Server systemd configured in /etc/systemd/system/btcpayserver.service\n" + if $SYSTEMD_RELOAD; then + systemctl daemon-reload + systemctl enable btcpayserver + if $START; then + echo "BTCPay Server starting... this can take 5 to 10 minutes..." + systemctl start btcpayserver + echo "BTCPay Server started" + fi + else + systemctl --no-reload enable btcpayserver + fi +elif $STARTUP_REGISTER && [[ -x "$(command -v initctl)" ]]; then + # Use upstart + echo "Using upstart" + echo " +# File is saved under /etc/init/start_containers.conf +# After file is modified, update config with : $ initctl reload-configuration + +description \"Start containers (see http://askubuntu.com/a/22105 and http://askubuntu.com/questions/612928/how-to-run-docker-compose-at-bootup)\" + +start on filesystem and started docker +stop on runlevel [!2345] + +# if you want it to automatically restart if it crashes, leave the next line in +# respawn # might cause over charge + +script + . \"$BASH_PROFILE_SCRIPT\" + cd \"\$BTCPAY_BASE_DIRECTORY/btcpayserver-docker\" + . helpers.sh + btcpay_up +end script" > /etc/init/start_containers.conf + echo -e "BTCPay Server upstart configured in /etc/init/start_containers.conf\n" + + if $START; then + initctl reload-configuration + fi +fi + + +cd "$(dirname $BTCPAY_ENV_FILE)" + +if $HAS_DOCKER && [[ ! -z "$OLD_BTCPAY_DOCKER_COMPOSE" ]] && [[ "$OLD_BTCPAY_DOCKER_COMPOSE" != "$BTCPAY_DOCKER_COMPOSE" ]]; then + echo "Closing old docker-compose at $OLD_BTCPAY_DOCKER_COMPOSE..." + docker-compose -f "$OLD_BTCPAY_DOCKER_COMPOSE" down -t "${COMPOSE_HTTP_TIMEOUT:-180}" +fi + +if $START; then + btcpay_up +elif $HAS_DOCKER; then + btcpay_pull +fi + +# Give SSH key to BTCPay +if $START && [[ -f "$BTCPAY_HOST_SSHKEYFILE" ]]; then + echo -e "\033[33mWARNING: BTCPAY_HOST_SSHKEYFILE is now deprecated, use instead BTCPAY_ENABLE_SSH=true and run again '. btcpay-setup.sh -i'\033[0m" + echo "Copying $BTCPAY_SSHKEYFILE to BTCPayServer container" + docker cp "$BTCPAY_HOST_SSHKEYFILE" $(docker ps --filter "name=_btcpayserver_" -q):$BTCPAY_SSHKEYFILE +fi + +cd "$BTCPAY_BASE_DIRECTORY/btcpayserver-docker" +install_tooling + +cd $ORIGINAL_DIRECTORY diff --git a/deployment/command.sh b/deployment/command.sh deleted file mode 100644 index 77ba2be..0000000 --- a/deployment/command.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -bash -c ./deploy.sh --domain=bitizen.store --hosting-provider=lxd --macvlan-interface=eno3 --storage-backend=/dev/sda diff --git a/deployment/create_lxc_base.sh b/deployment/create_lxc_base.sh new file mode 100755 index 0000000..7328273 --- /dev/null +++ b/deployment/create_lxc_base.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +set -exu +cd "$(dirname "$0")" + +./stub_lxc_profile.sh sovereign-stack + +# create the default storage pool if necessary +if ! lxc storage list --format csv | grep -q "sovereign-stack"; then + + if [ "$DISK_TO_USE" != loop ]; then + # we omit putting a size here so, so LXD will consume the entire disk if '/dev/sdb' or partition if '/dev/sdb1'. + # TODO do some sanity/resource checking on DISK_TO_USE. + lxc storage create "sovereign-stack" zfs source="$DISK_TO_USE" + + else + # if a disk is the default 'loop', then we create a zfs storage pool + # on top of the existing filesystem using a loop device, per LXD docs + lxc storage create "sovereign-stack" zfs + fi +fi + +# If our template doesn't exist, we create one. +if ! lxc image list --format csv "$VM_NAME" | grep -q "$VM_NAME"; then + + # If the lxc VM does exist, then we will delete it (so we can start fresh) + if lxc list -q --format csv | grep -q "$VM_NAME"; then + lxc delete "$VM_NAME" --force + + # remove the ssh known endpoint else we get warnings. + ssh-keygen -f "$SSH_HOME/known_hosts" -R "$VM_NAME" + fi + + # let's download our base image. + if ! lxc image list --format csv --columns l | grep -q "ubuntu-base"; then + # if the image doesn't exist, download it from Ubuntu's image server + # TODO see if we can fetch this file from a more censorship-resistant source, e.g., ipfs + # we don't really need to cache this locally since it gets continually updated upstream. + lxc image copy "images:$BASE_LXC_IMAGE" "$CLUSTER_NAME": --alias "ubuntu-base" --public --vm + fi + + # this vm is used temperarily with + lxc init --profile="sovereign-stack" "ubuntu-base" "$VM_NAME" --vm + + # let's PIN the HW address for now so we don't exhaust IP + # and so we can set DNS internally. + + # TODO move this sovereign-stack-base construction VM to separate dedicated IP + lxc config set "$VM_NAME" "volatile.enp5s0.hwaddr=$SOVEREIGN_STACK_MAC_ADDRESS" + + lxc start "$VM_NAME" + + # let's wait a minimum of 15 seconds before we start checking for an IP address. + sleep 15 + + # let's wait for the LXC vm remote machine to get an IP address. + ./wait_for_lxc_ip.sh "$VM_NAME" + + # stop the VM and get a snapshot. + lxc stop "$VM_NAME" + lxc publish "$CLUSTER_NAME:$VM_NAME" --alias "$VM_NAME" --public + lxc delete "$VM_NAME" +fi diff --git a/deployment/domain_init.sh b/deployment/domain_init.sh index 44d37f0..f1781f9 100755 --- a/deployment/domain_init.sh +++ b/deployment/domain_init.sh @@ -3,6 +3,7 @@ set -eux cd "$(dirname "$0")" + # let's make sure we have an ssh keypair. We just use ~/.ssh/id_rsa # TODO convert this to SSH private key held on Trezor. THus trezor-T required for # login operations. This should be configurable of course. @@ -33,12 +34,10 @@ function prepare_host { # create a directory to store backup archives. This is on all new vms. ssh "$FQDN" mkdir -p "$REMOTE_HOME/backups" - if [ "$APP_TO_DEPLOY" = btcpay ]; then + if [ "$VIRTUAL_MACHINE" = btcpayserver ]; then echo "INFO: new machine detected. Provisioning BTCPay server scripts." ./btcpayserver/run_setup.sh - - exit fi } @@ -80,26 +79,9 @@ if [ ! -f "$HOME/.docker/config.json" ]; then fi # this tells our local docker client to target the remote endpoint via SSH -export DOCKER_HOST="ssh://ubuntu@$FQDN" +export DOCKER_HOST="ssh://ubuntu@$FQDN" # the following scripts take responsibility for the rest of the provisioning depending on the app you're deploying. -if [ "$APP_TO_DEPLOY" = www ]; then - ./go_www.sh -elif [ "$APP_TO_DEPLOY" = btcpay ]; then - ./btcpayserver/go.sh -elif [ "$APP_TO_DEPLOY" = umbrel ]; then - ./go_umbrel.sh -elif [ "$APP_TO_DEPLOY" = certonly ]; then - # renew the certs; certbot takes care of seeing if we need to actually renew. - if [ "$RUN_CERT_RENEWAL" = true ]; then - ./generate_certs.sh - fi - - echo "INFO: Please run 'docker-machine rm -f $FQDN' to remove the remote VPS." - exit -else - echo "ERROR: APP_TO_DEPLOY not set correctly. Please refer to the documentation for allowable values." - exit -fi +bash -c "./$VIRTUAL_MACHINE/go.sh" echo "Successfull deployed '$DOMAIN_NAME' with git commit '$(cat ./.git/refs/heads/master)' VPS_HOSTING_TARGET=$VPS_HOSTING_TARGET;" diff --git a/deployment/down_btcpay_compose.sh b/deployment/down_btcpay_compose.sh deleted file mode 100644 index 05a7907..0000000 --- a/deployment/down_btcpay_compose.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash - diff --git a/deployment/expensive-relay/Dockerfile b/deployment/expensive-relay/Dockerfile deleted file mode 100644 index e69de29..0000000 diff --git a/deployment/expensive-relay/conf.conf b/deployment/expensive-relay/conf.conf deleted file mode 100644 index e69de29..0000000 diff --git a/deployment/provision_lxc.sh b/deployment/provision_lxc.sh index f8c6fb5..946cec4 100755 --- a/deployment/provision_lxc.sh +++ b/deployment/provision_lxc.sh @@ -1,43 +1,9 @@ #!/bin/bash set -eux +cd "$(dirname "$0")" -# The base VM image. -BASE_LXC_IMAGE="ubuntu/22.04/cloud" - -# let's create a profile for the BCM TYPE-1 VMs. This is per VM. -if ! lxc profile list --format csv | grep -q "$LXD_VM_NAME"; then - lxc profile create "$LXD_VM_NAME" -fi - -# generate the custom cloud-init file. Cloud init installs and configures sshd -SSH_AUTHORIZED_KEY=$(<"$SSH_HOME/id_rsa.pub") -eval "$(ssh-agent -s)" -ssh-add "$SSH_HOME/id_rsa" -export SSH_AUTHORIZED_KEY="$SSH_AUTHORIZED_KEY" -envsubst < ./lxc_profile.yml > "$SITE_PATH/cloud-init-$APP_TO_DEPLOY.yml" - -# configure the profile with our generated cloud-init.yml file. -cat "$SITE_PATH/cloud-init-$APP_TO_DEPLOY.yml" | lxc profile edit "$LXD_VM_NAME" - -function wait_for_lxc_ip { - -LXC_INSTANCE_NAME="$1" -IP_V4_ADDRESS= -while true; do - IP_V4_ADDRESS="$(lxc list "$LXC_INSTANCE_NAME" --format csv --columns=4 | grep enp5s0 | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')" || true - export IP_V4_ADDRESS="$IP_V4_ADDRESS" - if [ -n "$IP_V4_ADDRESS" ]; then - # give the machine extra time to spin up. - wait-for-it -t 300 "$IP_V4_ADDRESS:22" - break - else - sleep 1 - printf '.' - fi -done - -} +./stub_lxc_profile.sh "$LXD_VM_NAME" function run_ddns { # now that the VM has an IP, we can update the DNS record. TODO add additional DNS providers here; namecheap only atm. @@ -58,77 +24,24 @@ function run_ddns { echo "" echo "SUCCESS: The DNS appears to be configured correctly." - echo "INFO: Waiting $DDNS_SLEEP_SECONDS seconds to allow cached DNS records to expire." - sleep "$DDNS_SLEEP_SECONDS"; + # we're waiting here to allow dns records to stale out. + # this is necessary for certificate renewal; letsencrypt might have stale records + # and cert renew won't succeed. HOWEVER, if we're running a restore operation, we SHOULD NOT + # do a certificate renewal (we're restoring old certs). Thus it is not necessary to sleep here. + if [ "$RUN_RESTORE" = false ]; then + echo "INFO: Waiting $DDNS_SLEEP_SECONDS seconds to allow cached DNS records to expire." + sleep "$DDNS_SLEEP_SECONDS"; + fi + break; fi printf "." && sleep 2; done fi + } -# create the default storage pool if necessary -if ! lxc storage list --format csv | grep -q "sovereign-stack"; then - if [ -n "$LXD_DISK_TO_USE" ]; then - lxc storage create "sovereign-stack" zfs source="$LXD_DISK_TO_USE" - # size="${ROOT_DISK_SIZE_GB}GB" - else - lxc storage create "sovereign-stack" zfs - # size="${ROOT_DISK_SIZE_GB}GB" - fi -fi - -# If our template doesn't exist, we create one. -if ! lxc image list --format csv "$VM_NAME" | grep -q "$VM_NAME"; then - - # If the lxc VM does exist, then we will delete it (so we can start fresh) - if lxc list -q --format csv | grep -q "$VM_NAME"; then - lxc delete "$VM_NAME" --force - - # remove the ssh known endpoint else we get warnings. - ssh-keygen -f "$SSH_HOME/known_hosts" -R "$VM_NAME" - fi - - # let's download our base image. - if ! lxc image list --format csv --columns l | grep -q "ubuntu-base"; then - # if the image doesn't exist, download it from Ubuntu's image server - # TODO see if we can fetch this file from a more censorship-resistant source, e.g., ipfs - # we don't really need to cache this locally since it gets continually updated upstream. - lxc image copy "images:$BASE_LXC_IMAGE" "$DEV_LXD_REMOTE": --alias "ubuntu-base" --public --vm - fi - - lxc init \ - --profile="$LXD_VM_NAME" \ - "ubuntu-base" \ - "$VM_NAME" --vm - - # let's PIN the HW address for now so we don't exhaust IP - # and so we can set DNS internally. - - lxc config set "$VM_NAME" "volatile.enp5s0.hwaddr=$MAC_ADDRESS_TO_PROVISION" - - lxc start "$VM_NAME" - - # let's wait a minimum of 15 seconds before we start checking for an IP address. - sleep 15 - - # let's wait for the LXC vm remote machine to get an IP address. - wait_for_lxc_ip "$VM_NAME" - - # Let's remove any entry in our known_hosts, then add it back. - # we are using IP address here so we don't have to rely on external DNS - # configuration for the base image preparataion. - ssh-keygen -R "$IP_V4_ADDRESS" - ssh-keyscan -H -t ecdsa "$IP_V4_ADDRESS" >> "$SSH_HOME/known_hosts" - ssh "ubuntu@$IP_V4_ADDRESS" sudo chown -R ubuntu:ubuntu "$REMOTE_HOME" - - # stop the VM and get a snapshot. - lxc stop "$VM_NAME" - lxc publish "$DEV_LXD_REMOTE:$VM_NAME" --alias "$VM_NAME" --public - lxc delete "$VM_NAME" -fi - # now let's create a new VM to work with. lxc init --profile="$LXD_VM_NAME" "$VM_NAME" "$LXD_VM_NAME" --vm @@ -139,9 +52,12 @@ lxc config device override "$LXD_VM_NAME" root size="${ROOT_DISK_SIZE_GB}GB" lxc start "$LXD_VM_NAME" -wait_for_lxc_ip "$LXD_VM_NAME" +./wait_for_lxc_ip.sh "$LXD_VM_NAME" -run_ddns +if [ "$VPS_HOSTING_TARGET" = aws ]; then + run_ddns -# remove any existing SSH identities for the host, then add it back. -ssh-keygen -R "$IP_V4_ADDRESS" + # remove any existing SSH identities for the host, then add it back. + ssh-keygen -R "$IP_V4_ADDRESS" + +fi diff --git a/deployment/provision_vps.sh b/deployment/provision_vps.sh index 8c14817..1d65494 100755 --- a/deployment/provision_vps.sh +++ b/deployment/provision_vps.sh @@ -36,7 +36,7 @@ if [ -z "$AWS_SECRET_ACCESS_KEY" ]; then fi # Note, we assume the script has already made sure the machine doesn't exist. -if [ "$APP_TO_DEPLOY" = www ] || [ "$APP_TO_DEPLOY" = certonly ]; then +if [ "$VIRTUAL_MACHINE" = www ] || [ "$VIRTUAL_MACHINE" = certonly ]; then # creates a public VM in AWS and provisions the bcm website. docker-machine create --driver amazonec2 \ --amazonec2-open-port 80 \ @@ -50,7 +50,7 @@ if [ "$APP_TO_DEPLOY" = www ] || [ "$APP_TO_DEPLOY" = certonly ]; then --engine-label commit="$LATEST_GIT_COMMIT" \ "$FQDN" -elif [ "$APP_TO_DEPLOY" = btcpay ]; then +elif [ "$VIRTUAL_MACHINE" = btcpayserver ]; then # creates a public VM in AWS and provisions the bcm website. docker-machine create --driver amazonec2 \ --amazonec2-open-port 80 \ @@ -67,7 +67,7 @@ elif [ "$APP_TO_DEPLOY" = btcpay ]; then fi -docker-machine scp "$LXD_REMOTE_PATH/authorized_keys" "$FQDN:$REMOTE_HOME/authorized_keys" +docker-machine scp "$CLUSTER_PATH/authorized_keys" "$FQDN:$REMOTE_HOME/authorized_keys" docker-machine ssh "$FQDN" "cat $REMOTE_HOME/authorized_keys >> $REMOTE_HOME/.ssh/authorized_keys" # we have to ensure ubuntu is able to do sudo less docker commands. diff --git a/deployment/run_ddns.sh b/deployment/run_ddns.sh index 81852cc..da5714e 100755 --- a/deployment/run_ddns.sh +++ b/deployment/run_ddns.sh @@ -5,7 +5,7 @@ set -eux DDNS_STRING= # for the www stack, we register only the domain name so our URLs look like https://$DOMAIN_NAME -if [ "$APP_TO_DEPLOY" = www ] || [ "$APP_TO_DEPLOY" = certonly ]; then +if [ "$VIRTUAL_MACHINE" = www ] || [ "$VIRTUAL_MACHINE" = certonly ]; then DDNS_STRING="@" else DDNS_STRING="$DDNS_HOST" diff --git a/deployment/lxc_profile.yml b/deployment/stub_lxc_profile.sh old mode 100644 new mode 100755 similarity index 77% rename from deployment/lxc_profile.yml rename to deployment/stub_lxc_profile.sh index 4d1ba7e..747fe09 --- a/deployment/lxc_profile.yml +++ b/deployment/stub_lxc_profile.sh @@ -1,16 +1,40 @@ +#!/bin/bash + +set -eux + +VIRTUAL_MACHINE="$1" + +# generate the custom cloud-init file. Cloud init installs and configures sshd +SSH_AUTHORIZED_KEY=$(<"$SSH_HOME/id_rsa.pub") +eval "$(ssh-agent -s)" +ssh-add "$SSH_HOME/id_rsa" +export SSH_AUTHORIZED_KEY="$SSH_AUTHORIZED_KEY" + +export FILENAME="$VIRTUAL_MACHINE.yml" +mkdir -p "$CLUSTER_PATH/cloud-init" +YAML_PATH="$CLUSTER_PATH/cloud-init/$FILENAME" + +# If we are deploying the www, we attach the vm to the underlay via macvlan. +cat > "$YAML_PATH" <> "$YAML_PATH" <> ${REMOTE_HOME}/.bash_profile + - echo "alias ll='ls -lah'" >> /home/ubuntu/.bash_profile - sudo curl -s -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose - sudo chmod +x /usr/local/bin/docker-compose - sudo apt-get install -y openssh-server + -description: Default LXD profile for ${DOMAIN_NAME} +EOF + +else + # all other machines. + cat >> "$YAML_PATH" <> "$YAML_PATH" <> "$YAML_PATH" <>"$NGINX_CONF_PATH" <> "$SSH_HOME/known_hosts" +ssh "ubuntu@$IP_V4_ADDRESS" sudo chown -R ubuntu:ubuntu /home/ubuntu diff --git a/deployment/backup_www.sh b/deployment/www/backup.sh similarity index 99% rename from deployment/backup_www.sh rename to deployment/www/backup.sh index 1e988a0..e4970bf 100755 --- a/deployment/backup_www.sh +++ b/deployment/www/backup.sh @@ -1,6 +1,6 @@ #!/bin/bash -set -eu +set -eux cd "$(dirname "$0")" # TODO: We are using extra space on the remote VPS at the moment for the duplicity backup files. diff --git a/deployment/generate_certs.sh b/deployment/www/generate_certs.sh similarity index 92% rename from deployment/generate_certs.sh rename to deployment/www/generate_certs.sh index 92d82bc..c696eea 100755 --- a/deployment/generate_certs.sh +++ b/deployment/www/generate_certs.sh @@ -27,6 +27,6 @@ elif [ "$VPS_HOSTING_TARGET" = lxd ]; then -v "$REMOTE_HOME/letsencrypt":/etc/letsencrypt \ -v /var/lib/letsencrypt:/var/lib/letsencrypt \ -v "$REMOTE_HOME/letsencrypt_logs":/var/log/letsencrypt \ - certbot/certbot certonly -v --noninteractive --agree-tos --key-type ecdsa --standalone --expand -d "$DOMAIN_NAME" -d "$FQDN" -d "$NEXTCLOUD_FQDN" -d "$GITEA_FQDN" -d "$BTCPAY_FQDN" -d "$NOSTR_FQDN" --email "$CERTIFICATE_EMAIL_ADDRESS" + certbot/certbot certonly -v --noninteractive --agree-tos --key-type ecdsa --standalone --expand -d "$DOMAIN_NAME" -d "$FQDN" -d "$NEXTCLOUD_FQDN" -d "$GITEA_FQDN" -d "$NOSTR_FQDN" --email "$CERTIFICATE_EMAIL_ADDRESS" fi diff --git a/deployment/go_www.sh b/deployment/www/go.sh similarity index 92% rename from deployment/go_www.sh rename to deployment/www/go.sh index f375717..4e01b74 100755 --- a/deployment/go_www.sh +++ b/deployment/www/go.sh @@ -1,6 +1,7 @@ #!/bin/bash set -exu +cd "$(dirname "$0")" TOR_CONFIG_PATH= @@ -38,11 +39,11 @@ if [ "$RUN_CERT_RENEWAL" = true ]; then fi if [ "$RUN_BACKUP" = true ]; then - ./backup_www.sh + ./backup.sh fi if [ "$RUN_RESTORE" = true ]; then - ./restore_www.sh + ./restore.sh fi if [ "$DEPLOY_ONION_SITE" = true ]; then @@ -71,6 +72,11 @@ if [ "$DEPLOY_ONION_SITE" = true ]; then fi if [ "$RUN_SERVICES" = true ]; then + mkdir -p "$SITE_PATH/stacks" + DOCKER_YAML_PATH="$SITE_PATH/stacks/www.yml" + export DOCKER_YAML_PATH="$DOCKER_YAML_PATH" + bash -c ./stub_docker_yml.sh + docker stack deploy -c "$DOCKER_YAML_PATH" webstack # start a browser session; point it to port 80 to ensure HTTPS redirect. diff --git a/deployment/restore_www.sh b/deployment/www/restore.sh similarity index 91% rename from deployment/restore_www.sh rename to deployment/www/restore.sh index 32ab1eb..3f66b41 100755 --- a/deployment/restore_www.sh +++ b/deployment/www/restore.sh @@ -13,7 +13,7 @@ ssh "$FQDN" sudo rm -rf "$REMOTE_HOME/*" ssh "$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/" "$FQDN:$REMOTE_HOME/backups/$APP_TO_DEPLOY" +scp -r "$LOCAL_BACKUP_PATH/" "$FQDN:$REMOTE_HOME/backups/$VIRTUAL_MACHINE" # now we run duplicity to restore the archive. ssh "$FQDN" sudo PASSPHRASE="$DUPLICITY_BACKUP_PASSPHRASE" duplicity --force restore "file://$REMOTE_BACKUP_PATH/" "$REMOTE_HOME/" diff --git a/deployment/stub_docker_yml.sh b/deployment/www/stub_docker_yml.sh similarity index 98% rename from deployment/stub_docker_yml.sh rename to deployment/www/stub_docker_yml.sh index cbbe013..01a04b4 100755 --- a/deployment/stub_docker_yml.sh +++ b/deployment/www/stub_docker_yml.sh @@ -122,11 +122,12 @@ cat >>"$DOCKER_YAML_PATH" <> "$(pwd)/env" - chmod 0744 "$(pwd)/env" - echo "We stubbed out a '$(pwd)/env' file for you. Put any LXD-remote specific information in there." - echo "Check out 'https://www.sovereign-stack.org/env' for an example." - exit 1 -fi - - # make ss-deploy available to the user if ! groups | grep -q docker; then sudo groupadd docker @@ -64,12 +54,12 @@ sudo usermod -aG docker "$USER" # make the Sovereign Stack commands available to the user. # we use ~/.bashrc ADDED_COMMAND=false -if ! cat "$HOME/.bashrc" | grep -q "ss-deploy"; then +if ! < "$HOME/.bashrc" grep -q "ss-deploy"; then echo "alias ss-deploy='/home/$USER/sovereign-stack/deploy.sh \$@'" >> "$HOME/.bashrc" ADDED_COMMAND=true fi -if ! cat "$HOME/.bashrc" | grep -q "ss-cluster"; then +if ! < "$HOME/.bashrc" grep -q "ss-cluster"; then echo "alias ss-cluster='/home/$USER/sovereign-stack/cluster.sh \$@'" >> "$HOME/.bashrc" ADDED_COMMAND=true fi diff --git a/management/registry_mirror.yml b/management/registry_mirror.yml index f6c39c6..a0d56a7 100644 --- a/management/registry_mirror.yml +++ b/management/registry_mirror.yml @@ -48,7 +48,7 @@ services: configs: registry-config: - file: ${LXD_REMOTE_PATH}/registry.yml + file: ${CLUSTER_PATH}/registry.yml volumes: registry_data: \ No newline at end of file diff --git a/reset.sh b/reset.sh new file mode 100755 index 0000000..4eafe62 --- /dev/null +++ b/reset.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +set -x + +CLUSTER_NAME="production-primary" +SSH_ENDPOINT="atlantis" +DOMAIN_NAME="ancapistan.io" +export LXD_VM_NAME="${DOMAIN_NAME//./-}" + +lxc delete --force www-"$LXD_VM_NAME" +lxc delete --force btcpay-"$LXD_VM_NAME" +lxc delete --force sovereign-stack + +lxc profile delete www-"$LXD_VM_NAME" +lxc profile delete umbrel-"$LXD_VM_NAME" +lxc profile delete btcpay-"$LXD_VM_NAME" +lxc profile delete sovereign-stack + +lxc image rm sovereign-stack-base +lxc image rm ubuntu-base + +lxc storage delete sovereign-stack + +lxc remote switch "local" +lxc remote remove "$CLUSTER_NAME" + +source "$HOME/.bashrc" + +./cluster.sh create "$CLUSTER_NAME" "$SSH_ENDPOINT.$DOMAIN_NAME" + +./deploy.sh diff --git a/shared.sh b/shared.sh index bcfe258..8032db0 100755 --- a/shared.sh +++ b/shared.sh @@ -14,10 +14,6 @@ if [ ! -d "$SITE_PATH" ]; then exit 1 fi -DOCKER_YAML_PATH="$SITE_PATH/appstack.yml" -export DOCKER_YAML_PATH="$DOCKER_YAML_PATH" -export REMOTE_HOME="/home/ubuntu" - mkdir -p "$SSHFS_PATH" # VALIDATE THE INPUT from the ENVFILE @@ -35,8 +31,6 @@ export ADMIN_ACCOUNT_USERNAME="info" export CERTIFICATE_EMAIL_ADDRESS="$ADMIN_ACCOUNT_USERNAME@$DOMAIN_NAME" export REMOTE_CERT_BASE_DIR="$REMOTE_HOME/.certs" - -export VM_NAME="sovereign-stack-base" export REMOTE_NEXTCLOUD_PATH="$REMOTE_HOME/nextcloud" export REMOTE_GITEA_PATH="$REMOTE_HOME/gitea" diff --git a/staging/Dockerfile b/staging/Dockerfile index b15cdc8..aca6b75 100644 --- a/staging/Dockerfile +++ b/staging/Dockerfile @@ -1,7 +1,7 @@ FROM ubuntu:22.04 ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get update && apt-get install -y wait-for-it dnsutils rsync duplicity sshfs snapd lxd-client +RUN apt-get update && apt-get install -y wait-for-it dnsutils rsync sshfs snapd lxd-client RUN mkdir /sovereign-stack COPY ./deployment /sovereign-stack diff --git a/deployment/tor.yml b/staging/tor.yml similarity index 100% rename from deployment/tor.yml rename to staging/tor.yml