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 \
net-tools make || ERREXIT
fi
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)
if docker ps | egrep "sf-host|sf-router" >/dev/null; then
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: "
INFO " (cd \" ${ SFI_SRCDIR } \" && \\ \n\
2022-08-09 19:29:11 +00:00
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