Huge updates.

This commit is contained in:
Derek Smith 2022-07-27 12:38:33 -04:00
parent ff706a62ae
commit bb072c67dc
Signed by: farscapian
GPG Key ID: 8F1CD799CCA516CC
44 changed files with 1651 additions and 341 deletions

2
.gitignore vendored
View File

@ -1,3 +1,3 @@
env
clear_lxd.sh
publish_tag.sh
publish_tag.sh

View File

@ -13,8 +13,9 @@
"shellcheck.customArgs": [],
"shellcheck.ignorePatterns": {},
"shellcheck.exclude": [
"1090",
"1091"
"SC1090",
"SC1091",
"SC2029"
],
"terminal.integrated.fontFamily": "monospace",
"workbench.colorCustomizations": {

View File

@ -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?
All documentation for this project can be found at the [sovereign-stack.org](https://www.sovereign-stack.org).

View File

@ -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" <<EOL
#!/bin/bash
# Note: the path above ./ corresponds to your LXD Remote. If your remote is set to 'cluster1'
# Then $HOME/clusters/cluster1 will be your cluster working path.
# Then $HOME/ss-clusters/cluster1 will be your cluster working path.
export LXD_CLUSTER_PASSWORD="$(gpg --gen-random --armor 1 14)"
# This is REQUIRED. A list of all sites in ~/sites/ that will be deployed.
# This is REQUIRED. A list of all sites in ~/ss-sites/ that will be deployed.
# e.g., 'domain1.tld,domain2.tld,domain3.tld' Add all your domains that will
# run within this SS deployment.
SITE_LIST="domain1.tld"
# Deploy a registry cache on your management machine.
DEPLOY_REGISTRY=true
# only relevant
export REGISTRY_URL="http://${HOSTNAME}:5000"
export REGISTRY_URL="http://$(hostname).$(resolvectl status | grep 'DNS Domain:' | awk '{ print $3 }'):5000"
export REGISTRY_USERNAME=""
export REGISTRY_PASSWORD=""
@ -61,8 +60,7 @@ EOL
source "$CLUSTER_DEFINITION"
if ! lxc remote list | grep -q "$CLUSTER_NAME"; then
FQDN="$3"
echo "FQDN: $FQDN"
FQDN="${3:-}"
if [ -z "$FQDN" ]; then
echo "ERROR: The Fully Qualified Domain Name of the new cluster member was not set."
@ -143,7 +141,9 @@ EOL
# The MGMT Plane IP is the IP address that the LXD API binds to, which happens
# to be the same as whichever SSH connection you're coming in on.
MGMT_PLANE_IP="$(ssh ubuntu@"$FQDN" env | grep SSH_CONNECTION | cut -d " " -f 3)"
IP_OF_MGMT_MACHINE="$(ssh ubuntu@"$FQDN" env | grep SSH_CLIENT | cut -d " " -f 1 )"
IP_OF_MGMT_MACHINE="${IP_OF_MGMT_MACHINE#*=}"
IP_OF_MGMT_MACHINE="$(echo "$IP_OF_MGMT_MACHINE" | cut -d: -f1)"
# if the LXD_CLUSTER_PASSWORD wasnt set, we can generate a random one using gpg.
if [ -z "$LXD_CLUSTER_PASSWORD" ]; then
@ -163,13 +163,8 @@ EOL
ssh -t "ubuntu@$FQDN" "
# set host firewall policy.
# allow SSH from management network.
sudo ufw allow from 192.168.1.0/24 proto tcp to $MGMT_PLANE_IP port 22
sudo ufw allow from 192.168.4.0/24 proto tcp to $MGMT_PLANE_IP port 8443
# allow 8443 from management subnets
sudo ufw allow from 192.168.1.0/24 proto tcp to $MGMT_PLANE_IP port 8443
sudo ufw allow from 192.168.4.0/24 proto tcp to $MGMT_PLANE_IP port 8443
# allow LXD API from management network.
sudo ufw allow from ${IP_OF_MGMT_MACHINE}/32 proto tcp to $MGMT_PLANE_IP port 8443
# enable it.
if sudo ufw status | grep -q 'Status: inactive'; then
@ -189,7 +184,7 @@ fi
fi
# stub out the lxd init file for the remote SSH endpoint.
CLUSTER_MASTER_LXD_INIT="$LXD_REMOTE_PATH/$CLUSTER_NAME-primary.yml"
CLUSTER_MASTER_LXD_INIT="$CLUSTER_PATH/$CLUSTER_NAME-primary.yml"
cat >"$CLUSTER_MASTER_LXD_INIT" <<EOF
config:
core.https_address: ${MGMT_PLANE_IP}:8443
@ -235,18 +230,18 @@ EOF
cat "$CLUSTER_MASTER_LXD_INIT" | ssh "ubuntu@$FQDN" lxd init --preseed
# not ensure the service is active on the remote host.
if wait-for-it -t 5 "$FQDN:8443"; then
if wait-for-it -t 20 "$FQDN:8443"; then
# now create a remote on your local LXC client and switch to it.
# the software will now target the new cluster.
lxc remote add "$CLUSTER_NAME" "$FQDN" --password="$LXD_CLUSTER_PASSWORD" --protocol=lxd --auth-type=tls --accept-certificate
lxc remote switch "$CLUSTER_NAME"
echo "INFO: You have create a new cluster named '$CLUSTER_NAME'. Great! We switched your lxd remote to it."
else
echo "ERROR: Could not detect the LXD endpoint. Something went wrong."
exit 1
fi
echo "SUCCESS: Congrats, you have created a new LXD cluster named '$CLUSTER_NAME'. We create a new lxd remote and switched your local lxd client to it."
echo " You can go inspect by running 'lxc remote list'. Your current cluster path is '$CLUSTER_DEFINITION'."
echo ""
echo "HINT: Now you can consider running 'ss-deploy'."
else
echo "ERROR: invalid command."

View File

@ -70,7 +70,7 @@ export DUPLICITY_BACKUP_PASSPHRASE=
export SSH_HOME="$HOME/.ssh"
export VLAN_INTERFACE=
export VM_NAME=
export VM_NAME="sovereign-stack-base"
export DEV_MEMORY_MB="4096"
export DEV_CPU_COUNT="4"
export SSHFS_PATH="/tmp/sshfs_temp"
@ -91,7 +91,7 @@ export LATEST_GIT_COMMIT="$LATEST_GIT_COMMIT"
# exit 1
# fi
ENABLE_NGINX_CACHING=true
ENABLE_NGINX_CACHING=false
# TODO
@ -104,22 +104,35 @@ BTC_CHAIN=regtest
export BTC_CHAIN="$BTC_CHAIN"
DEFAULT_DB_IMAGE="mariadb:10.6.5"
DEFAULT_DB_IMAGE="mariadb:10.8.3-jammy"
export ENABLE_NGINX_CACHING="$ENABLE_NGINX_CACHING"
# run the docker stack.
export GHOST_IMAGE="ghost:4.44.0"
export GHOST_IMAGE="ghost:5.2.4"
export GHOST_DB_IMAGE="$DEFAULT_DB_IMAGE"
export NGINX_IMAGE="nginx:1.21.6"
export NEXTCLOUD_IMAGE="nextcloud:23.0.2"
export NGINX_IMAGE="nginx:1.23.0"
export NEXTCLOUD_IMAGE="nextcloud:24.0.2"
export NEXTCLOUD_DB_IMAGE="$DEFAULT_DB_IMAGE"
export GITEA_IMAGE="gitea/gitea:latest"
export GITEA_DB_IMAGE="$DEFAULT_DB_IMAGE"
export SOVEREIGN_STACK_MAC_ADDRESS="aa:bb:cc:00:00:03"
export WWW_MAC_ADDRESS="aa:bb:cc:00:00:00"
export BTCPAY_MAC_ADDRESS="aa:bb:cc:00:00:01"
export UMBREL_MAC_ADDRESS="aa:bb:cc:00:00:02"
export CLUSTERS_DIR="$HOME/ss-clusters"
export SITES_PATH="$HOME/ss-sites"
# The base VM image.
export BASE_LXC_IMAGE="ubuntu/22.04/cloud"
# Deploy a registry cache on your management machine.
export DEPLOY_MGMT_REGISTRY=true
export REMOTE_HOME="/home/ubuntu"
export BTCPAY_SERVER_APPPATH="$REMOTE_HOME/btcpayserver-docker"

165
deploy.sh
View File

@ -13,7 +13,8 @@ check_dependencies () {
}
# Check system's dependencies
check_dependencies wait-for-it dig rsync sshfs lxc docker-machine duplicity
check_dependencies wait-for-it dig rsync sshfs lxc docker-machine
# TODO remove dependency on Docker-machine. That's what we use to provision VM on 3rd party vendors. Looking for LXD endpoint.
# let's check to ensure the management machine is on the Baseline ubuntu 21.04
@ -24,15 +25,18 @@ fi
MIGRATE_VPS=false
DOMAIN_NAME=
RESTORE_ARCHIVE=
VPS_HOSTING_TARGET=lxd
RUN_CERT_RENEWAL=true
USER_NO_BACKUP=false
USER_RUN_RESTORE=false
RESTORE_BTCPAY=false
USER_SKIP_WWW=false
USER_SKIP_BTCPAY=false
UPDATE_BTCPAY=false
RECONFIGURE_BTCPAY_SERVER=false
DEPLOY_BTCPAY_SERVER=false
CURRENT_REMOTE="$(lxc remote get-default)"
CLUSTER_NAME="$(lxc remote get-default)"
# grab any modifications from the command line.
for i in "$@"; do
@ -41,12 +45,20 @@ for i in "$@"; do
VPS_HOSTING_TARGET=aws
shift
;;
--restore)
--restore-www)
USER_RUN_RESTORE=true
RUN_CERT_RENEWAL=false
USER_NO_BACKUP=true
shift
;;
--restore-btcpay)
RESTORE_BTCPAY=true
shift
;;
--archive=*)
RESTORE_ARCHIVE="${i#*=}"
shift
;;
--domain=*)
DOMAIN_NAME="${i#*=}"
shift
@ -55,12 +67,22 @@ for i in "$@"; do
UPDATE_BTCPAY=true
shift
;;
--skip-www)
USER_SKIP_WWW=true
shift
;;
--skip-btcpay)
USER_SKIP_BTCPAY=true
shift
;;
--no-backup)
USER_NO_BACKUP=true
shift
;;
--migrate)
--migrate-btcpay)
MIGRATE_VPS=true
RESTORE_BTCPAY=true
RUN_CERT_RENEWAL=false
shift
;;
--no-cert-renew)
@ -84,29 +106,36 @@ export CACHES_DIR="$HOME/ss-cache"
export SSH_HOME="$HOME/.ssh"
export DOMAIN_NAME="$DOMAIN_NAME"
export REGISTRY_DOCKER_IMAGE="registry:2"
export RESTORE_ARCHIVE="$RESTORE_ARCHIVE"
if [ "$VPS_HOSTING_TARGET" = aws ]; then
CURRENT_REMOTE="docker-machine"
if [ -z "$DOMAIN_NAME" ]; then
echo "ERROR: Please specify a domain name with --domain= when using --aws."
exit 1
fi
CLUSTER_NAME="docker-machine"
fi
export CURRENT_REMOTE="$CURRENT_REMOTE"
export LXD_REMOTE_PATH="$CLUSTERS_DIR/$CURRENT_REMOTE"
export CLUSTER_NAME="$CLUSTER_NAME"
export CLUSTER_PATH="$CLUSTERS_DIR/$CLUSTER_NAME"
# ensure our cluster path is created.
mkdir -p "$LXD_REMOTE_PATH"
mkdir -p "$CLUSTER_PATH"
# if an authorized_keys file does not exist, we'll stub one out with the current user.
# add additional id_rsa.pub entries manually for more administrative logins.
if [ ! -f "$LXD_REMOTE_PATH/authorized_keys" ]; then
cat "$SSH_HOME/id_rsa.pub" >> "$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" <<EOL
cat > "$CLUSTER_PATH/registry.yml" <<EOL
version: 0.1
http:
addr: 0.0.0.0:5000
@ -146,18 +175,35 @@ EOL
mkdir -p "${CACHES_DIR}/registry_images"
# run a docker reigstry pull through cache on the management
if ! docker stack list | grep -q registry; then
docker stack deploy -c management/registry_mirror.yml registry
# run a docker registry pull through cache on the management machine.
if [ "$DEPLOY_MGMT_REGISTRY" = true ]; then
if ! docker stack list | grep -q registry; then
docker stack deploy -c management/registry_mirror.yml registry
fi
fi
fi
fi
# this is our password generation mechanism. Relying on GPG for secure password generation
function new_pass {
apg -a 1 -M nc -n 3 -m 26 -E GHIJKLMNOPQRSTUVWXYZ | head -n1 | awk '{print $1;}'
gpg --gen-random --armor 1 25
}
if [ "$VPS_HOSTING_TARGET" = lxd ]; then
# first let's get the DISK_TO_USE and DATA_PLANE_MACVLAN_INTERFACE from the ss-config
# which is set up during LXD cluster creation ss-cluster.
LXD_SS_CONFIG_LINE="$(lxc network list --format csv | grep ss-config)"
CONFIG_ITEMS="$(echo "$LXD_SS_CONFIG_LINE" | awk -F'"' '{print $2}')"
DATA_PLANE_MACVLAN_INTERFACE="$(echo "$CONFIG_ITEMS" | cut -d ',' -f2)"
DISK_TO_USE="$(echo "$CONFIG_ITEMS" | cut -d ',' -f3)"
export DATA_PLANE_MACVLAN_INTERFACE="$DATA_PLANE_MACVLAN_INTERFACE"
export DISK_TO_USE="$DISK_TO_USE"
./deployment/create_lxc_base.sh
fi
function run_domain {
export VPS_HOSTING_TARGET="$VPS_HOSTING_TARGET"
@ -170,7 +216,8 @@ function run_domain {
# iterate over all our server endpoints and provision them if needed.
# www
VPS_HOSTNAME=
for APP_TO_DEPLOY in www btcpay umbrel; do
# OPTINOAL umbrel
for VIRTUAL_MACHINE in www btcpayserver umbrel; do
FQDN=
# shellcheck disable=SC1091
@ -190,11 +237,11 @@ function run_domain {
export MAC_ADDRESS_TO_PROVISION=
export VPS_HOSTNAME="$VPS_HOSTNAME"
export FQDN="$VPS_HOSTNAME.$DOMAIN_NAME"
export APP_TO_DEPLOY="$APP_TO_DEPLOY"
export VIRTUAL_MACHINE="$VIRTUAL_MACHINE"
BACKUP_TIMESTAMP="$(date +"%Y-%m")"
UNIX_BACKUP_TIMESTAMP="$(date +%s)"
export REMOTE_BACKUP_PATH="$REMOTE_HOME/backups/$APP_TO_DEPLOY/$BACKUP_TIMESTAMP"
LOCAL_BACKUP_PATH="$SITE_PATH/backups/$APP_TO_DEPLOY/$BACKUP_TIMESTAMP"
export REMOTE_BACKUP_PATH="$REMOTE_HOME/backups/$VIRTUAL_MACHINE/$BACKUP_TIMESTAMP"
LOCAL_BACKUP_PATH="$SITE_PATH/backups/$VIRTUAL_MACHINE/$BACKUP_TIMESTAMP"
export LOCAL_BACKUP_PATH="$LOCAL_BACKUP_PATH"
export BACKUP_TIMESTAMP="$BACKUP_TIMESTAMP"
@ -208,16 +255,20 @@ function run_domain {
fi
DDNS_HOST=
if [ "$APP_TO_DEPLOY" = www ]; then
if [ "$VIRTUAL_MACHINE" = www ]; then
if [ "$DEPLOY_WWW_SERVER" = false ] || [ "$USER_SKIP_WWW" = true ]; then
continue
fi
VPS_HOSTNAME="$WWW_HOSTNAME"
MAC_ADDRESS_TO_PROVISION="$WWW_MAC_ADDRESS"
DDNS_HOST="$WWW_HOSTNAME"
ROOT_DISK_SIZE_GB="$((ROOT_DISK_SIZE_GB + NEXTCLOUD_SPACE_GB))"
if [ "$DEPLOY_WWW_SERVER" = false ]; then
elif [ "$VIRTUAL_MACHINE" = btcpayserver ] || [ "$USER_SKIP_BTCPAY" = true ]; then
if [ "$DEPLOY_BTCPAY_SERVER" = false ]; then
continue
fi
elif [ "$APP_TO_DEPLOY" = btcpay ]; then
DDNS_HOST="$BTCPAY_HOSTNAME"
VPS_HOSTNAME="$BTCPAY_HOSTNAME"
MAC_ADDRESS_TO_PROVISION="$BTCPAY_MAC_ADDRESS"
@ -226,12 +277,11 @@ function run_domain {
elif [ "$BTC_CHAIN" = testnet ]; then
ROOT_DISK_SIZE_GB=40
fi
if [ "$DEPLOY_BTCPAY_SERVER" = false ]; then
elif [ "$VIRTUAL_MACHINE" = umbrel ]; then
if [ "$DEPLOY_UMBREL_VPS" = false ]; then
continue
fi
elif [ "$APP_TO_DEPLOY" = umbrel ]; then
DDNS_HOST="$UMBREL_HOSTNAME"
VPS_HOSTNAME="$UMBREL_HOSTNAME"
MAC_ADDRESS_TO_PROVISION="$UMBREL_MAC_ADDRESS"
@ -240,15 +290,12 @@ function run_domain {
elif [ "$BTC_CHAIN" = testnet ]; then
ROOT_DISK_SIZE_GB=70
fi
if [ "$DEPLOY_UMBREL_VPS" = false ]; then
continue
fi
elif [ "$APP_TO_DEPLOY" = certonly ]; then
DDNS_HOST="$WWW_HOSTNAME"
elif [ "$VIRTUAL_MACHINE" = "sovereign-stack" ]; then
DDNS_HOST="sovereign-stack-base"
ROOT_DISK_SIZE_GB=8
MAC_ADDRESS_TO_PROVISION="$SOVEREIGN_STACK_MAC_ADDRESS"
else
echo "ERROR: APP_TO_DEPLOY not within allowable bounds."
echo "ERROR: VIRTUAL_MACHINE not within allowable bounds."
exit
fi
@ -328,7 +375,6 @@ function run_domain {
exit 1
fi
if [ -z "$DEPLOY_UMBREL_VPS" ]; then
echo "ERROR: Ensure DEPLOY_UMBREL_VPS is configured in your site_definition."
exit 1
@ -339,9 +385,7 @@ function run_domain {
echo "INFO: Go to your site_definition file and set the NOSTR_ACCOUNT_PUBKEY variable."
exit 1
fi
# generate the docker yaml and nginx configs.
bash -c ./deployment/stub_docker_yml.sh
bash -c ./deployment/stub_nginxconf.sh
MACHINE_EXISTS=false
@ -360,19 +404,19 @@ function run_domain {
if [ "$MACHINE_EXISTS" = true ]; then
# we delete the machine if the user has directed us to
if [ "$MIGRATE_VPS" = true ]; then
# run the domain_init based on user input.
if [ "$USER_NO_BACKUP" = true ]; then
echo "Machine exists. We don't need to back it up because the user has directed --no-backup."
else
echo "Machine exists. Since we're going to delete it, let's grab a backup. We don't need to restore services since we're deleting it."
RUN_RESTORE=false RUN_BACKUP=true RUN_SERVICES=false "$(pwd)/deployment/domain_init.sh"
fi
# get a backup of the machine. This is what we restore to the new VPS.
echo "INFO: Machine exists. Since we're going to delete it, let's grab a backup. We don't need to restore services since we're deleting it."
RESTORE_BTCPAY=false UPDATE_BTCPAY=false RUN_RESTORE=false RUN_BACKUP=true RUN_SERVICES=false ./deployment/domain_init.sh
# delete the remote VPS.
if [ "$VPS_HOSTING_TARGET" = aws ]; then
if [ "$APP_TO_DEPLOY" != btcpay ]; then
# docker-machine rm -f "$FQDN"
echo "ERROR: NOT IMPLEMENTED"
RESPONSE=
read -r -p "Do you want to continue with deleting '$FQDN' (y/n)": RESPONSE
if [ "$RESPONSE" = y ]; then
docker-machine rm -f "$FQDN"
else
echo "STOPPING the migration. User entered something other than 'y'."
exit 1
fi
elif [ "$VPS_HOSTING_TARGET" = lxd ]; then
lxc delete --force "$LXD_VM_NAME"
@ -382,7 +426,7 @@ function run_domain {
# Then we run the script again to re-instantiate a new VPS, restoring all user data
# if restore directory doesn't exist, then we end up with a new site.
echo "INFO: Recreating the remote VPS then restoring user data."
RUN_RESTORE="$USER_RUN_RESTORE" RUN_BACKUP=false RUN_SERVICES=true "$(pwd)/deployment/domain_init.sh"
RESTORE_BTCPAY=true UPDATE_BTCPAY=false RUN_RESTORE=true RUN_BACKUP=false RUN_SERVICES=true ./deployment/domain_init.sh
else
if [ "$USER_NO_BACKUP" = true ]; then
RUN_BACKUP=false
@ -392,7 +436,7 @@ function run_domain {
echo "INFO: Maintaining existing VPS. RUN_BACKUP=$RUN_BACKUP RUN_RESTORE=$USER_RUN_RESTORE"
fi
RUN_RESTORE="$USER_RUN_RESTORE" RUN_BACKUP="$RUN_BACKUP" RUN_SERVICES=true "$(pwd)/deployment/domain_init.sh"
RESTORE_BTCPAY=false UPDATE_BTCPAY="$UPDATE_BTCPAY" RUN_RESTORE="$USER_RUN_RESTORE" RUN_BACKUP="$RUN_BACKUP" RUN_SERVICES=true ./deployment/domain_init.sh
fi
else
if [ "$MIGRATE_VPS" = true ]; then
@ -401,7 +445,7 @@ function run_domain {
# The machine does not exist. Let's bring it into existence, restoring from latest backup.
echo "Machine does not exist. RUN_RESTORE=$USER_RUN_RESTORE RUN_BACKUP=false"
RUN_RESTORE="$USER_RUN_RESTORE" RUN_BACKUP=false RUN_SERVICES=true "$(pwd)/deployment/domain_init.sh"
RESTORE_BTCPAY=false UPDATE_BTCPAY="$UPDATE_BTCPAY" RUN_RESTORE="$USER_RUN_RESTORE" RUN_BACKUP=false RUN_SERVICES=true ./deployment/domain_init.sh
fi
done
@ -425,7 +469,7 @@ function stub_site_definition {
#!/bin/bash
# Set the domain name for the identity site.
export DOMAIN_NAME="domain.tld"
export DOMAIN_NAME="${DOMAIN_NAME}"
# duplicitiy backup archive password
export DUPLICITY_BACKUP_PASSPHRASE="$(new_pass)"
@ -436,9 +480,6 @@ export DUPLICITY_BACKUP_PASSPHRASE="$(new_pass)"
## WWW
export DEPLOY_WWW_SERVER=true
# see https://www.sovereign-stack.org/mac-addresses-for-new-type-vms/ for more info
# export WWW_MAC_ADDRESS="CHANGE_ME"
# Deploy APPS to www
export DEPLOY_GHOST=true
export DEPLOY_NEXTCLOUD=true
@ -466,15 +507,9 @@ export GITEA_MYSQL_ROOT_PASSWORD="$(new_pass)"
## BTCPAY SERVER; if true, then a BTCPay server is deployed.
export DEPLOY_BTCPAY_SERVER=false
# https://www.sovereign-stack.org/mac-addresses-for-new-type-vms/
#export BTCPAY_MAC_ADDRESS=""
## Deploy and Umbrel node?
export DEPLOY_UMBREL_VPS=false
# REQUIRED if DEPLOY_UMBREL_VPS=true; https://www.sovereign-stack.org/mac-addresses-for-new-type-vms/
# export UMBREL_MAC_ADDRESS=""
# CHAIN to DEPLOY; valid are 'regtest', 'testnet', and 'mainnet'
export BTC_CHAIN=regtest

View File

@ -1,3 +0,0 @@
# Documentation
Please visit the [https://www.sovereign-stack.org](Sovereign Stack) website for documentation related to this repository.

View File

@ -1,9 +1,22 @@
#!/bin/bash
set -e
set -exo
cd "$(dirname "$0")"
# take the services down, create a backup archive, then pull it down.
ssh "$FQDN" "cd $REMOTE_HOME/btcpayserver-docker/; sudo bash -c ./backup.sh"
# the script executed here from the BTCPAY repo will automatically take services down
# and bring them back up.
#ssh "$FQDN" "cd $REMOTE_HOME/; sudo BTCPAY_BASE_DIRECTORY=$REMOTE_HOME bash -c $BTCPAY_SERVER_APPPATH/btcpay-down.sh"
# TODO enable encrypted archives
# TODO switch to btcpay-backup.sh when on LXD fully.
scp ./btcpay-backup.sh "$FQDN:$REMOTE_HOME/btcpay-backup.sh"
ssh "$FQDN" "sudo cp $REMOTE_HOME/btcpay-backup.sh $BTCPAY_SERVER_APPPATH/btcpay-backup.sh && sudo chmod 0755 $BTCPAY_SERVER_APPPATH/btcpay-backup.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-backup.sh"
# next we pull the resulting backup archive down to our management machine.
ssh "$FQDN" "sudo cp /var/lib/docker/volumes/backup_datadir/_data/backup.tar.gz $REMOTE_HOME/backups/btcpay.tar.gz"
ssh "$FQDN" "sudo chown ubuntu:ubuntu $REMOTE_HOME/backups/btcpay.tar.gz"
scp "$FQDN:$REMOTE_HOME/backups/btcpay.tar.gz" "$LOCAL_BACKUP_PATH/btcpay-$1.tar.gz"
scp "$FQDN:$REMOTE_HOME/backups/btcpay.tar.gz" "$LOCAL_BACKUP_PATH/$1.tar.gz"

View File

@ -0,0 +1,113 @@
#!/bin/bash -e
set -o pipefail -o errexit -x
# Please be aware of these important issues:
#
# - Old channel state is toxic and you can loose all your funds, if you or someone
# else closes a channel based on the backup with old state - and the state changes
# often! If you publish an old state (say from yesterday's backup) on chain, you
# WILL LOSE ALL YOUR FUNDS IN A CHANNEL, because the counterparty will publish a
# revocation key!
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
# preparation
docker_dir=$(docker volume inspect generated_btcpay_datadir --format="{{.Mountpoint}}" | sed -e "s%/volumes/.*%%g")
dbdump_name=postgres.sql.gz
btcpay_dir="$BTCPAY_BASE_DIRECTORY/btcpayserver-docker"
backup_dir="$docker_dir/volumes/backup_datadir/_data"
dbdump_path="$docker_dir/$dbdump_name"
backup_path="$backup_dir/backup.tar.gz"
# ensure backup dir exists
if [ ! -d "$backup_dir" ]; then
mkdir -p "$backup_dir"
fi
cd "$btcpay_dir"
. helpers.sh
dbcontainer=$(docker ps -a -q -f "name=postgres_1")
if [ -z "$dbcontainer" ]; then
printf "\n"
echo " Database container is not up and running. Starting BTCPay Server …"
docker volume create generated_postgres_datadir
docker-compose -f "$BTCPAY_DOCKER_COMPOSE" up -d postgres
printf "\n"
dbcontainer=$(docker ps -a -q -f "name=postgres_1")
if [ -z "$dbcontainer" ]; then
echo "🚨 Database container could not be started or found."
exit 1
fi
fi
printf "\n"
echo " Dumping database …"
{
docker exec "$dbcontainer" pg_dumpall -c -U postgres | gzip > "$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"

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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" <<EOL
#!/bin/bash
set -ex
cd "\$(dirname "\$0")"
# wait for cloud-init to complete yo
while [ ! -f /var/lib/cloud/instance/boot-finished ]; do
sleep 1
done
# if [ -d "btcpayserver-docker" ] && [ "$EXISTING_BRANCH" != "master" ] && [ "$EXISTING_REMOTE" != "master" ]; then
# echo "existing btcpayserver-docker folder found that did not match our specified fork. Moving. (Current branch: $EXISTING_BRANCH, Current remote: $EXISTING_REMOTE)";
# mv "btcpayserver-docker" "btcpayserver-docker_$(date +%s)";
# fi
# if [ -d "btcpayserver-docker" ] && [ "$EXISTING_BRANCH" == "master" ] && [ "$EXISTING_REMOTE" == "master" ]; then
# echo "existing btcpayserver-docker folder found, pulling instead of cloning.";
# git pull;
# fi
#curl -SL https://github.com/docker/compose/releases/download/v2.6.1/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
#chmod 0777 /usr/local/bin/docker-compose
if [ ! -d "btcpayserver-docker" ]; then
echo "cloning btcpayserver-docker";
git clone -b master https://github.com/btcpayserver/btcpayserver-docker btcpayserver-docker;
git clone -b master https://github.com/btcpayserver/btcpayserver-docker btcpayserver-docker;
git config --global --add safe.directory /home/ubuntu/btcpayserver-docker
else
cd ./btcpayserver-docker
git pull
git pull --all --tags
cd -
fi
cd btcpayserver-docker
export BTCPAY_HOST="${FQDN}"
export NBITCOIN_NETWORK="${BTC_CHAIN}"
export LIGHTNING_ALIAS="${DOMAIN_NAME}"
@ -39,16 +42,12 @@ export LETSENCRYPT_EMAIL="${CERTIFICATE_EMAIL_ADDRESS}"
export BTCPAYGEN_LIGHTNING="clightning"
export BTCPAYGEN_CRYPTO1="btc"
# opt-save-storage keeps 1 year of blocks (prunes to 100 GB)
# opt-add-btctransmuter adds transmuter software
#
export BTCPAYGEN_ADDITIONAL_FRAGMENTS="opt-save-storage;opt-add-btctransmuter;opt-add-configurator;opt-add-nostr-relay;opt-add-tor-relay"
export BTCPAYGEN_ADDITIONAL_FRAGMENTS="opt-save-storage;opt-add-btctransmuter;opt-add-nostr-relay;opt-add-tor-relay"
#export BTCPAYGEN_EXCLUDE_FRAGMENTS="nginx-https"
export BTCPAY_ADDITIONAL_HOSTS="${BTCPAY_ADDITIONAL_HOSTNAMES}"
export BTCPAYGEN_REVERSEPROXY="nginx"
export BTCPAY_ENABLE_SSH=false
cd btcpayserver-docker
export BTCPAY_BASE_DIRECTORY=${REMOTE_HOME}
if [ "\$NBITCOIN_NETWORK" != regtest ]; then
# run fast_sync if it's not been done before.
@ -60,9 +59,10 @@ if [ "\$NBITCOIN_NETWORK" != regtest ]; then
fi
fi
# provision the btcpay server
# provision the btcpayserver
. ./btcpay-setup.sh -i
sleep 15
EOL
# send the setup script to the remote machine.

View File

@ -0,0 +1,123 @@
#!/bin/bash
# This script might look like a good idea. Please be aware of these important issues:
#
# - The backup file is not encrypted and it contains your lightning private keys.
# Consider encrypting before uploading or using another backup tool like duplicity.
# - Old channel state is toxic and you can loose all your funds, if you or someone
# else closes a channel based on the backup with old state - and the state changes
# often! If you publish an old state (say from yesterday's backup) on chain, you
# WILL LOSE ALL YOUR FUNDS IN A CHANNEL, because the counterparty will publish a
# revocation key!
if [ "$(id -u)" != "0" ]; then
echo "This script must be run as root."
echo "Use the command 'sudo su -' (include the trailing hypen) and try again"
exit 1
fi
case "$BACKUP_PROVIDER" in
"Dropbox")
if [ -z "$DROPBOX_TOKEN" ]; then
echo -e "\033[0;31mSet DROPBOX_TOKEN environment variable and try again.\033[0m"
exit 1
fi
;;
"S3")
echo -e "\033[1;33mUsing S3 backup provider. Make sure you have ran 'aws configure' on your root user and configured an AMI with access to your bucket.\033[0m"
if [ -z "$S3_BUCKET" ]; then
echo -e "\033[0;31mSet S3_BUCKET environment variable and try again.\033[0m"
exit 1
fi
if [ -z "$S3_PATH" ]; then
echo -e "\033[1;33mUsing bucket root for backup, set S3_PATH if you want to backup into a specific folder (Make sure it ends with a trailing slash).\033[0m"
fi
;;
"SCP")
if [ -z "$SCP_TARGET" ]; then
echo -e "\033[0;31mSet SCP_TARGET environment variable and try again.\033[0m"
exit 1
fi
;;
*)
echo "No BACKUP_PROVIDER set. Backing up to local directory."
;;
esac
# preparation
volumes_dir=/var/lib/docker/volumes
backup_dir="$volumes_dir/backup_datadir"
filename="backup.tar.gz"
dumpname="postgres.sql.gz"
if [ "$BACKUP_TIMESTAMP" == true ]; then
timestamp=$(date "+%Y%m%d-%H%M%S")
filename="$timestamp-$filename"
dumpname="$timestamp-$dumpname"
fi
backup_path="$backup_dir/_data/${filename}"
dbdump_path="$backup_dir/_data/${dumpname}"
cd "$BTCPAY_BASE_DIRECTORY/btcpayserver-docker"
. helpers.sh
# ensure backup dir exists
if [ ! -d "$backup_dir" ]; then
docker volume create backup_datadir
fi
# dump database
echo "Dumping database …"
btcpay_dump_db $dbdump_path
if [[ "$1" == "--only-db" ]]; then
tar -cvzf $backup_path $dbdump_path
else
# stop docker containers, save files and restart
echo "Stopping BTCPay Server …"
btcpay_down
echo "Backing up files …"
tar --exclude="$backup_path" --exclude="$volumes_dir/generated_bitcoin_datadir/*" --exclude="$volumes_dir/generated_litecoin_datadir/*" --exclude="$volumes_dir/generated_postgres_datadir/*" --exclude="$volumes_dir/**/logs/*" -cvzf $backup_path $dbdump_path $volumes_dir
echo "Restarting BTCPay Server …"
btcpay_up
fi
# post processing
case $BACKUP_PROVIDER in
"Dropbox")
echo "Uploading to Dropbox …"
docker run --name backup --env DROPBOX_TOKEN=$DROPBOX_TOKEN -v backup_datadir:/data jvandrew/btcpay-dropbox:1.0.5 $filename
echo "Deleting local backup …"
rm $backup_path
;;
"S3")
echo "Uploading to S3 …"
docker run --rm -v ~/.aws:/root/.aws -v $backup_path:/aws/$filename amazon/aws-cli s3 cp $filename s3://$S3_BUCKET/$S3_PATH
echo "Deleting local backup …"
rm $backup_path
;;
"SCP")
echo "Uploading via SCP …"
scp $backup_path $SCP_TARGET
echo "Deleting local backup …"
rm $backup_path
;;
*)
echo "Backed up to $backup_path"
;;
esac
# cleanup
rm $dbdump_path
echo "Backup done."

View File

@ -0,0 +1,113 @@
#!/bin/bash -e
set -o pipefail -o errexit
# Please be aware of these important issues:
#
# - Old channel state is toxic and you can loose all your funds, if you or someone
# else closes a channel based on the backup with old state - and the state changes
# often! If you publish an old state (say from yesterday's backup) on chain, you
# WILL LOSE ALL YOUR FUNDS IN A CHANNEL, because the counterparty will publish a
# revocation key!
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
# preparation
docker_dir=$(docker volume inspect generated_btcpay_datadir --format="{{.Mountpoint}}" | sed -e "s%/volumes/.*%%g")
dbdump_name=postgres.sql.gz
btcpay_dir="$BTCPAY_BASE_DIRECTORY/btcpayserver-docker"
backup_dir="$docker_dir/volumes/backup_datadir/_data"
dbdump_path="$docker_dir/$dbdump_name"
backup_path="$backup_dir/backup.tar.gz"
# ensure backup dir exists
if [ ! -d "$backup_dir" ]; then
mkdir -p $backup_dir
fi
cd $btcpay_dir
. helpers.sh
dbcontainer=$(docker ps -a -q -f "name=postgres_1")
if [ -z "$dbcontainer" ]; then
printf "\n"
echo " Database container is not up and running. Starting BTCPay Server …"
docker volume create generated_postgres_datadir
docker-compose -f $BTCPAY_DOCKER_COMPOSE up -d postgres
printf "\n"
dbcontainer=$(docker ps -a -q -f "name=postgres_1")
if [ -z "$dbcontainer" ]; then
echo "🚨 Database container could not be started or found."
exit 1
fi
fi
printf "\n"
echo " Dumping database …"
{
docker exec $dbcontainer pg_dumpall -c -U postgres | gzip > $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"

View File

@ -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"

View File

@ -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

View File

@ -1,3 +0,0 @@
#!/bin/bash
bash -c ./deploy.sh --domain=bitizen.store --hosting-provider=lxd --macvlan-interface=eno3 --storage-backend=/dev/sda

63
deployment/create_lxc_base.sh Executable file
View File

@ -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

View File

@ -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;"

View File

@ -1,2 +0,0 @@
#!/bin/bash

View File

@ -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

View File

@ -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.

View File

@ -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"

View File

@ -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" <<EOF
config:
limits.cpu: "${DEV_CPU_COUNT}"
limits.memory: "${DEV_MEMORY_MB}MB"
EOF
# if VIRTUAL_MACHINE=sovereign-stack then we are building the base image.
if [ "$VIRTUAL_MACHINE" = "sovereign-stack" ]; then
# this is for the base image only...
cat >> "$YAML_PATH" <<EOF
user.vendor-data: |
#cloud-config
apt_mirror: http://us.archive.ubuntu.com/ubuntu/
package_update: true
package_upgrade: false
package_reboot_if_required: false
preserve_hostname: false
fqdn: ${FQDN}
fqdn: sovereign-stack
packages:
- curl
@ -33,11 +57,9 @@ config:
- dnsutils
- wget
groups:
- docker
users:
- name: ubuntu
groups: docker
@ -49,7 +71,7 @@ config:
write_files:
- path: ${REMOTE_HOME}/docker.asc
- path: /home/ubuntu/docker.asc
content: |
-----BEGIN PGP PUBLIC KEY BLOCK-----
@ -132,19 +154,41 @@ config:
]
}
runcmd:
- cat ${REMOTE_HOME}/docker.asc | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
- sudo rm ${REMOTE_HOME}/docker.asc
- cat /home/ubuntu/docker.asc | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
- sudo rm /home/ubuntu/docker.asc
- echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list
- sudo apt-get update
- sudo apt-get install -y docker-ce docker-ce-cli containerd.io
- echo "alias ll='ls -lah'" >> ${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" <<EOF
user.vendor-data: |
#cloud-config
apt_mirror: http://us.archive.ubuntu.com/ubuntu/
package_update: false
package_upgrade: false
package_reboot_if_required: false
preserve_hostname: false
fqdn: ${FQDN}
EOF
fi
# If we are deploying the www, we attach the vm to the underlay via macvlan.
cat >> "$YAML_PATH" <<EOF
description: Default LXD profile for ${FILENAME}
devices:
root:
path: /
@ -153,3 +197,26 @@ devices:
config:
source: cloud-init:config
type: disk
EOF
# If we are deploying the www, we attach the vm to the underlay via macvlan.
cat >> "$YAML_PATH" <<EOF
enp5s0:
nictype: macvlan
parent: ${DATA_PLANE_MACVLAN_INTERFACE}
type: nic
enp6s0:
nictype: bridged
parent: lxdfanSS
type: nic
name: ${FILENAME}
EOF
# let's create a profile for the BCM TYPE-1 VMs. This is per VM.
if ! lxc profile list --format csv | grep -q "$VIRTUAL_MACHINE"; then
lxc profile create "$VIRTUAL_MACHINE"
fi
# configure the profile with our generated cloud-init.yml file.
cat "$YAML_PATH" | lxc profile edit "$VIRTUAL_MACHINE"

View File

@ -205,6 +205,7 @@ cat >>"$NGINX_CONF_PATH" <<EOL
}
location / {
#set_from_accept_language \$lang en es;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header Host \$http_host;

26
deployment/wait_for_lxc_ip.sh Executable file
View File

@ -0,0 +1,26 @@
#!/bin/bash
set -ex
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"
echo ""
break
else
sleep 1
printf '.'
fi
done
# 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 /home/ubuntu

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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/"

View File

@ -122,11 +122,12 @@ cat >>"$DOCKER_YAML_PATH" <<EOL
environment:
- USER_UID=1000
- USER_GID=1000
- ROOT_URL=https://${GITEA_FQDN}
- GITEA__database__DB_TYPE=mysql
- GITEA__database__HOST=gitea-db:3306
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__PASSWD=${GITEA_MYSQL_PASSWORD}
- GITEA__PASSWD=\${GITEA_MYSQL_PASSWORD}
networks:
- gitea-net
- giteadb-net

View File

@ -44,16 +44,6 @@ if [ ! -f /usr/local/bin/docker-machine ]; then
sudo cp /tmp/docker-machine /usr/local/bin/docker-machine
fi
# if there's a ./env file here, let's execute it. Admins can put various deployment-specific things there.
if [ ! -f "$(pwd)/env" ]; then
echo "#!/bin/bash" >> "$(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

View File

@ -48,7 +48,7 @@ services:
configs:
registry-config:
file: ${LXD_REMOTE_PATH}/registry.yml
file: ${CLUSTER_PATH}/registry.yml
volumes:
registry_data:

31
reset.sh Executable file
View File

@ -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

View File

@ -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"

View File

@ -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