Files
CloudDeploy/deploy.sh

309 lines
9.9 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
# Ensure script is run as root (required for apt + /etc)
if [[ "$EUID" -ne 0 ]]; then
echo "Please run as root (or use sudo)." >&2
exit 1
fi
#set script directory
scriptdir="$(dirname "$(realpath "$0")")"
# recursive replace function
replace_string_recursive() {
local DIRECTORY="$1"
local OLD_STRING="$2"
local NEW_STRING="$3"
if [ ! -d "$DIRECTORY" ]; then
echo "Error: Directory '$DIRECTORY' does not exist."
return 1
fi
echo "Starting replacement of '$OLD_STRING' with '$NEW_STRING' in '$DIRECTORY'..."
find "$DIRECTORY" -type f -exec sed -i "s|$OLD_STRING|$NEW_STRING|g" {} +
if [ $? -eq 0 ]; then
echo "Replacement completed successfully."
return 0
else
echo "An error occurred during replacement."
return 1
fi
}
# example use
# replace_string_recursive "/path/to/directory" "oldstring" "newstring"
# sqlite db replace function
replace_in_sqlite_db() {
local DB_PATH="$1"
local OLD_STRING="$2"
local NEW_STRING="$3"
# Check if the database file exists
if [ ! -f "$DB_PATH" ]; then
echo "Error: Database file '$DB_PATH' does not exist."
exit 1
fi
echo "Starting replacement of '$OLD_STRING' with '$NEW_STRING' in '$DB_PATH'..."
# Create a backup of the original database
local BACKUP_PATH="${DB_PATH}.bak"
cp "$DB_PATH" "$BACKUP_PATH"
# Escape single quotes for SQL
local OLD_STRING_ESC=$(printf '%s\n' "$OLD_STRING" | sed "s/'/''/g")
local NEW_STRING_ESC=$(printf '%s\n' "$NEW_STRING" | sed "s/'/''/g")
# Get a list of all tables in the database
local TABLES
TABLES=$(sqlite3 "$DB_PATH" ".tables")
# Loop through each table
for TABLE in $TABLES; do
echo "Processing table: $TABLE"
# Escape table name if it's a reserved keyword
local ESCAPED_TABLE
if [[ "$TABLE" =~ ^(index|group|order|table|view|database|schema|trigger|transaction|commit|rollback|savepoint|release|alter|create|drop|insert|update|delete|select|from|where|join|union|intersect|except|limit|offset|order|by|group|having|as|with|replace|cast|case|when|then|else|end|and|or|not|is|null|between|in|like|glob|match|regexp|collate|exists|unique|primary|key|foreign|references|check|constraint|default|collate|asc|desc|on|using|natural|left|right|full|outer|cross|inner)$ ]]; then
ESCAPED_TABLE="\"$TABLE\""
else
ESCAPED_TABLE="$TABLE"
fi
# Get a list of all non-BLOB columns in the table
sqlite3 "$DB_PATH" "PRAGMA table_info($ESCAPED_TABLE);" 2>/dev/null | awk -F'|' '
{
if ($3 != "BLOB") {
print $2
}
}' | while read -r COLUMN; do
if [ -n "$COLUMN" ]; then
echo " Processing column: $COLUMN"
# Escape column name if it's a reserved keyword
local ESCAPED_COLUMN
if [[ "$COLUMN" =~ ^(index|group|order|table|view|database|schema|trigger|transaction|commit|rollback|savepoint|release|alter|create|drop|insert|update|delete|select|from|where|join|union|intersect|except|limit|offset|order|by|group|having|as|with|replace|cast|case|when|then|else|end|and|or|not|is|null|between|in|like|glob|match|regexp|collate|exists|unique|primary|key|foreign|references|check|constraint|default|collate|asc|desc|on|using|natural|left|right|full|outer|cross|inner)$ ]]; then
ESCAPED_COLUMN="\"$COLUMN\""
else
ESCAPED_COLUMN="$COLUMN"
fi
# Update only rows where the column contains OLD_STRING
# Run each update in its own connection to avoid locking issues
sqlite3 "$DB_PATH" "
UPDATE $ESCAPED_TABLE
SET $ESCAPED_COLUMN = replace(CAST($ESCAPED_COLUMN AS TEXT), '$OLD_STRING_ESC', '$NEW_STRING_ESC')
WHERE CAST($ESCAPED_COLUMN AS TEXT) LIKE '%$OLD_STRING_ESC%';
"
fi
done
done
echo "Replacement completed in '$DB_PATH'. Original database backed up to '$BACKUP_PATH'."
}
#example usage: replace_in_sqlite_db "database.sqlite" "Europe/Amsterdam" "UTC"
# what this script needs to do:
# request all install parameters needed from user
# ---- User input ----
read -rp "Admin email: " adminemail < /dev/tty
read -rsp "Admin password: " adminpass < /dev/tty
echo
read -rp "Timezone (e.g. Europe/Amsterdam): " timezone < /dev/tty
read -rp "Domain (e.g. example.com): " domain < /dev/tty
# Public IP (tries multiple services)
publicip="$(curl -fsS https://api.ipify.org || curl -fsS https://ifconfig.me || echo "UNKNOWN")"
# Local IP (first non-loopback)
localip="$(hostname -I | awk '{print $1}')"
# generate random passwords for DB hosts and other secrets
# ---- Random generators ----
rand_hex() { openssl rand -hex 24; }
rand_b64() { openssl rand -base64 32; }
ownclouddbpass="$(rand_hex)"
ownclouddbrootpass="$(rand_hex)"
convertxJWT="$(rand_hex)"
bookstackkey="$(rand_b64)" # base64 as requested
bookstackdbpass="$(rand_hex)"
bookstackdbrootpass="$(rand_hex)"
onlyofficeJWT="$(rand_hex)"
# install docker
echo "Updating apt and installing prerequisites..."
apt update
apt install -y ca-certificates curl
echo "Setting up Docker GPG key..."
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
echo "Adding Docker apt repository..."
. /etc/os-release
cat > /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: ${UBUNTU_CODENAME:-$VERSION_CODENAME}
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF
echo "Updating apt and installing Docker..."
apt update
apt install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
echo "Docker installation complete."
docker --version
# install dockge
mkdir -p /opt/dockge
cd /opt/dockge
# Download your compose.yaml
curl "https://dockge.kuma.pet/compose.yaml?port=5001&stacksPath=%2Fopt%2Fstacks" --output compose.yaml
# write configuration to compose files
cp -r $scriptdir/stacks /opt
cp -r $scriptdir/scripts /opt
chmod -R 775 /opt/stacks
cd /opt/stacks
git clone https://github.com/trantienloi2404/youtube-downloader.git downloader
#adminemail
replace_string_recursive "/opt/stacks" "?adminemail?" $adminemail
#adminpass
replace_string_recursive "/opt/stacks" "?adminpass?" $adminpass
#timezone
replace_string_recursive "/opt/stacks" "?timezone?" $timezone
#domain
replace_string_recursive "/opt/stacks" "?domain?" $domain
#publicip
replace_string_recursive "/opt/stacks" "?publicip?" $publicip
#localip
replace_string_recursive "/opt/stacks" "?localip?" $localip
#ownclouddbpass
replace_string_recursive "/opt/stacks" "?ownclouddbpass?" $ownclouddbpass
#ownclouddbrootpass
replace_string_recursive "/opt/stacks" "?ownclouddbrootpass?" $ownclouddbrootpass
#convertxJWT
replace_string_recursive "/opt/stacks" "?convertxJWT?" $convertxJWT
#bookstackkey
replace_string_recursive "/opt/stacks" "?bookstackkey?" $bookstackkey
#bookstackdbpass
replace_string_recursive "/opt/stacks" "?bookstackdbpass?" $bookstackdbpass
#bookstackdbrootpass
replace_string_recursive "/opt/stacks" "?bookstackdbrootpass?" $bookstackdbrootpass
#onlyofficeJWT
replace_string_recursive "/opt/stacks" "?onlyofficeJWT?" $onlyofficeJWT
# install mailcow to /opt/stacks/mailcow so it shows up in dockge
apt install -y git openssl curl gawk coreutils grep jq sqlite3
umask 0022
#cd /opt/stacks
#git clone https://github.com/mailcow/mailcow-dockerized mailcow
#cd /opt/stacks/mailcow
#bash ./generate_config.sh < /dev/tty
#disable stub listener
echo "DNSStubListener=no" | tee -a /etc/systemd/resolved.conf
# up dockge
cd /opt/dockge
docker compose up -d
echo "Dockge has been installed and launched. go to http://$localip:5001 and configure your username and password, then press any key to continue"
read -n 1 -s -r -p ""
# call replacements for nginx db
replace_in_sqlite_db "/opt/stacks/npm/data/database.sqlite" "<domain>" $domain
replace_in_sqlite_db "/opt/stacks/npm/data/database.sqlite" "<localip>" $localip
replace_in_sqlite_db "/opt/stacks/npm/data/database.sqlite" "<adminpass>" $adminpass
replace_in_sqlite_db "/opt/stacks/npm/data/database.sqlite" "<adminemail>" $adminemail
cd /opt/stacks/npm
docker compose up -d
echo "Dockge has been installed and launched. go to http://$localip:81 and configure your username and password, then press any key to continue"
read -n 1 -s -r -p ""
cd /opt/stacks/dozzle
docker compose up -d
echo "dozzle has been launched from http://dozzle.$domain, verify it is online"
cd /opt/stacks/convertx
docker compose up -d
echo "convertx has been launched from http://convert.$domain, verify it is online"
cd /opt/stacks/downloader
docker compose up -d
echo "downloader has been launched from http://download.$domain, verify it is online"
cd /opt/stacks/wireguard
docker compose up -d
echo "wireguard has been launched from http://vpn.$domain, verify it is online"
cd /opt/stacks/it-tools
docker compose up -d
echo "it-tools has been launched from http://tools.$domain, verify it is online"
cd /opt/stacks/onlyoffice
docker compose up -d
echo "onlyoffice has been launched from http://tools.$domain, verify it is online"
cd /opt/stacks/site
docker compose up -d
echo "site has been launched from http://www.$domain, verify it is online"
cd /opt/stacks/vaultwarden
docker compose up -d
echo "vaultwarden has been launched from http://vault.$domain, verify it is online"
#bookstack
#browser
#dashboard
#jellyfin
#uptimekuma
#owncloud
#pihole
echo ""
echo ""
echo ""
echo "you can now access the dockge GUI interface at $localip:5001 and the proxy interface at $localip:81 once you start it from Dockge. be sure to forward ports 80, 443 and 51820 to $localip in your router settings"
echo "please reboot before further setup"