diff --git a/nc-install-ubuntu2004.sh b/nc-install-ubuntu2004.sh new file mode 100755 index 0000000..53b3d13 --- /dev/null +++ b/nc-install-ubuntu2004.sh @@ -0,0 +1,616 @@ +#!/bin/bash + +############################################################# +# Author: Taryel Hlontsi, 2022 +# 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 su -- root" +############################################################# + +# if set to true, ssh login only with ssh key which must(!) be configured upfront +NO_PASSWORD_SSH=true + +# only if new user is required (root login won't be allowed anyway) +OS_USER="ubuntu" +OS_USER_PASSWORD="password_goes_here" + +# change the IP. If domain is used then set it here as the server name +OS_SERVER_NAME="nextcloud" +OS_IP="127.0.0.1" + +# database setup for the nexcloud web app +NC_DB="nextcloud" +NC_DB_USER="nextcloud" +NC_DB_PASSWORD="qrsE1001^00000" + +# account to log on to the nexcloud web app +NC_ADMIN_USER="tar" +NC_ADMIN_PASSWORD="password_goes_here" + +# link for nextcloud, country is for ssl certificate and fixing some warnings +NC_DOWNLOAD_URL="https://download.nextcloud.com/server/releases/latest.zip" +NC_COUNTRY_CODE="PL" + +# optional, but removes some warnings in nextcloud +PHP_TIMEZONE="Europe/Warsaw" + +# may be left as is +LOG_DIR="/home" +LOG="${LOG_DIR}/log.txt" + +############################################################# +# HELPER FUNCTIONS +############################################################# +trace() { + PURPLE='\033[1;35m' + NC='\033[0m' + echo -e "${PURPLE}$1${NC}" + echo -e "TRACE:\t$1" >> $LOG +} + +info() { + GREEN='\033[1;32m' + NC='\033[0m' + echo -e "${GREEN}$1${NC}" + echo -e "INFO:\t$1" >> $LOG +} + +warn() { + YELLOW='\033[1;33m' + NC='\033[0m' + echo -e "${YELLOW}$1${NC}" + echo -e "WARN:\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 > 0 )) || (( $count == 0 )); then + true + else + false + fi +} + +not_exist() { + if test ! -f "$2"; then + warn "file does not exist: $2" + true + else + count=$(grep -Pc "$1" "$2") + code=$? + if (( $code > 0 )) || (( $count == 0 )); then + true + else + false + fi + fi +} + +configure() { + if not_exist "$1" "$3"; then + warn "setting \"$1\" is not in the file, thus won't be changed" + false + else + if not_set "$2" "$3"; then + sed -i "s~.*${1}.*~${2}~gi" "$3" && + trace "\"$1\" set to \"$2\"" && + true + else + warn "\"$2\" already set in \"$3\"" + false + fi + fi +} + +configured() { + count=$(grep -Pcx "$1" "$2") + if (( $? > 0 )) || (( $count == 0 )); then + false + else + true + fi +} + +insert_before() { + if not_set "$2" "$3"; then + sed -i "\~.*${1}.*~i ${2}" "$3" && + trace "\"$1\" set to \"$2\"" && + true + else + warn "\"$2\" already set in \"$3\"" + false + fi +} + +############################################################# +# 1 - ADD USER +############################################################# +add_user() { + info "STEP 1 Adding a user" + + adduser --disabled-password --gecos "" $OS_USER + chpasswd <<<"${OS_USER}:${OS_USER_PASSWORD}" + usermod -aG sudo $OS_USER + + info "STEP 1 done" +} + +############################################################# +# 2 - CHANGE SERVER NAME +############################################################# +change_servername() { + info "STEP 2 Changing server name" + + echo $OS_SERVER_NAME > /etc/hostname + hostentry="127.0.1.1\t${OS_SERVER_NAME}" + if not_set "$hostentry" "/etc/hostname"; then + echo -e "$hostentry" >> /etc/hosts + else + trace "\"$hostentry\" already set in \"/etc/hosts\"" + fi + + info "STEP 2 done" +} + +############################################################# +# 3 - INSTALL MARIADB +############################################################# +install_mariadb() { + info "STEP 3 Installing Maria DB" + + apt install -y mariadb-server + systemctl --quiet is-active mariadb || systemctl start mariadb + systemctl --quiet is-enabled mariadb || systemctl enable mariadb + + mysql -u root < ${CFG_NAME} + + DocumentRoot "/var/www/${OS_SERVER_NAME}" + ServerName ${OS_SERVER_NAME} + + + Options MultiViews FollowSymlinks + AllowOverride All + Order allow,deny + Allow from all + + + TransferLog /var/log/apache2/${OS_SERVER_NAME}_access.log + ErrorLog /var/log/apache2/${OS_SERVER_NAME}_error.log + + +EOF + + trace "Apache config created: ${CFG_NAME}. Enabling it" + a2ensite "${OS_SERVER_NAME}.conf" + a2enmod dir env headers mime rewrite ssl + systemctl restart apache2 + + info "STEP 6 done" +} + +############################################################# +# 7 - SET UP NEXTCLOUD +############################################################# +setup_nextcloud() { + info "STEP 7 Setting up NEXTCLOUD" + + USER='www-data' + NC_CONFIG="/var/www/${OS_SERVER_NAME}/config/config.php" + + trace "setting up ${NC_CONFIG}" + + cd "/var/www/${OS_SERVER_NAME}/" + + sudo -u www-data php occ maintenance:install \ + --database "mysql" \ + --database-name "${NC_DB}" \ + --database-user "${NC_DB_USER}" \ + --database-pass "${NC_DB_PASSWORD}" \ + --database-host "localhost" \ + --data-dir "/var/www/${OS_SERVER_NAME}/data" \ + --admin-user "${NC_ADMIN_USER}" \ + --admin-pass "${NC_ADMIN_PASSWORD}" + + trace "Nextcloud config creation result (0 means OK): $?" + + configure ';' " 'memcache.local' => '\\\OC\\\Memcache\\\APCu'," $NC_CONFIG && \ + echo " 'default_phone_region' => '${NC_COUNTRY_CODE}'," >> $NC_CONFIG && \ + echo ');' >> $NC_CONFIG + + if configured "\t2 => '${OS_IP}'," $NC_CONFIG; then + warn "Trusted domains were already configured" + else + configure "0 => 'localhost'," "\t0 => 'localhost',\n\t1 => '${OS_SERVER_NAME}',\n\t2 => '${OS_IP}'," $NC_CONFIG + trace "Trusted domains were set in ${NC_CONFIG}" + fi + + sudo chmod 660 $NC_CONFIG + trace "Changed mod of ${NC_CONFIG}" + + trace "Setting up a cron job for cron.php" + + cat < /etc/systemd/system/nextcloudcron.service +[Unit] +Description=Nextcloud cron.php job + +[Service] +User=${USER} +ExecStart=/usr/bin/php -f /var/www/${OS_SERVER_NAME}/cron.php --define apc.enable_cli=1 +KillMode=process +EOF + + cat < /etc/systemd/system/nextcloudcron.timer +[Unit] +Description=Run Nextcloud cron.php every 5 minutes + +[Timer] +OnBootSec=5min +OnUnitActiveSec=5min +Unit=nextcloudcron.service + +[Install] +WantedBy=timers.target +EOF + + systemctl enable --now nextcloudcron.timer + + # alternative approach is to setup a crontab: + #CRONTAB="/var/spool/cron/crontabs/${USER}" + #echo "*/5 * * * * php -f /var/www/${OS_SERVER_NAME}/cron.php" >> $CRONTAB + #sudo chmod 600 $CRONTAB + #sudo chown $USER:$USER $CRONTAB + + # to delete the crontab: + # crontab -r -u www-data + + info "STEP 7 done" +} + +############################################################# +# 8 - INSTALL SELF-SIGNED SSL CERTIFICATE +############################################################# +use_selfsigned_ssl_certificate() { + info "STEP 8.1 Configuring a self-signed SSL certificate" + + KEY="/etc/ssl/private/apache.key" + CRT="/etc/ssl/certs/apache.crt" + APACHE_SSL_CFG="/etc/apache2/sites-available/default-ssl.conf" + + openssl req -x509 \ + -nodes \ + -days 2048 \ + -newkey rsa:2048 \ + -keyout $KEY \ + -out $CRT \ + -subj "/C=${NC_COUNTRY_CODE}/ST=${NC_COUNTRY_CODE}/L=${NC_COUNTRY_CODE}/O=E Corp/OU=IT/CN=${OS_SERVER_NAME}/emailAddress=info@example.com" + + trace "SSH key created at: ${KEY}" + trace "Certificate created at: ${CRT}" + + CFG_NAME="/etc/apache2/sites-available/${OS_SERVER_NAME}-ssl.conf" + cat < ${CFG_NAME} + + + DocumentRoot "/var/www/${OS_SERVER_NAME}" + ServerName $OS_SERVER_NAME + SSLEngine on + + + Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains" + + + + Options MultiViews FollowSymlinks + AllowOverride All + Order allow,deny + Allow from all + + + + SSLOptions +StdEnvVars + + + SSLOptions +StdEnvVars + + + TransferLog /var/log/apache2/${OS_SERVER_NAME}_access.log + ErrorLog /var/log/apache2/${OS_SERVER_NAME}_error.log + +SSLCertificateFile ${CRT} +SSLCertificateKeyFile ${KEY} + +SSLProtocol -all +TLSv1.2 +TLSv1.3 +SSLHonorCipherOrder on +SSLCipherSuite EECDH+AESGCM:EDH+AESGCM +SSLCompression off + + + +EOF + trace "New config for site created: ${CFG_NAME}. Enabling it" + + a2ensite "${OS_SERVER_NAME}-ssl.conf" + + trace "Setting up auto-redirect to HTTPS..." + + CFG_NAME="/etc/apache2/sites-available/${OS_SERVER_NAME}.conf" + if configured ' RewriteEngine on' $CFG_NAME; then + warn 'HTTPS redirection was already set up' + else + configure "ServerName ${OS_SERVER_NAME}" \ + " ServerName ${OS_SERVER_NAME}\n RewriteEngine on\n RewriteCond %{HTTPS} !=on\n RewriteRule ^(.*)$ https://%{HTTP_HOST} [R=301,L]" \ + $CFG_NAME + trace "Entries added to ${CFG_NAME} to redirect all requests to HTTPS" + fi + + systemctl restart apache2 + + info "STEP 8.1 done" +} + +############################################################# +# 9 - SET AUTOUPDATES FOR THE SERVER +############################################################# +set_autoupdates() { + info "STEP 9 Setting up autoupdates (unattended-updates)" + + apt install -y unattended-upgrades + export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true + dpkg-reconfigure --priority=low unattended-upgrades + UNT_CFG="/etc/apt/apt.conf.d/50unattended-upgrades" + UNT_CFG_BACK="${LOG_DIR}/50unattended-upgrades.backup" + + trace "Going to rewrite ${UNT_CFG}" + trace "Backup will be here: ${UNT_CFG_BACK}" + + if test -f "$UNT_CFG_BACK"; then + warn "unattended updates config backup is already there!" + else + cp $UNT_CFG $UNT_CFG_BACK + cat <<'EOF' > ${UNT_CFG} +Unattended-Upgrade::Allowed-Origins { + "${distro_id}:${distro_codename}"; + "${distro_id}:${distro_codename}-security"; + "${distro_id}ESMApps:${distro_codename}-apps-security"; + "${distro_id}ESM:${distro_codename}-infra-security"; +}; + +Unattended-Upgrade::Package-Blacklist { +}; + +Unattended-Upgrade::DevRelease "auto"; +Unattended-Upgrade::Remove-Unused-Kernel-Packages "true"; +Unattended-Upgrade::Remove-New-Unused-Dependencies "true"; +Unattended-Upgrade::Remove-Unused-Dependencies "true"; +Unattended-Upgrade::Automatic-Reboot "true"; +Unattended-Upgrade::Automatic-Reboot-Time "05:00"; +EOF + fi + + info "STEP 9 done" +} + +############################################################# +# 10 - ADDITIONAL SECURITY FOR THE SERVER +############################################################# +secure_server() { + info "STEP 10 Securing the server" + + trace "Installing openssh server..." + apt install -y openssh-server + 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 test -f "$SSH_CFG_BACK"; then + warn "SSH config backup is already there!" + else + cp $SSH_CFG $SSH_CFG_BACK + cat < ${SSH_CFG} +Include /etc/ssh/sshd_config.d/*.conf +PermitRootLogin no +ChallengeResponseAuthentication no +UsePAM yes +X11Forwarding yes +PrintMotd no +AcceptEnv LANG LC_* +Subsystem sftp /usr/lib/openssh/sftp-server +EOF + if $NO_PASSWORD_SSH; then + info "Disabling SSH with password completely!" + echo 'PasswordAuthentication no' >> $SSH_CFG + fi + fi + + trace "Installing fail2ban..." + apt install -y fail2ban + 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 test -f "$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 'Apache Full' + ufw allow 'OpenSSH' + ufw status + + info "STEP 10 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!" + +apt update +apt upgrade -y +#add_user +change_servername +install_mariadb +install_php_and_apache +setup_php +download_nextcloud +setup_nextcloud +use_selfsigned_ssl_certificate +set_autoupdates +secure_server + +info "Don't forget to reboot" +info "Bye!" + +exit 0 + +# if domain name is available, SSL cert can be verified by Lets encrypt: +# sudo snap install core; sudo snap refresh core +# sudo snap install --classic certbot +# sudo ln -s /snap/bin/certbot /usr/bin/certbot +# sudo certbot certonly --apache +# sudo certbot renew --dry-run +# disable current ssl site in apache +# create new ssl config based on old one, replace certificates and ServerName (here: /etc/apache2/sites-available/) +# optional: replace ServerName in the http config as well +# and a new domain name to the trusted_domains section in NC's config.php (here: /var/www/nextcloud/config/) +# sudo systemctl restart apache2 + +# do not change ownership of /var/www/nextcloud, it should be owned by www-data +# sometimes login page cannot be started after a fresh install +# then try to run again: +# sudo chown -R www-data:www-data /var/www/nextcloud +# btw log is here: sudo vim /var/www/nextcloud/data/nextcloud.log