#!/bin/bash
#############################################################
# Author: Taryel Hlontsi, 2023
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see 
#############################################################
#############################################################
#           SETUP SECTION, use "sudo" to run the script
#############################################################
# if set to true, ssh login only with ssh key which must(!) be configured upfront
NO_PASSWORD_SSH=true
# user for gitea, and DB password that should be entered on the initialization web page
HOST_USER='git' # better don't change it
DB_PASSWORD='PasswordGoesHere'
GITEA_URL='https://dl.gitea.com/gitea/1.19.3/gitea-1.19.3-linux-arm64'
# change the IP. If domain is used then set it here as the server name
OS_SERVER_NAME="gitea.local"
OS_IP="192.168.0.10"
OS_COUNTRY="PL"
# may be left as is
LOG_DIR="/home/${SUDO_USER}"
LOG="${LOG_DIR}/log.txt"
#############################################################
#          HELPER FUNCTIONS
#############################################################
warn() {
    PURPLE='\033[1;35m'
    NC='\033[0m'
    echo -e "${PURPLE}$1${NC}"
    echo -e "WARN:\t$1" >> $LOG
}
info() {
    GREEN='\033[1;32m'
    NC='\033[0m'
    echo -e "${GREEN}$1${NC}"
    echo -e "INFO:\t$1" >> $LOG
}
trace() {
    YELLOW='\033[1;33m'
    NC='\033[0m'
    echo -e "${YELLOW}$1${NC}"
    echo -e "TRACE:\t$1" >> $LOG
}
error() {
    RED='\033[1;31m'
    NC='\033[0m'
    echo -e "${RED}$1${NC}"
    echo -e "ERROR:\t$1" >> $LOG
}
not_set() {
    count=$(grep -Pcx "$1" "$2")
    code=$?
    if [[ $code == 2 ]] && [[ -z "$count" ]]; then
        echo "not_set() func or its caller contains a bug that has to be fixed! param1=${1} param2=${2} code=${code} count=${count}. Exiting!"
        exit -1
    fi
    [[ $count == 0 ]] && [[ $code == 1 ]] && return 0
    return 1   
}
not_exist() {
    if [[ ! -e "$2" ]]; then
	warn "file does not exist: $2"
	return 0
    else
	count=$(grep -Pc "$1" "$2")
	code=$?
	[[ $count == 0 ]] && [[ $code == 1 ]] && return 0
	return 1   
    fi
}
configure() {
    if not_exist "$1" "$3"; then
	warn "setting \"$1\" is not in the file, thus won't be changed"
	return 1
    else
	if not_set "$2" "$3"; then	
	    sed -i "s~.*${1}.*~${2}~gi" "$3" &&
		trace "\"$1\" set to \"$2\"" &&
		return 0
	else
	    warn "\"$2\" already set in \"$3\""
	    return 2
	fi
    fi    
}
#############################################################
#          1 - ADD USER
#############################################################
add_user() {
    info "STEP 1 Adding a user for container"
    sudo adduser \
   --system \
   --shell /bin/bash \
   --gecos 'Git Version Control' \
   --group \
   --disabled-password \
   --home /home/git \
   git
    [[ $? -gt 0 ]] && { error 'Check git user setup, stopping now'; exit 1; }
    info "STEP 1 done"
    warn "Press enter to proceed with the next step"; read
}
#############################################################
#          2 - CHANGE SERVER NAME
#############################################################
change_servername() {
    info "STEP 2 Changing server name to ${OS_SERVER_NAME}"
    echo $OS_SERVER_NAME > /etc/hostname
    hostentry="127.0.1.1\t${OS_SERVER_NAME}"
    if not_set "$hostentry" "/etc/hosts"; then
	echo -e "$hostentry" >> /etc/hosts
    else
	warn "\"$hostentry\" already set in \"/etc/hosts\""
    fi
    info "STEP 2 done"
    warn "Press enter to proceed with the next step"; read
}
#############################################################
#          3 - INSTALL MARIADB
#############################################################
install_mariadb() {
    info "STEP 3 Installing Maria DB"
    apt-get -y install mariadb-server > /dev/null
    systemctl --quiet is-active mariadb || systemctl start mariadb
    systemctl --quiet is-enabled mariadb || systemctl enable mariadb
    mysql -u root < /dev/null
    systemctl --quiet is-active nginx || systemctl start nginx
    ufw allow 'Nginx Full'
    trace "Rewriting default /etc/nginx/nginx.conf"
    cat < /dev/null
    wget --continue $GITEA_URL --output-document gitea
    chmod +x gitea
    chown git:git gitea
    trace 'Creating nessesary directories with git owner'
    
    mkdir -p /var/lib/gitea/{custom,data,log}
    chown -Rv git:git /var/lib/gitea/
    chmod -Rv 750 /var/lib/gitea/
    mkdir /etc/gitea
    chown root:git /etc/gitea
    chmod 770 /etc/gitea
    cp --force gitea /usr/local/bin/gitea
    cat < /dev/null
    systemctl --quiet is-active sshd || systemctl start sshd
    systemctl --quiet is-enabled sshd || systemctl enable sshd
    SSH_CFG="/etc/ssh/sshd_config"
    SSH_CFG_BACK="${LOG_DIR}/sshd_config.backup"
    trace "Going to rewrite ${SSH_CFG}"
    trace "Backup will be here: ${SSH_CFG_BACK}"
    if [[ -e "$SSH_CFG_BACK" ]]; then
	warn "SSH config backup is already there!"
    else
	cp $SSH_CFG $SSH_CFG_BACK
	cat <> $SSH_CFG
	fi    
    fi
    trace "Installing fail2ban..."
    apt-get install -y fail2ban > /dev/null
    systemctl --quiet is-active fail2ban || systemctl start fail2ban
    systemctl --quiet is-enabled fail2ban || systemctl enable fail2ban
    fail2ban-client status
    F2B_CFG_ORIG="/etc/fail2ban/jail.conf"
    F2B_CFG_COPY="/etc/fail2ban/jail.local"
    if [[ -e "$F2B_CFG_COPY" ]]; then
	warn "Fail2ban was already set up"
    else
	cp $F2B_CFG_ORIG $F2B_CFG_COPY
	trace "Setting up ${F2B_CFG_COPY}"
	configure 'bantime  = 10m' 'bantime  = 60m' $F2B_CFG_COPY
	configure 'maxretry = 5' 'maxretry = 20' $F2B_CFG_COPY
    fi
    trace "Configuring ufw..."
    ufw --force enable
    ufw allow 'OpenSSH'
    ufw status    
    
    info "STEP 6 done"
    warn "Press enter to proceed with the next step"; read    
}
#############################################################
#          7 - MAKE AN UPDATE HELPER (AS A SCRIPT)
#############################################################
create_updater() {
    info 'Step 7 Create an updater for gitea (small helper utility)'
    MY_HOME="/home/${SUDO_USER}"
    SCRIPT='/usr/local/bin/gitea-update'
    cat < /dev/null
cd "${MY_HOME}"
gitea --version
wget --continue \$1 --output-document gitea
systemctl stop gitea
chmod +x gitea
chown git:git gitea
cp --force gitea /usr/local/bin/gitea
systemctl restart gitea
gitea --version
EOF
    chmod +x $SCRIPT
    trace "Updater has been created. call it 'sudo gitea-update url_to_new_version'"
    info 'Step 7 done'
}
#############################################################
#          RUN SECTION
#############################################################
user=$(whoami)
if [ $user != root ]; then
	error "You are using a non-privileged account"
        exit 1
fi
echo $(date +'%Y-%m-%d %H:%M') > $LOG
info "Hiya!"
sudo apt update
sudo apt upgrade -y
add_user
change_servername
install_mariadb
install_nginx
install_gitea
secure_server
create_updater
info "Don't forget to reboot"
info "Bye!"
info "PS. Log is here: ${LOG}"
warn "REBOOT NOW!!!"
exit 0
# restart is mandatory!!!
# if a real domain is available - a certificate can be obtained, for examle:
# sudo apt install certbot python3-certbot-nginx
# sudo certbot --nginx -d gittar.crabdance.com
# sudo certbot renew --dry-run
# gitea can be upgraded or downgraded by executing
# sudo gitea-update 'https://dl.gitea.com/gitea/1.19.3/gitea-1.19.3-linux-arm64'
# however before running it ensure there is no old gitea file in the home dir
# otherwise it will install the same version again (such 'safety' measure;))