segfault/provision/init-ubuntu.sh

298 lines
10 KiB
Bash
Raw Normal View History

2022-05-10 15:39:52 +00:00
#! /bin/bash
# Installs & Bootstraps 'Segfault Hosting Solution' onto a vanilla Linux Server.
#
# See https://www.thc.org/segfault/deploy to install with a single command.
#
# Environment variables:
2022-05-19 11:17:21 +00:00
# SF_HOST_USER - The user on the server under which 'segfault' is installed. (e.g. /home/ubuntu)
# SF_NO_INTERNET - DEBUG: Runs script without Internet
2022-05-10 15:39:52 +00:00
SFI_SRCDIR="$(cd "$(dirname "${0}")/.." || exit; pwd)"
2022-07-28 13:33:08 +00:00
# shellcheck disable=SC1091
2022-05-19 11:17:21 +00:00
source "${SFI_SRCDIR}/provision/system/funcs" || exit 255
2022-05-10 15:39:52 +00:00
NEED_ROOT
DEBUGF "SFI_SRCDIR=${SFI_SRCDIR}"
SUDO_SF()
{
2022-05-19 11:17:21 +00:00
DEBUGF "${SF_HOST_USER} $*"
2022-05-10 15:39:52 +00:00
sudo -u "${SF_HOST_USER}" bash -c "$*"
}
2022-07-25 12:42:33 +00:00
install_docker()
2022-05-19 11:17:21 +00:00
{
2022-07-25 12:42:33 +00:00
command -v docker >/dev/null && return
# Add docker repository to APT
if [[ ! -s /usr/share/keyrings/docker-archive-keyring.gpg ]]; then
[[ -z $SF_NO_INTERNET ]] && apt update -y && apt -y install --no-install-recommends ca-certificates \
curl \
gnupg \
lsb-release \
apt-transport-https
[[ -s /usr/share/keyrings/docker-archive-keyring.gpg ]] || {
rm -rf /usr/share/keyrings/docker-archive-keyring.gpg 2>/dev/null # Delete in case it is zero bytes
[[ -z $SF_NO_INTERNET ]] && curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
}
[[ -z $SF_NO_INTERNET ]] && apt-get update -y
2022-05-19 11:17:21 +00:00
fi
2022-07-25 12:42:33 +00:00
### Install Docker and supporting tools
if [[ -z $SF_NO_INTERNET ]]; then
apt-get install -y --no-install-recommends \
docker-ce docker-ce-cli containerd.io docker-compose \
2022-09-09 14:19:46 +00:00
net-tools make || ERREXIT 138 "Docker not running"
2022-07-25 12:42:33 +00:00
fi
2022-09-09 14:19:46 +00:00
docker ps >/dev/null || ERREXIT
2022-05-10 15:39:52 +00:00
}
2022-07-25 12:42:33 +00:00
init_user()
{
# INIT: Find valid user to use for installation
[[ -z $SF_HOST_USER ]] && {
# EC2 default is 'ubuntu'. Fall-back to 'sf-user' otherwise.
id -u ubuntu &>/dev/null && SF_HOST_USER="ubuntu" || SF_HOST_USER="sf-user"
export SF_HOST_USER
}
2022-05-10 15:39:52 +00:00
2022-07-25 12:42:33 +00:00
# Create user if it does not exist
useradd "${SF_HOST_USER}" -s /bin/bash 2>/dev/null
[[ -d "/home/${SF_HOST_USER}" ]] || {
cp -a /etc/skel "/home/${SF_HOST_USER}"
chown -R "${SF_HOST_USER}:${SF_HOST_USER}" "/home/${SF_HOST_USER}"
}
2022-05-10 15:39:52 +00:00
2022-07-25 12:42:33 +00:00
SF_HOST_USER_ID="$(id -u "$SF_HOST_USER")"
DEBUGF "SF_HOST_USER_ID=${SF_HOST_USER_ID} (SF_HOST_USER=${SF_HOST_USER})"
2022-05-10 15:39:52 +00:00
}
2022-07-25 12:42:33 +00:00
init_host_sshd()
{
2022-07-28 13:33:08 +00:00
local port
2022-07-25 12:42:33 +00:00
# Configure SSHD
[[ -f /etc/ssh/sshd_config ]] || return
2022-05-10 15:39:52 +00:00
2022-07-28 13:33:08 +00:00
port=${SF_SSH_PORT:-22}
2022-07-25 12:42:33 +00:00
[[ -z $SF_SSH_PORT_MASTER ]] && SF_SSH_PORT_MASTER=64222
2022-05-10 15:39:52 +00:00
2022-07-25 12:42:33 +00:00
# Move original SSH server out of the way...
2022-07-28 13:33:08 +00:00
[[ "${port}" -eq 22 ]] && grep "Port 22" /etc/ssh/sshd_config >/dev/null && {
sed -i "s/#Port ${port}/Port ${SF_SSH_PORT_MASTER}/g" /etc/ssh/sshd_config
DEBUGF "Restarting SSHD on port ${SF_SSH_PORT_MASTER}"
2022-07-25 12:42:33 +00:00
service sshd restart
2022-07-28 13:33:08 +00:00
IS_SSH_GOT_MOVED=1
2022-07-25 12:42:33 +00:00
}
2022-05-10 15:39:52 +00:00
}
2022-07-25 12:42:33 +00:00
init_basedir()
{
# INIT: Find good location for dynamic configuration
[[ -z $SF_BASEDIR ]] && {
SUDO_SF "mkdir -p ~/segfault"
SF_BASEDIR="$(cd "/home/${SF_HOST_USER}/segfault" || exit; pwd)"
2022-05-10 15:39:52 +00:00
}
2022-07-25 12:42:33 +00:00
DEBUGF "SF_BASEDIR=${SF_BASEDIR}"
2022-05-10 15:39:52 +00:00
2022-07-25 12:42:33 +00:00
[[ ! -d "${SF_BASEDIR}/config" ]] && SUDO_SF "mkdir \"${SF_BASEDIR}/config\""
[[ ! -d "${SF_BASEDIR}/config/db" ]] && SUDO_SF "mkdir \"${SF_BASEDIR}/config/db\""
2022-05-10 15:39:52 +00:00
}
2022-08-09 19:29:11 +00:00
# Try to merge new config into old directory and yield if
# we did not overwrite old config
mergedir()
2022-07-25 12:42:33 +00:00
{
2022-08-09 19:29:11 +00:00
local src
local dst
[[ "$SFI_SRCDIR" == "$SF_BASEDIR" ]] && return
src="$1"
dst="$(dirname "$src")"
2022-07-25 12:42:33 +00:00
2022-08-09 19:29:11 +00:00
[[ ! -d "${SF_BASEDIR}/${src}" ]] && SUDO_SF "cp -r \"${SFI_SRCDIR}/${src}\" \"${SF_BASEDIR}/${dst}\"" || CONFLICT+=("${src}")
}
init_config_run()
{
mergedir "config/etc/nginx"
mergedir "config/etc/tc"
mergedir "config/etc/info"
2022-07-31 20:32:45 +00:00
2022-07-28 13:33:08 +00:00
# Create Master-SEED
if [[ -z $SF_SEED ]]; then
if [[ -f "${SF_BASEDIR}/config/etc/seed/seed.txt" ]]; then
SF_SEED="$(cat "${SF_BASEDIR}/config/etc/seed/seed.txt")"
else
[[ -d "${SF_BASEDIR}/config/etc/seed" ]] || SUDO_SF mkdir "${SF_BASEDIR}/config/etc/seed"
SF_SEED="$(head -c 1024 /dev/urandom | tr -dc '[:alpha:]' | head -c 32)"
SUDO_SF "echo \"${SF_SEED}\" >\"${SF_BASEDIR}/config/etc/seed/seed.txt\"" || ERREXIT
fi
2022-07-25 12:42:33 +00:00
fi
# Setup /dev/shm/sf-u1001/run/log (in-memory /var/run...)
if [[ -d /dev/shm ]]; then
2022-07-28 16:02:58 +00:00
SF_SHMDIR="/dev/shm/sf-u${SF_HOST_USER_ID}"
2022-07-25 12:42:33 +00:00
else
2022-07-28 16:02:58 +00:00
SF_SHMDIR="/tmp/sf-u${SF_HOST_USER_ID}"
2022-07-25 12:42:33 +00:00
fi
2022-07-27 14:26:03 +00:00
# Create ./data or symlink correctly.
[[ -n $SF_DATADIR ]] && {
[[ ! -d "$SF_DATADIR" ]] && mkdir -p "$SF_DATADIR"
[[ ! -d "${SF_BASEDIR}/data" ]] && ln -s "$SF_DATADIR" "${SF_BASEDIR}/data"
}
2022-08-09 19:29:11 +00:00
# Copy over sfbin
[[ -d "${SF_BASEDIR}/sfbin" ]] && rm -rf "${SF_BASEDIR}/sfbin"
2022-08-13 15:18:52 +00:00
mergedir "sfbin"
2022-07-25 12:42:33 +00:00
}
# Add user
init_user
# Move SSHD out of the way if SF_SSH_PORT==22 (to port 64222)
init_host_sshd
init_basedir
# Install Docker and docker-cli
install_docker
2022-05-10 15:39:52 +00:00
# SSHD's login user (normally 'root' with uid 1000) needs to start docker instances
usermod -a -G docker "${SF_HOST_USER}"
2022-08-09 22:09:50 +00:00
# Free some space
apt-get clean
rm -rf /var/lib/apt/lists/*
snap list --all | awk '/disabled/{print $1, $3}' | while read pkg revision; do
snap remove "$pkg" --revision="$revision"
done
journalctl --vacuum-size=20M
journalctl --vacuum-time=10d
2022-05-10 15:39:52 +00:00
# NOTE: Only needed if source is mounted into vmbox (for testing)
[[ "$(stat -c %G /segfault 2>/dev/null)" = "vboxsf" ]] && usermod -a -G vboxsf "${SF_HOST_USER}"
2022-07-25 12:42:33 +00:00
# SNAPSHOT #3 (2022-07-22)
# exit
2022-05-10 15:39:52 +00:00
# Create SSH-KEYS and directories.
2022-05-19 11:17:21 +00:00
[[ -d "${SF_BASEDIR}/config/etc/ssh" ]] || {
IS_NEW_SSH_HOST_KEYS=1
SUDO_SF "mkdir -p \"${SF_BASEDIR}/config/etc/ssh\" && ssh-keygen -A -f \"${SF_BASEDIR}\"/config"
}
[[ -f "${SF_BASEDIR}/config/etc/ssh/id_ed25519" ]] || {
IS_NEW_SSH_LOGIN_KEYS=1
SUDO_SF "ssh-keygen -q -t ed25519 -C \"\" -N \"\" -f \"${SF_BASEDIR}/config/etc/ssh/id_ed25519\""
}
2022-07-31 22:15:48 +00:00
init_config_run
2022-07-25 12:42:33 +00:00
### Create guest, encfs and other docker images.
2022-05-19 11:17:21 +00:00
[[ -z $SF_NO_INTERNET ]] && { SUDO_SF "cd ${SFI_SRCDIR} && make" || exit; }
2022-05-10 15:39:52 +00:00
2022-07-25 12:42:33 +00:00
# SNAPSHOT #4 (2022-07-22)
# SNAPSHOT #4.1 (2022-07-23)
# exit
### Find out my own hostname unless SF_FQDN is set (before NordVPN is runnning)
2022-05-10 15:39:52 +00:00
[[ -z $SF_FQDN ]] && {
# Find out my own hostname
2022-05-19 11:17:21 +00:00
[[ -z $SF_NO_INTERNET ]] && {
IP="$(curl ifconfig.me 2>/dev/null)"
2022-05-20 15:59:45 +00:00
HOST="$(host "$IP")" && { HOST="$(echo "$HOST" | sed -E 's/.*name pointer (.*)\.$/\1/g')"; true; } || HOST="$(hostname -f)"
2022-05-19 11:17:21 +00:00
}
2022-05-10 15:39:52 +00:00
# To short or contains illegal characters?
[[ "$HOST" =~ ^[a-zA-Z0-9.-]{4,61}$ ]] || unset HOST
SF_FQDN="${HOST:-UNKNOWN}"
unset ip
unset HOST
}
2022-07-25 12:42:33 +00:00
2022-05-10 15:39:52 +00:00
DEBUGF "SF_FQDN=${SF_FQDN}"
# Create '.env' file for docker-compose
SF_BASEDIR_ESC="${SF_BASEDIR//\//\\/}"
2022-07-25 12:42:33 +00:00
SF_NORDVPN_PRIVATE_KEY_ESC="${SF_NORDVPN_PRIVATE_KEY//\//\\/}"
2022-05-10 15:39:52 +00:00
SF_FQDN_ESC="${SF_FQDN//\//\\/}"
2022-07-28 16:02:58 +00:00
SF_SHMDIR_ESC="${SF_SHMDIR//\//\\/}"
2022-07-27 14:26:03 +00:00
# .env needs to be where the images are build (in the source directory)
2022-05-10 15:39:52 +00:00
ENV="${SFI_SRCDIR}/.env"
2022-07-25 12:42:33 +00:00
if [[ -e "${ENV}" ]]; then
IS_USING_EXISTING_ENV_FILE=1
else
2022-05-10 15:39:52 +00:00
SUDO_SF "cp \"${SFI_SRCDIR}/provision/env.example\" \"${ENV}\" && \
sed -i 's/^SF_BASEDIR.*/SF_BASEDIR=${SF_BASEDIR_ESC}/' \"${ENV}\" && \
2022-07-28 16:02:58 +00:00
sed -i 's/.*SF_SHMDIR.*/SF_SHMDIR=${SF_SHMDIR_ESC}/' \"${ENV}\" && \
2022-07-28 13:33:08 +00:00
sed -i 's/.*SF_FQDN.*/SF_FQDN=${SF_FQDN_ESC}/' \"${ENV}\"" || ERREXIT 120 failed
[[ -n $SF_SSH_PORT ]] && { SUDO_SF "sed -i 's/.*SF_SSH_PORT.*/SF_SSH_PORT=${SF_SSH_PORT}/' \"${ENV}\"" || ERREXIT 121 failed; }
2022-07-27 14:26:03 +00:00
[[ -n $SF_NORDVPN_PRIVATE_KEY ]] && { SUDO_SF "sed -i 's/.*SF_NORDVPN_PRIVATE_KEY.*/SF_NORDVPN_PRIVATE_KEY=${SF_NORDVPN_PRIVATE_KEY_ESC}/' \"${ENV}\"" || ERREXIT 121 failed; }
[[ -n $SF_MAXOUT ]] && { SUDO_SF "sed -i 's/.*SF_MAXOUT.*/SF_MAXOUT=${SF_MAXOUT}/' \"${ENV}\"" || ERREXIT 121 failed; }
[[ -n $SF_MAXIN ]] && { SUDO_SF "sed -i 's/.*SF_MAXIN.*/SF_MAXIN=${SF_MAXIN}/' \"${ENV}\"" || ERREXIT 121 failed; }
2022-07-25 12:42:33 +00:00
fi
(cd "${SFI_SRCDIR}" && \
docker-compose pull && \
2022-07-27 14:26:03 +00:00
docker-compose build -q && \
docker network prune -f)
2022-09-09 14:19:46 +00:00
if docker ps | grep -E "sf-host|sf-router" >/dev/null; then
2022-07-27 14:26:03 +00:00
WARNMSG="A SEGFAULT is already running."
IS_DOCKER_NEED_MANUAL_START=1
2022-07-25 12:42:33 +00:00
else
2022-07-28 13:33:08 +00:00
docker container rm sf-host &>/dev/null
2022-07-28 16:02:58 +00:00
(cd "${SFI_SRCDIR}" && SF_SEED="${SF_SEED}" docker-compose up --force-recreate -d) || { WARNMSG="Could not start docker-compose."; IS_DOCKER_NEED_MANUAL_START=1; }
2022-07-25 12:42:33 +00:00
fi
2022-05-10 15:39:52 +00:00
2022-07-28 13:33:08 +00:00
GS_SECRET=$(echo -n "GS-${SF_SEED}${SF_FQDN}" | sha512sum | base64 | tr -dc '[:alpha:]' | head -c 12)
2022-05-19 11:17:21 +00:00
echo -e "***${CG}SUCCESS${CN}***"
[[ -z $IS_USING_EXISTING_ENV_FILE ]] || WARN 4 "Using existing .env file (${ENV})"
2022-07-27 14:26:03 +00:00
[[ -z $IS_DOCKER_NEED_MANUAL_START ]] || {
WARN 5 "${WARNMSG} Please run:"
2022-09-09 14:19:46 +00:00
INFO "(cd \"${SFI_SRCDIR}\" && "'\\\n'"\
docker-compose down; docker stop \$(docker ps -q --filter name='^(lg-|encfs-)'); "'\\\n'"\
docker network prune -f; docker container rm sf-host 2>/dev/null; "'\\\n'"\
2022-07-28 16:02:58 +00:00
SF_SEED=\"${SF_SEED}\" docker-compose up --force-recreate -d)"
2022-05-10 21:24:48 +00:00
}
2022-07-27 14:26:03 +00:00
[[ -z $SF_NORDVPN_PRIVATE_KEY ]] && {
WARN 6 "NordVPN ${CR}DISABLED${CN}. Set SF_NORDVPN_PRIVATE_KEY= to enable."
INFO "To retrieve the PRIVATE_KEY try: \n\
${CDC}docker run --rm --cap-add=NET_ADMIN -e USER=XXX -e PASS=YYY bubuntux/nordvpn:get_private_key${CN}"
}
2022-07-28 13:33:08 +00:00
[[ -n $IS_SSH_GOT_MOVED ]] && INFO "${CY}System's SSHD was in the way and got moved to ${SF_SSH_PORT_MASTER}${CN}"
INFO "Basedir : ${CC}${SF_BASEDIR}${CN}"
2022-07-28 16:02:58 +00:00
INFO "SF_SEED : ${CDY}${SF_SEED}${CN}"
2022-07-28 13:33:08 +00:00
INFO "Password : ${CDY}${SF_USER_PASSWORD:-segfault}${CN}"
[[ -n $SF_SSH_PORT ]] && PORTSTR="-p${SF_SSH_PORT} "
INFO "SSH : ${CDC}ssh ${PORTSTR}${SF_USER:-root}@${SF_FQDN:-UNKNOWN}${CN}"
INFO "SSH (gsocket) : ${CDC}gsocket -s ${GS_SECRET} ssh ${SF_USER:-root}@${SF_FQDN%.*}.gsocket${CN}"
2022-05-19 11:17:21 +00:00
[[ -z $IS_NEW_SSH_HOST_KEYS ]] && STR="existing" || STR="${CR}***NEW***${CN}"
2022-07-25 12:42:33 +00:00
INFO "SSH Host Keys : $(cd "${SF_BASEDIR}/config" && md5sum etc/ssh/ssh_host_ed25519_key) (${STR})"
2022-05-19 11:17:21 +00:00
[[ -z $IS_NEW_SSH_LOGIN_KEYS ]] && STR="existing" || STR="${CR}***NEW***${CN}"
INFO "SSH Login Keys : $(cd "${SF_BASEDIR}/config" && md5sum etc/ssh/id_ed25519) (${STR})"
2022-08-09 19:29:11 +00:00
[[ -n $CONFLICT ]] && {
WARN 7 "Not updating these directories in ${SF_BASEDIR}:"
for x in "${CONFLICT[@]}"; do
INFO "${x}"
done
}
2022-05-19 11:17:21 +00:00
2022-05-10 15:39:52 +00:00