Multilanguage ghost and other updates.

This commit is contained in:
Derek Smith 2022-09-28 13:59:01 -04:00
parent 8d0af43339
commit 5a9c27c54f
Signed by: farscapian
GPG Key ID: 8F1CD799CCA516CC
16 changed files with 490 additions and 351 deletions

1
NOTES Normal file
View File

@ -0,0 +1 @@
Trezor MUST Use the "Crypto" firmware with shitcoin support in order for 2FA (WEBAUTHN) to work. Bummer.

View File

@ -73,8 +73,7 @@ export VLAN_INTERFACE=
export VM_NAME="sovereign-stack-base"
export DEV_MEMORY_MB="4096"
export DEV_CPU_COUNT="4"
export SSHFS_PATH="/tmp/sshfs_temp"
mkdir -p "$SSHFS_PATH"
export DOCKER_IMAGE_CACHE_FQDN="registry-1.docker.io"
export NEXTCLOUD_SPACE_GB=10
@ -92,7 +91,7 @@ export NEXTCLOUD_SPACE_GB=10
# exit 1
# fi
ENABLE_NGINX_CACHING=false
# TODO
@ -105,16 +104,17 @@ BTC_CHAIN=regtest
export BTC_CHAIN="$BTC_CHAIN"
DEFAULT_DB_IMAGE="mariadb:10.8.3-jammy"
export ENABLE_NGINX_CACHING="$ENABLE_NGINX_CACHING"
DEFAULT_DB_IMAGE="mariadb:10.9.3-jammy"
# run the docker stack.
export GHOST_IMAGE="ghost:5.12.3"
export GHOST_IMAGE="ghost:5.14.2"
export GHOST_DB_IMAGE="$DEFAULT_DB_IMAGE"
export NGINX_IMAGE="nginx:1.23.1"
export NEXTCLOUD_IMAGE="nextcloud:24.0.4"
export NEXTCLOUD_IMAGE="nextcloud:24.0.5"
export NEXTCLOUD_DB_IMAGE="$DEFAULT_DB_IMAGE"
# TODO PIN the gitea version number.
export GITEA_IMAGE="gitea/gitea:latest"
export GITEA_DB_IMAGE="$DEFAULT_DB_IMAGE"

View File

@ -27,12 +27,13 @@ fi
DOMAIN_NAME=
RESTORE_ARCHIVE=
VPS_HOSTING_TARGET=lxd
RUN_CERT_RENEWAL=true
RUN_CERT_RENEWAL=false
RESTORE_WWW=false
BACKUP_WWW=true
BACKUP_CERTS=true
BACKUP_GHOST=true
RESTORE_BTCPAY=false
BACKUP_BTCPAY=true
BACKUP_BTCPAY=false
MIGRATE_WWW=false
MIGRATE_BTCPAY=false
@ -52,7 +53,7 @@ for i in "$@"; do
;;
--restore-www)
RESTORE_WWW=true
BACKUP_WWW=false
BACKUP_GHOST=false
RUN_CERT_RENEWAL=false
shift
;;
@ -61,6 +62,10 @@ for i in "$@"; do
BACKUP_BTCPAY=false
shift
;;
--backup-certs)
BACKUP_CERTS=true
shift
;;
--archive=*)
RESTORE_ARCHIVE="${i#*=}"
shift
@ -81,12 +86,12 @@ for i in "$@"; do
USER_SKIP_BTCPAY=true
shift
;;
--no-backup-www)
BACKUP_WWW=false
--backup-ghost)
BACKUP_GHOST=true
shift
;;
--no-backup-btcpay)
BACKUP_BTCPAY=false
--backup-btcpay)
BACKUP_BTCPAY=true
shift
;;
--migrate-www)
@ -99,8 +104,8 @@ for i in "$@"; do
RUN_CERT_RENEWAL=false
shift
;;
--no-cert-renew)
RUN_CERT_RENEWAL=false
--renew-certs)
RUN_CERT_RENEWAL=true
shift
;;
--reconfigure-btcpay)
@ -123,7 +128,9 @@ export DOMAIN_NAME="$DOMAIN_NAME"
export REGISTRY_DOCKER_IMAGE="registry:2"
export RESTORE_ARCHIVE="$RESTORE_ARCHIVE"
export RESTORE_WWW="$RESTORE_WWW"
export BACKUP_WWW="$BACKUP_WWW"
export BACKUP_CERTS="$BACKUP_CERTS"
export BACKUP_GHOST="$BACKUP_GHOST"
export RESTORE_BTCPAY="$RESTORE_BTCPAY"
export BACKUP_BTCPAY="$RESTORE_BTCPAY"
export MIGRATE_WWW="$MIGRATE_WWW"
@ -252,10 +259,6 @@ function instantiate_vms {
fi
# create the local packup path if it's not there!
BACKUP_PATH_CREATED=false
export BACKUP_PATH_CREATED="$BACKUP_PATH_CREATED"
export MAC_ADDRESS_TO_PROVISION=
export VPS_HOSTNAME="$VPS_HOSTNAME"
export FQDN="$VPS_HOSTNAME.$DOMAIN_NAME"
@ -309,24 +312,13 @@ function instantiate_vms {
export DDNS_HOST="$DDNS_HOST"
export FQDN="$DDNS_HOST.$DOMAIN_NAME"
export LXD_VM_NAME="${FQDN//./-}"
BACKUP_TIMESTAMP="$(date +"%Y-%m")"
UNIX_BACKUP_TIMESTAMP="$(date +%s)"
export VIRTUAL_MACHINE="$VIRTUAL_MACHINE"
export REMOTE_BACKUP_PATH="$REMOTE_HOME/backups/$VIRTUAL_MACHINE"
export BACKUP_TIMESTAMP="$BACKUP_TIMESTAMP"
export UNIX_BACKUP_TIMESTAMP="$UNIX_BACKUP_TIMESTAMP"
export REMOTE_CERT_DIR="$REMOTE_CERT_BASE_DIR/$FQDN"
export REMOTE_BACKUP_PATH="$REMOTE_BACKUP_PATH"
export MAC_ADDRESS_TO_PROVISION="$MAC_ADDRESS_TO_PROVISION"
LOCAL_BACKUP_PATH="$SITE_PATH/backups/$VIRTUAL_MACHINE/$BACKUP_TIMESTAMP"
export LOCAL_BACKUP_PATH="$LOCAL_BACKUP_PATH"
if [ ! -d "$LOCAL_BACKUP_PATH" ]; then
mkdir -p "$LOCAL_BACKUP_PATH"
BACKUP_PATH_CREATED=true
fi
# This next section of if statements is our sanity checking area.
@ -432,6 +424,7 @@ function stub_site_definition {
#!/bin/bash
export DOMAIN_NAME="${DOMAIN_NAME}"
export SITE_LANGUAGE_CODES="en"
export DUPLICITY_BACKUP_PASSPHRASE="$(new_pass)"
# AWS only
#export DDNS_PASSWORD=
@ -478,7 +471,6 @@ export WWW_SERVER_MAC_ADDRESS="CHANGE_ME_REQUIRED"
export DEPLOY_BTCPAY_SERVER=true
export BTCPAYSERVER_MAC_ADDRESS="CHANGE_ME_REQUIRED"
# export BTC_CHAIN=mainnet
# export ENABLE_NGINX_CACHING=true
export PRIMARY_DOMAIN="CHANGE_ME"
export OTHER_SITES_LIST=
EOL

View File

@ -3,18 +3,45 @@
set -eux
cd "$(dirname "$0")"
#$1 should be the app path (ghost,nextcloud,gitea)
#$2 should be the domain to backup
if [ -z "$1" ]; then
echo "ERROR: the app path was not specified."
exit 1
fi
# TODO: We are using extra space on the remote VPS at the moment for the duplicity backup files.
# we could eliminate that and simply save duplicity backups to the management machine running the script
# this could be done by using a local path and mounting it on the remote VPS.
# maybe something like https://superuser.com/questions/616182/how-to-mount-local-directory-to-remote-like-sshfs
REMOTE_BACKUP_PATH="$REMOTE_HOME/backups/www/$DOCKER_STACK_SUFFIX-$LANGUAGE_CODE"
REMOTE_BACKUP_LOCATION="$REMOTE_BACKUP_PATH/$1/$DOMAIN_NAME"
# step 1: run duplicity on the remote system to backup all files to the remote system.
ssh "$PRIMARY_WWW_FQDN" sudo PASSPHRASE="$DUPLICITY_BACKUP_PASSPHRASE" duplicity --allow-source-mismatch --exclude "$REMOTE_HOME/backups" "$REMOTE_HOME" "file://$REMOTE_BACKUP_PATH"
ssh "$PRIMARY_WWW_FQDN" sudo chown -R ubuntu:ubuntu "$REMOTE_BACKUP_PATH"
# --allow-source-mismatch
ssh "$PRIMARY_WWW_FQDN" sudo PASSPHRASE="$DUPLICITY_BACKUP_PASSPHRASE" duplicity "$REMOTE_HOME/$1/$DOMAIN_NAME" "file://$REMOTE_BACKUP_LOCATION"
ssh "$PRIMARY_WWW_FQDN" sudo chown -R ubuntu:ubuntu "$REMOTE_BACKUP_LOCATION"
SSHFS_PATH="/tmp/sshfs_temp"
mkdir -p "$SSHFS_PATH"
# now let's pull down the latest files from the backup directory.
# create a temp directory to serve as the mountpoint for the remote machine backups directory
sshfs "$PRIMARY_WWW_FQDN:$REMOTE_BACKUP_PATH" "$SSHFS_PATH"
sshfs "$PRIMARY_WWW_FQDN:$REMOTE_BACKUP_LOCATION" "$SSHFS_PATH"
# ensure our local backup path exists so we can pull down the duplicity archive to the management machine.
LOCAL_BACKUP_PATH="$SITE_PATH/backups/www/$BACKUP_TIMESTAMP"
if [ "$1" = letsencrypt ]; then
LOCAL_BACKUP_PATH="$SITE_PATH/backups/www/letsencrypt"
fi
if [ ! -d "$LOCAL_BACKUP_PATH" ]; then
mkdir -p "$LOCAL_BACKUP_PATH"
fi
# rsync the files from the remote server to our local backup path.
rsync -av "$SSHFS_PATH/" "$LOCAL_BACKUP_PATH/"
@ -22,3 +49,4 @@ rsync -av "$SSHFS_PATH/" "$LOCAL_BACKUP_PATH/"
# step 4: unmount the SSHFS filesystem and cleanup.
umount "$SSHFS_PATH"
rm -rf "$SSHFS_PATH"

View File

@ -54,5 +54,6 @@ elif [ "$VPS_HOSTING_TARGET" = lxd ]; then
-v "$REMOTE_HOME/letsencrypt/$DOMAIN_NAME/_logs":/var/log/letsencrypt \
certbot/certbot certonly -v --noninteractive --agree-tos --key-type ecdsa --standalone --expand -d "$DOMAIN_NAME" -d "$WWW_FQDN" -d "$BTCPAY_USER_FQDN" -d "$NEXTCLOUD_FQDN" -d "$GITEA_FQDN" -d "$NOSTR_FQDN" --email "$CERTIFICATE_EMAIL_ADDRESS"
sleep 3
done
fi

View File

@ -4,7 +4,7 @@ set -exu
cd "$(dirname "$0")"
# Create the nginx config file which covers all domains.
bash -c ./stub_nginxconf.sh
bash -c ./stub/nginx_config.sh
# redirect all docker commands to the remote host.
export DOCKER_HOST="ssh://ubuntu@$PRIMARY_WWW_FQDN"
@ -97,26 +97,12 @@ for DOMAIN_NAME in ${DOMAIN_LIST//,/ }; do
done
### The next series of commands
# stop services.
if docker stack list --format "{{.Name}}" | grep -q webstack; then
docker stack rm webstack
sleep 15
fi
if [ "$BACKUP_WWW" = true ]; then
./backup.sh
fi
./stop_docker_stacks.sh
if [ "$RESTORE_WWW" = true ]; then
# Generally speaking we try to restore data. But if the BACKUP directory was
# just created, we know that we'll deploy fresh.
./restore.sh
else
if [ "$RUN_CERT_RENEWAL" = true ]; then
./generate_certs.sh
fi
fi
@ -145,7 +131,8 @@ if [ "$DEPLOY_ONION_SITE" = true ]; then
# fi
fi
bash -c ./stub_docker_yml.sh
bash -c ./stub/nginx_yml.sh
bash -c ./stub/ghost_yml.sh
# # start a browser session; point it to port 80 to ensure HTTPS redirect.
# wait-for-it -t 320 "$PRIMARY_WWW_FQDN:80"

View File

@ -0,0 +1,61 @@
#!/bin/bash
set -exu
cd "$(dirname "$0")"
# bring down ghost instances.
for DOMAIN_NAME in ${DOMAIN_LIST//,/ }; do
export DOMAIN_NAME="$DOMAIN_NAME"
export SITE_PATH="$SITES_PATH/$DOMAIN_NAME"
# source the site path so we know what features it has.
source ../../reset_env.sh
source "$SITE_PATH/site_definition"
source ../../domain_env.sh
### Stop all services.
for APP in ghost; do
for LANGUAGE_CODE in ${SITE_LANGUAGE_CODES//,/ }; do
STACK_NAME="$DOCKER_STACK_SUFFIX-$LANGUAGE_CODE"
if docker stack list --format "{{.Name}}" | grep -q "$STACK_NAME"; then
docker stack rm "$STACK_NAME"
sleep 2
fi
if [ "$BACKUP_GHOST" = true ]; then
./backup_path.sh "$APP"
fi
done
done
done
if docker stack list --format "{{.Name}}" | grep -q reverse-proxy; then
docker stack rm reverse-proxy
# wait for all docker containers to stop.
# TODO see if there's a way to check for this.
sleep 10
fi
# generate the certs and grab a backup
if [ "$RUN_CERT_RENEWAL" = true ]; then
./generate_certs.sh
fi
if [ "$BACKUP_CERTS" = true ]; then
# Back each domain's certificates under /home/ubuntu/letsencrypt/domain
for DOMAIN_NAME in ${DOMAIN_LIST//,/ }; do
export DOMAIN_NAME="$DOMAIN_NAME"
export SITE_PATH="$SITES_PATH/$DOMAIN_NAME"
# source the site path so we know what features it has.
source ../../reset_env.sh
source "$SITE_PATH/site_definition"
source ../../domain_env.sh
./backup_path.sh "letsencrypt"
done
fi

102
deployment/www/stub/ghost_yml.sh Executable file
View File

@ -0,0 +1,102 @@
#!/bin/bash
domain_number=0
for DOMAIN_NAME in ${DOMAIN_LIST//,/ }; do
export DOMAIN_NAME="$DOMAIN_NAME"
export SITE_PATH="$SITES_PATH/$DOMAIN_NAME"
# source the site path so we know what features it has.
source ../../reset_env.sh
source "$SITE_PATH/site_definition"
source ../../domain_env.sh
# for each language specified in the site_definition, we spawn a separate ghost container
# at https://www.domain.com/$LANGUAGE_CODE
for LANGUAGE_CODE in ${SITE_LANGUAGE_CODES//,/ }; do
STACK_NAME="$DOCKER_STACK_SUFFIX-$LANGUAGE_CODE"
# ensure directories on remote host exist so we can mount them into the containers.
ssh "$PRIMARY_WWW_FQDN" mkdir -p "$REMOTE_HOME/ghost/$DOMAIN_NAME/$LANGUAGE_CODE/ghost" "$REMOTE_HOME/ghost/$DOMAIN_NAME/$LANGUAGE_CODE/db"
export GHOST_STACK_TAG="ghost-$STACK_NAME"
export GHOST_DB_STACK_TAG="ghostdb-$STACK_NAME"
# todo append domain number or port number.
WEBSTACK_PATH="$SITE_PATH/webstack"
mkdir -p "$WEBSTACK_PATH"
export DOCKER_YAML_PATH="$WEBSTACK_PATH/ghost-$LANGUAGE_CODE.yml"
# here's the NGINX config. We support ghost and nextcloud.
echo "" > "$DOCKER_YAML_PATH"
cat >>"$DOCKER_YAML_PATH" <<EOL
version: "3.8"
services:
EOL
# This is the ghost for HTTPS (not over Tor)
cat >>"$DOCKER_YAML_PATH" <<EOL
${GHOST_STACK_TAG}:
image: ${GHOST_IMAGE}
networks:
- ghostnet-${DOCKER_STACK_SUFFIX}-${LANGUAGE_CODE}
- ghostdbnet-${DOCKER_STACK_SUFFIX}-${LANGUAGE_CODE}
volumes:
- ${REMOTE_HOME}/ghost/${DOMAIN_NAME}/${LANGUAGE_CODE}/ghost:/var/lib/ghost/content
environment:
EOL
cat >>"$DOCKER_YAML_PATH" <<EOL
- url=https://${WWW_FQDN}/${LANGUAGE_CODE}
- database__client=mysql
- database__connection__host=${GHOST_DB_STACK_TAG}
- database__connection__user=ghost
- database__connection__password=\${GHOST_MYSQL_PASSWORD}
- database__connection__database=ghost
- database__pool__min=0
- privacy__useStructuredData=true
deploy:
restart_policy:
condition: on-failure
${GHOST_DB_STACK_TAG}:
image: ${GHOST_DB_IMAGE}
networks:
- ghostdbnet-${DOCKER_STACK_SUFFIX}-${LANGUAGE_CODE}
volumes:
- ${REMOTE_HOME}/ghost/${DOMAIN_NAME}/${LANGUAGE_CODE}/db:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=\${GHOST_MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=ghost
- MYSQL_USER=ghost
- MYSQL_PASSWORD=\${GHOST_MYSQL_PASSWORD}
deploy:
restart_policy:
condition: on-failure
EOL
cat >>"$DOCKER_YAML_PATH" <<EOL
networks:
EOL
if [ "$DEPLOY_GHOST" = true ]; then
GHOSTNET_NAME="ghostnet-$DOCKER_STACK_SUFFIX-$LANGUAGE_CODE"
GHOSTDBNET_NAME="ghostdbnet-$DOCKER_STACK_SUFFIX-$LANGUAGE_CODE"
cat >>"$DOCKER_YAML_PATH" <<EOL
${GHOSTNET_NAME}:
name: "reverse-proxy_ghostnet-$DOCKER_STACK_SUFFIX-$LANGUAGE_CODE"
external: true
${GHOSTDBNET_NAME}:
EOL
fi
docker stack deploy -c "$DOCKER_YAML_PATH" "$DOCKER_STACK_SUFFIX-$LANGUAGE_CODE"
sleep 1
done
domain_number=$((domain_number+1))
done

View File

@ -0,0 +1,27 @@
if [ "$DEPLOY_GITEA" = true ]; then
cat >>"$NGINX_CONF_PATH" <<EOL
# TLS listener for ${GITEA_FQDN}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name ${GITEA_FQDN};
location / {
proxy_headers_hash_max_size 512;
proxy_headers_hash_bucket_size 64;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header Host \$host;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://gitea:3000;
}
}
EOL
fi

View File

@ -0,0 +1,44 @@
# if [ "$DEPLOY_NEXTCLOUD" = true ]; then
# cat >>"$NGINX_CONF_PATH" <<EOL
# # TLS listener for ${NEXTCLOUD_FQDN}
# server {
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
# ssl_certificate $CONTAINER_TLS_PATH/fullchain.pem;
# ssl_certificate_key $CONTAINER_TLS_PATH/privkey.pem;
# ssl_trusted_certificate $CONTAINER_TLS_PATH/fullchain.pem;
# server_name ${NEXTCLOUD_FQDN};
# location / {
# proxy_headers_hash_max_size 512;
# proxy_headers_hash_bucket_size 64;
# proxy_set_header X-Real-IP \$remote_addr;
# proxy_set_header Host \$host;
# proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto \$scheme;
# proxy_set_header X-NginX-Proxy true;
# proxy_pass http://nextcloud:80;
# }
# # https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/reverse_proxy_configuration.html
# location /.well-known/carddav {
# return 301 \$scheme://\$host/remote.php/dav;
# }
# location /.well-known/caldav {
# return 301 \$scheme://\$host/remote.php/dav;
# }
# }
# EOL
# fi

View File

@ -20,9 +20,9 @@ for DOMAIN_NAME in ${DOMAIN_LIST//,/ }; do
export CONTAINER_TLS_PATH="/etc/letsencrypt/${DOMAIN_NAME}/live/${DOMAIN_NAME}"
# source the site path so we know what features it has.
source ../../reset_env.sh
source ../../../reset_env.sh
source "$SITE_PATH/site_definition"
source ../../domain_env.sh
source ../../../domain_env.sh
echo "Doing DOMAIN_NAME: $DOMAIN_NAME"
if [ $iteration = 0 ]; then
@ -43,7 +43,6 @@ http {
proxy_busy_buffers_size 256k;
client_header_buffer_size 500k;
large_client_header_buffers 4 500k;
http2_max_header_size 500k;
# Needed websocket support (used by Ledger hardware wallets)
map \$http_upgrade \$connection_upgrade {
@ -167,6 +166,15 @@ EOL
#map \$http_user_agent \$og_prefix {
# ~*(googlebot|twitterbot)/ /open-graph;
#}
# this map allows us to route the clients request to the correct Ghost instance
# based on the clients browser language setting.
map \$http_accept_language \$lang {
default "en";
~en en;
~es es;
}
EOL
fi
@ -184,7 +192,7 @@ EOL
# catch all; send request to ${WWW_FQDN}
location / {
return 301 https://${WWW_FQDN}\$request_uri;
return 301 https://${WWW_FQDN}/\$request_uri;
}
EOL
@ -209,17 +217,9 @@ EOL
#access_log /var/log/nginx/ghost-access.log;
#error_log /var/log/nginx/ghost-error.log;
EOL
if [ "$ENABLE_NGINX_CACHING" = true ]; then
cat >>"$NGINX_CONF_PATH" <<EOL
# main TLS listener; proxies requests to ghost service. NGINX configured to cache
proxy_cache_path /tmp/nginx_ghost levels=1:2 keys_zone=ghostcache:600m max_size=100m inactive=24h;
EOL
fi
# SERVER block for BTCPAY Server
if [ "$VPS_HOSTING_TARGET" = lxd ]; then
# gitea http to https redirect.
@ -229,7 +229,6 @@ EOL
# http://${BTCPAY_USER_FQDN} redirect to https://${BTCPAY_USER_FQDN}
server {
listen 443 ssl http2;
ssl on;
ssl_certificate $CONTAINER_TLS_PATH/fullchain.pem;
ssl_certificate_key $CONTAINER_TLS_PATH/privkey.pem;
@ -257,9 +256,19 @@ EOL
fi
# the open server block for the HTTPS listener
echo " # set up cache paths for nginx caching" >>"$NGINX_CONF_PATH"
for LANGUAGE_CODE in ${SITE_LANGUAGE_CODES//,/ }; do
STACK_NAME="$DOCKER_STACK_SUFFIX-$LANGUAGE_CODE"
cat >>"$NGINX_CONF_PATH" <<EOL
proxy_cache_path /tmp/${STACK_NAME} levels=1:2 keys_zone=${STACK_NAME}:600m max_size=100m inactive=24h;
EOL
done
# the open server block for the HTTPS listener for ghost
cat >>"$NGINX_CONF_PATH" <<EOL
# Main HTTPS listener for https://${WWW_FQDN}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
@ -269,41 +278,53 @@ EOL
ssl_trusted_certificate $CONTAINER_TLS_PATH/fullchain.pem;
server_name ${WWW_FQDN};
EOL
# add the Onion-Location header if specifed.
if [ "$DEPLOY_ONION_SITE" = true ]; then
cat >>"$NGINX_CONF_PATH" <<EOL
add_header Onion-Location https://${ONION_ADDRESS}\$request_uri;
EOL
fi
if [ "$ENABLE_NGINX_CACHING" = true ]; then
cat >>"$NGINX_CONF_PATH" <<EOL
# No cache + keep cookies for admin and previews
location ~ ^/(ghost/|p/|private/) {
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header Host \$http_host;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_intercept_errors on;
proxy_pass http://ghost-${iteration}:2368;
}
EOL
fi
# proxy config for ghost
cat >>"$NGINX_CONF_PATH" <<EOL
# Set the crawler policy.
location = /robots.txt {
add_header Content-Type text/plain;
return 200 "User-Agent: *\\nAllow: /\\n";
}
EOL
# # add the Onion-Location header if specifed.
# if [ "$DEPLOY_ONION_SITE" = true ]; then
# cat >>"$NGINX_CONF_PATH" <<EOL
# add_header Onion-Location https://${ONION_ADDRESS}\$request_uri;
# EOL
# fi
cat >>"$NGINX_CONF_PATH" <<EOL
# if the client is accesssing https://${WWW_FQDN}/ , then we check the client
# langauge header and send them to the correct ghost instance based on language
location / {
rewrite (.*) \$1/\$lang;
}
EOL
for LANGUAGE_CODE in ${SITE_LANGUAGE_CODES//,/ }; do
STACK_NAME="$DOCKER_STACK_SUFFIX-$LANGUAGE_CODE"
cat >>"$NGINX_CONF_PATH" <<EOL
location ~ ^/${LANGUAGE_CODE}/(ghost/|p/|private/) {
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header Host \$http_host;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_intercept_errors on;
proxy_pass http://ghost-${STACK_NAME}:2368;
}
EOL
done
for LANGUAGE_CODE in ${SITE_LANGUAGE_CODES//,/ }; do
cat >>"$NGINX_CONF_PATH" <<EOL
# Location block to back https://${WWW_FQDN}/${LANGUAGE_CODE}
location /${LANGUAGE_CODE} {
#set_from_accept_language \$lang en es;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header Host \$http_host;
@ -311,11 +332,8 @@ fi
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_intercept_errors on;
proxy_pass http://ghost-${iteration}:2368;
EOL
proxy_pass http://ghost-${DOCKER_STACK_SUFFIX}-${LANGUAGE_CODE}:2368;
if [ "$ENABLE_NGINX_CACHING" = true ]; then
cat >>"$NGINX_CONF_PATH" <<EOL
# https://stanislas.blog/2019/08/ghost-nginx-cache/ for nginx caching instructions
# Remove cookies which are useless for anonymous visitor and prevent caching
proxy_ignore_headers Set-Cookie Cache-Control;
@ -323,7 +341,7 @@ EOL
# Add header for cache status (miss or hit)
add_header X-Cache-Status \$upstream_cache_status;
proxy_cache ghostcache;
proxy_cache ${DOCKER_STACK_SUFFIX}-${LANGUAGE_CODE};
# Default TTL: 1 day
proxy_cache_valid 5s;
@ -341,16 +359,12 @@ EOL
# Bypass cache for errors
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
EOL
fi
# this is the closing location / block for the ghost HTTPS segment
cat >>"$NGINX_CONF_PATH" <<EOL
}
EOL
done
# TODO this MIGHT be part of the solution for Twitter Cards.
# location /contents {
# resolver 127.0.0.11 ipv6=off valid=5m;
@ -359,102 +373,16 @@ EOL
# proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto \$scheme;
# proxy_intercept_errors on;
# proxy_pass http://ghost-${iteration}::2368\$og_prefix\$request_uri;
# proxy_pass http://ghost-${DOCKER_STACK_SUFFIX}-${SITE_LANGUAGE_CODES}::2368\$og_prefix\$request_uri;
# }
# this is the closing server block for the ghost HTTPS segment
# this is the closing server block for the ghost HTTPS segment
cat >>"$NGINX_CONF_PATH" <<EOL
}
EOL
# tor config
if [ "$DEPLOY_ONION_SITE" = true ]; then
cat >>"$NGINX_CONF_PATH" <<EOL
# server listener for tor v3 onion endpoint
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name ${ONION_ADDRESS};
#access_log /var/log/nginx/tor-www.log;
# administration not allowed over tor interface.
location /ghost { deny all; }
location / {
proxy_set_header X-Forwarded-For 1.1.1.1;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP 1.1.1.1;
proxy_set_header Host \$http_host;
proxy_pass http://tor-ghost:2368;
}
}
EOL
fi
if [ "$DEPLOY_NEXTCLOUD" = true ]; then
cat >>"$NGINX_CONF_PATH" <<EOL
# TLS listener for ${NEXTCLOUD_FQDN}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate $CONTAINER_TLS_PATH/fullchain.pem;
ssl_certificate_key $CONTAINER_TLS_PATH/privkey.pem;
ssl_trusted_certificate $CONTAINER_TLS_PATH/fullchain.pem;
server_name ${NEXTCLOUD_FQDN};
location / {
proxy_headers_hash_max_size 512;
proxy_headers_hash_bucket_size 64;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header Host \$host;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://nextcloud:80;
}
# https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/reverse_proxy_configuration.html
location /.well-known/carddav {
return 301 \$scheme://\$host/remote.php/dav;
}
location /.well-known/caldav {
return 301 \$scheme://\$host/remote.php/dav;
}
}
EOL
fi
if [ "$DEPLOY_GITEA" = true ]; then
cat >>"$NGINX_CONF_PATH" <<EOL
# TLS listener for ${GITEA_FQDN}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name ${GITEA_FQDN};
location / {
proxy_headers_hash_max_size 512;
proxy_headers_hash_bucket_size 64;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header Host \$host;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://gitea:3000;
}
}
EOL
fi
iteration=$((iteration+1))
done

View File

@ -0,0 +1,88 @@
#!/bin/bash
set -eux
cd "$(dirname "$0")"
#https://github.com/fiatjaf/expensive-relay
# NOSTR RELAY WHICH REQUIRES PAYMENTS.
DOCKER_YAML_PATH="$PROJECT_PATH/nginx.yml"
cat > "$DOCKER_YAML_PATH" <<EOL
version: "3.8"
services:
nginx:
image: ${NGINX_IMAGE}
ports:
- 0.0.0.0:443:443
- 0.0.0.0:80:80
networks:
EOL
for DOMAIN_NAME in ${DOMAIN_LIST//,/ }; do
export DOMAIN_NAME="$DOMAIN_NAME"
export SITE_PATH="$SITES_PATH/$DOMAIN_NAME"
# source the site path so we know what features it has.
source ../../../reset_env.sh
source "$SITE_PATH/site_definition"
source ../../../domain_env.sh
# for each language specified in the site_definition, we spawn a separate ghost container
# at https://www.domain.com/$LANGUAGE_CODE
for LANGUAGE_CODE in ${SITE_LANGUAGE_CODES//,/ }; do
cat >> "$DOCKER_YAML_PATH" <<EOL
- ghostnet-$DOCKER_STACK_SUFFIX-$LANGUAGE_CODE
EOL
done
done
cat >> "$DOCKER_YAML_PATH" <<EOL
volumes:
- ${REMOTE_HOME}/letsencrypt:/etc/letsencrypt:ro
configs:
- source: nginx-config
target: /etc/nginx/nginx.conf
deploy:
restart_policy:
condition: on-failure
configs:
nginx-config:
file: ${PROJECT_PATH}/nginx.conf
EOL
################ NETWORKS SECTION
cat >> "$DOCKER_YAML_PATH" <<EOL
networks:
EOL
for DOMAIN_NAME in ${DOMAIN_LIST//,/ }; do
export DOMAIN_NAME="$DOMAIN_NAME"
export SITE_PATH="$SITES_PATH/$DOMAIN_NAME"
# source the site path so we know what features it has.
source ../../../reset_env.sh
source "$SITE_PATH/site_definition"
source ../../../domain_env.sh
# for each language specified in the site_definition, we spawn a separate ghost container
# at https://www.domain.com/$LANGUAGE_CODE
for LANGUAGE_CODE in ${SITE_LANGUAGE_CODES//,/ }; do
cat >> "$DOCKER_YAML_PATH" <<EOL
ghostnet-$DOCKER_STACK_SUFFIX-$LANGUAGE_CODE:
attachable: true
EOL
done
done
docker stack deploy -c "$DOCKER_YAML_PATH" "reverse-proxy"
# iterate over all our domains and create the nginx config file.

View File

@ -0,0 +1,23 @@
# # tor config
# if [ "$DEPLOY_ONION_SITE" = true ]; then
# cat >>"$NGINX_CONF_PATH" <<EOL
# # server listener for tor v3 onion endpoint
# server {
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
# server_name ${ONION_ADDRESS};
# #access_log /var/log/nginx/tor-www.log;
# # administration not allowed over tor interface.
# location /ghost { deny all; }
# location / {
# proxy_set_header X-Forwarded-For 1.1.1.1;
# proxy_set_header X-Forwarded-Proto https;
# proxy_set_header X-Real-IP 1.1.1.1;
# proxy_set_header Host \$http_host;
# proxy_pass http://tor-ghost:2368;
# }
# }
# EOL
# fi

View File

@ -1,144 +1,9 @@
#!/bin/bash
set -eux
cd "$(dirname "$0")"
ssh "$PRIMARY_WWW_FQDN" sudo rm -rf /home/ubuntu/ghost
sleep 4
#https://github.com/fiatjaf/expensive-relay
# NOSTR RELAY WHICH REQUIRES PAYMENTS.
DOCKER_YAML_PATH="$PROJECT_PATH/nginx.yml"
cat > "$DOCKER_YAML_PATH" <<EOL
version: "3.8"
services:
nginx:
image: ${NGINX_IMAGE}
ports:
- 0.0.0.0:443:443
- 0.0.0.0:80:80
networks:
EOL
for i in $(seq 0 $DOMAIN_COUNT); do
cat >> "$DOCKER_YAML_PATH" <<EOL
- ghostnet-$i
EOL
done
cat >> "$DOCKER_YAML_PATH" <<EOL
volumes:
- ${REMOTE_HOME}/letsencrypt:/etc/letsencrypt:ro
configs:
- source: nginx-config
target: /etc/nginx/nginx.conf
deploy:
restart_policy:
condition: on-failure
configs:
nginx-config:
file: ${PROJECT_PATH}/nginx.conf
EOL
cat >> "$DOCKER_YAML_PATH" <<EOL
networks:
EOL
for i in $(seq 0 $DOMAIN_COUNT); do
cat >> "$DOCKER_YAML_PATH" <<EOL
ghostnet-$i:
attachable: true
EOL
done
docker stack deploy -c "$DOCKER_YAML_PATH" "reverse-proxy"
# iterate over all our domains and create the nginx config file.
domain_number=0
for DOMAIN_NAME in ${DOMAIN_LIST//,/ }; do
export DOMAIN_NAME="$DOMAIN_NAME"
export SITE_PATH="$SITES_PATH/$DOMAIN_NAME"
ssh "$PRIMARY_WWW_FQDN" mkdir -p "$REMOTE_HOME/ghost/$DOMAIN_NAME/ghost" "$REMOTE_HOME/ghost/$DOMAIN_NAME/db"
# source the site path so we know what features it has.
source ../../reset_env.sh
source "$SITE_PATH/site_definition"
source ../../domain_env.sh
STACK_TAG="ghost-$domain_number"
# todo append domain number or port number.
mkdir -p "$SITE_PATH/webstack"
DOCKER_YAML_PATH="$SITE_PATH/webstack/$STACK_TAG.yml"
export DOCKER_YAML_PATH="$DOCKER_YAML_PATH"
# if [ "$DEPLOY_ONION_SITE" = true ]; then
# if [ -z "$ONION_ADDRESS" ]; then
# echo "ERROR: ONION_ADDRESS is not defined."
# exit 1
# fi
# fi
# here's the NGINX config. We support ghost and nextcloud.
echo "" > "$DOCKER_YAML_PATH"
cat >>"$DOCKER_YAML_PATH" <<EOL
version: "3.8"
services:
EOL
# This is the ghost for HTTPS (not over Tor)
cat >>"$DOCKER_YAML_PATH" <<EOL
ghost-${domain_number}:
image: ${GHOST_IMAGE}
networks:
- ghostnet-${domain_number}
- ghostdbnet-${domain_number}
volumes:
- ${REMOTE_HOME}/ghost/${DOMAIN_NAME}/ghost:/var/lib/ghost/content
environment:
- url=https://${PRIMARY_WWW_FQDN}
- database__client=mysql
- database__connection__host=ghostdb-${domain_number}
- database__connection__user=ghost
- database__connection__password=\${GHOST_MYSQL_PASSWORD}
- database__connection__database=ghost
- database__pool__min=0
- privacy__useStructuredData=true
deploy:
restart_policy:
condition: on-failure
ghostdb-${domain_number}:
image: ${GHOST_DB_IMAGE}
networks:
- ghostdbnet-${domain_number}
volumes:
- ${REMOTE_HOME}/ghost/${DOMAIN_NAME}/db:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=\${GHOST_MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=ghost
- MYSQL_USER=ghost
- MYSQL_PASSWORD=\${GHOST_MYSQL_PASSWORD}
deploy:
restart_policy:
condition: on-failure
EOL
# if [ "$DEPLOY_NEXTCLOUD" = true ]; then
@ -302,19 +167,7 @@ EOL
# fi
# #-------------------------
# networks ----------------------
cat >>"$DOCKER_YAML_PATH" <<EOL
networks:
EOL
if [ "$DEPLOY_GHOST" = true ]; then
cat >>"$DOCKER_YAML_PATH" <<EOL
ghostnet-${domain_number}:
name: "reverse-proxy_ghostnet-${domain_number}"
external: true
ghostdbnet-${domain_number}:
EOL
fi
# if [ "$DEPLOY_NEXTCLOUD" = true ]; then
# cat >>"$DOCKER_YAML_PATH" <<EOL
@ -346,9 +199,3 @@ EOL
# EOL
# fi
# # -----------------------------
docker stack deploy -c "$DOCKER_YAML_PATH" "$STACK_TAG"
domain_number=$((domain_number+1))
done

View File

@ -16,3 +16,11 @@ export REMOTE_GITEA_PATH="$REMOTE_HOME/gitea"
export BTC_CHAIN="$BTC_CHAIN"
export WWW_INSTANCE_TYPE="$WWW_INSTANCE_TYPE"
export BTCPAY_ADDITIONAL_HOSTNAMES="$BTCPAY_ADDITIONAL_HOSTNAMES"
BACKUP_TIMESTAMP="$(date +"%Y-%m")"
UNIX_BACKUP_TIMESTAMP="$(date +%s)"
export BACKUP_TIMESTAMP="$BACKUP_TIMESTAMP"
export UNIX_BACKUP_TIMESTAMP="$UNIX_BACKUP_TIMESTAMP"
export DOCKER_STACK_SUFFIX="${DOMAIN_NAME//./-}"

View File

@ -17,6 +17,8 @@ export NEXTCLOUD_MYSQL_PASSWORD=
export NEXTCLOUD_MYSQL_ROOT_PASSWORD=
export GITEA_MYSQL_PASSWORD=
export GITEA_MYSQL_ROOT_PASSWORD=
export SITE_LANGUAGE_CODES="en"
export LANGUAGE_CODE=
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source "$SCRIPT_DIR/defaults.sh"