diff --git a/.env.dist b/.env.dist index 91e2db72..54fee77a 100644 --- a/.env.dist +++ b/.env.dist @@ -264,21 +264,24 @@ REDIS_VERSION="stable" REDIS_REQUIRE_PASSWORD=false REDIS_PASSWORD="" -[vsftpd] -INSTALL_VSFTPD=true +[ftpd] +INSTALL_FTP_SERVER=true # Available installer: repo | source. -VSFTPD_INSTALLER="source" +FTP_SERVER_INSTALLER="source" -# Available version: 3.0.5 or latest. -VSFTPD_VERSION="3.0.5" +# Supported FTP server: vsftpd | pureftpd. +FTP_SERVER_NAME="vsftpd" + +# Available version: 3.0.5 (vsftpd), 1.0.50 (pure-ftpd), or latest. +FTP_SERVER_VERSION="latest" # Enable FTP over TLS. -VSFTPD_SSL_ENABLE=true +FTP_SSL_ENABLE=true # Range of passv ports. FTP_MIN_PORT=45000 -FTP_MAX_PORT=45099 +FTP_MAX_PORT=45999 [dns] # TODO: Install DNS server. diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 21640037..5c3dd91c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,12 +3,10 @@ on: push: branches: - '2.x.x' - - '3.x.x' - 'master' pull_request: branches: - '2.x.x' - - '3.x.x' - 'master' workflow_dispatch: jobs: @@ -48,9 +46,9 @@ jobs: sudo apt-get install -q -y bash curl sudo curl -sSL -o /usr/local/bin/shunit2 https://raw.githubusercontent.com/kward/shunit2/master/shunit2 sudo chmod +x /usr/local/bin/shunit2 - sudo curl -sSLO https://github.com/koalaman/shellcheck/releases/download/v0.7.2/shellcheck-v0.7.2.linux.x86_64.tar.xz - sudo tar -xf shellcheck-v0.7.2.linux.x86_64.tar.xz - sudo mv shellcheck-v0.7.2/shellcheck /usr/local/bin/ + sudo curl -sSLO https://github.com/koalaman/shellcheck/releases/download/v0.8.0/shellcheck-v0.8.0.linux.x86_64.tar.xz + sudo tar -xf shellcheck-v0.8.0.linux.x86_64.tar.xz + sudo mv shellcheck-v0.8.0/shellcheck /usr/local/bin/ sudo chmod +x /usr/local/bin/shellcheck # Shellcheck Tests - name: Run shellcheck testing diff --git a/etc/init.d/pure-ftpd b/etc/init.d/pure-ftpd new file mode 100755 index 00000000..a47c3bca --- /dev/null +++ b/etc/init.d/pure-ftpd @@ -0,0 +1,117 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: pure-ftpd +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Should-Start: slapd mysql postgresql-8.3 postgresql-8.4 +# Should-Stop: slapd mysql postgresql-8.3 postgresql-8.4 +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +### END INIT INFO +# +# pure-ftpd starts and stops the pure-ftpd ftp daemon +# +# Copyright 2002-2011 by Stefan Hornburg (Racke) + +PATH=/sbin:/bin:/usr/sbin:/usr/bin +NAME=pure-ftpd +DESC="ftp server" +: ${SSDAEMONLOGOPTS:="--quiet"} +UPLOADDAEMON=/usr/sbin/pure-uploadscript +UDNAME=pure-uploadscript +UDDESC="ftp upload handler" +WRAPPER=/usr/sbin/pure-ftpd-wrapper + +# load LSB init-functions to get status_of_proc helper +. /lib/lsb/init-functions + +PIDFILE=/var/run/pure-ftpd/pure-ftpd.pid + +# try to figure with suffix this script is called, +# $0 might be a symlink pointing to this script +if [ -h $0 ]; then + ME=`/bin/readlink $0` +else + ME=$0 +fi + +SUFFIX=`basename $ME | sed -ne 's/^pure-ftpd-\(.*\)/\1/p'` +if [ "$SUFFIX" ] ; then + DAEMON=/usr/sbin/pure-ftpd-$SUFFIX +else + DAEMON=/usr/sbin/pure-ftpd +fi + +export STANDALONE_OR_INETD=inetd +export VIRTUALCHROOT= +test -r /etc/default/pure-ftpd-common && . /etc/default/pure-ftpd-common + +if [ "$VIRTUALCHROOT" = "true" ]; then + if [ "$SUFFIX" ]; then + SUFFIX="$SUFFIX-virtualchroot" + else + SUFFIX="virtualchroot" + fi +fi + +test -x $DAEMON || exit 0 +test -x $WRAPPER || exit 0 + +set -e + +if [ ! -e `dirname $PIDFILE` ];then + mkdir `dirname $PIDFILE` +fi + +start_uploadscript() { + if [ "$UPLOADSCRIPT" -a "$STANDALONE_OR_INETD" != inetd ] && \ + egrep -i '^[ ]*(yes|1|on)[ ]*' /etc/pure-ftpd/conf/CallUploadScript > /dev/null 2>&1 + then + UOPTS="" + test "$UPLOADUID" && UOPTS="$UOPTS -u $UPLOADUID" + test "$UPLOADGID" && UOPTS="$UOPTS -g $UPLOADGID" + echo -n "$1 $UDDESC: " + start-stop-daemon --start $SSDAEMONLOGOPTS --oknodo \ + --exec $UPLOADDAEMON -- -r "$UPLOADSCRIPT" -B $UOPTS + echo "$UDNAME." + + fi +} + +case "$1" in + start) + test "$STANDALONE_OR_INETD" = standalone || exit 0 + echo -n "Starting $DESC: " + --start $SSDAEMONLOGOPTS --pidfile "$PIDFILE" \ + --exec $WRAPPER -- $SUFFIX + start_uploadscript Starting + ;; + stop) + echo -n "Stopping $DESC: " + start-stop-daemon --stop $SSDAEMONLOGOPTS --oknodo \ + --pidfile "$PIDFILE" + start-stop-daemon --stop $SSDAEMONLOGOPTS --oknodo --exec $UPLOADDAEMON + echo "$NAME." + ;; + restart|force-reload) + test "$STANDALONE_OR_INETD" = standalone || exit 0 + echo -n "Restarting $DESC: " + start-stop-daemon --stop $SSDAEMONLOGOPTS --oknodo \ + --pidfile "$PIDFILE" + start-stop-daemon --stop $SSDAEMONLOGOPTS --oknodo --exec $UPLOADDAEMON + sleep 1 + start-stop-daemon --start $SSDAEMONLOGOPTS --pidfile "$PIDFILE" \ + --exec $WRAPPER -- $SUFFIX + start_uploadscript Restarting + ;; + status) + status_of_proc -p /var/run/pure-ftpd/pure-ftpd.pid $DAEMON $NAME && exit 0 || exit $? + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|restart|force-reload|status}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/etc/systemd/pure-ftpd.service b/etc/systemd/pure-ftpd.service new file mode 100644 index 00000000..b3e2dfac --- /dev/null +++ b/etc/systemd/pure-ftpd.service @@ -0,0 +1,27 @@ +# Automatically generated by systemd-sysv-generator + +[Unit] +Description=Free FTP Server with a strong focus on software security installed using LEMPer Stack +Documentation=https://www.pureftpd.org/project/pure-ftpd/, man:systemd-sysv-generator(8) +SourcePath=/etc/init.d/pure-ftpd +Before=multi-user.target +Before=multi-user.target +Before=multi-user.target +Before=graphical.target +After=remote-fs.target +After=slapd.service +After=mysql.service +After=postgresql-8.3.service +After=postgresql-8.4.service + +[Service] +Type=forking +Restart=no +TimeoutSec=5min +IgnoreSIGPIPE=no +KillMode=process +GuessMainPID=no +RemainAfterExit=yes +SuccessExitStatus=5 6 +ExecStart=/etc/init.d/pure-ftpd start +ExecStop=/etc/init.d/pure-ftpd stop diff --git a/install.sh b/install.sh index 5311899d..c2e40ed5 100755 --- a/install.sh +++ b/install.sh @@ -144,10 +144,17 @@ if [ -f ./scripts/install_mailer.sh ]; then . ./scripts/install_mailer.sh fi -### VSFTPD installation ### -if [ -f ./scripts/install_vsftpd.sh ]; then - echo "" - . ./scripts/install_vsftpd.sh +### FTP installation ### +if [[ "${FTP_SERVER_NAME}" == "pureftpd" || "${FTP_SERVER_NAME}" == "pure-ftpd" ]]; then + if [ -f ./scripts/install_pureftpd.sh ]; then + echo "" + . ./scripts/install_pureftpd.sh + fi +else + if [ -f ./scripts/install_vsftpd.sh ]; then + echo "" + . ./scripts/install_vsftpd.sh + fi fi ### Fail2ban, intrusion prevention software framework. ### diff --git a/lemper.sh b/lemper.sh index 69c1cd09..f8de0d02 100755 --- a/lemper.sh +++ b/lemper.sh @@ -140,10 +140,17 @@ function lemper_install() { . ./scripts/install_mailer.sh fi - ### VSFTPD installation ### - if [ -f ./scripts/install_vsftpd.sh ]; then - echo "" - . ./scripts/install_vsftpd.sh + ### FTP installation ### + if [[ "${FTP_SERVER_NAME}" == "pureftpd" || "${FTP_SERVER_NAME}" == "pure-ftpd" ]]; then + if [ -f ./scripts/install_pureftpd.sh ]; then + echo "" + . ./scripts/install_pureftpd.sh + fi + else + if [ -f ./scripts/install_vsftpd.sh ]; then + echo "" + . ./scripts/install_vsftpd.sh + fi fi ### Fail2ban, intrusion prevention software framework. ### @@ -330,10 +337,17 @@ function lemper_remove() { . ./scripts/remove_certbotle.sh fi - ### Remove VSFTPD ### - if [ -f ./scripts/remove_vsftpd.sh ]; then - echo "" - . ./scripts/remove_vsftpd.sh + ### Remove FTP installation ### + if [[ "${FTP_SERVER_NAME}" == "pureftpd" || "${FTP_SERVER_NAME}" == "pure-ftpd" ]]; then + if [ -f ./scripts/remove_pureftpd.sh ]; then + echo "" + . ./scripts/remove_pureftpd.sh + fi + else + if [ -f ./scripts/remove_vsftpd.sh ]; then + echo "" + . ./scripts/remove_vsftpd.sh + fi fi ### Remove Fail2ban ### @@ -524,12 +538,13 @@ function init_lemper_install() { shift # Set getopt options. - OPTS=$(getopt -o h:i:dgpDBF \ - -l debug,development,dry-run,fix-broken-install,force,guided,hostname:,ipv4:,production,unattended \ + OPTS=$(getopt -o e:h:i:dgpDBF \ + -l admin-email:,debug,development,dry-run,fix-broken-install,force,guided,hostname:,ipv4:,production,unattended \ -l with-nginx:,with-nginx-installer:,with-nginx-custom-ssl:,with-nginx-lua,with-nginx-pagespeed,with-nginx-passenger \ - -l with-nginx-pcre:,with-nginx-rtmp,with-php:,with-php-extensions:,with-php-loader: \ - -l with-mysql-server:,with-memcached:,with-memcached-installer:,with-mongodb:,with-mongodb-admin: \ - -l with-redis:,with-redis-installer:,with-redis-requirepass:,with-ftp-server: \ + -l with-nginx-pcre:,with-nginx-rtmp,with-php:,with-php-extensions:,with-php-loader:,with-mysql-server: \ + -l with-ftp-server:,with-memcached:,with-memcached-installer:,with-mongodb:,with-mongodb-admin:,with-redis: \ + -l with-redis-installer:,with-redis-requirepass:,with-ssh-passwordless,with-ssh-port:,with-ssh-pub-key: \ + -l with-mailer,with-mail-sender-domain: \ -n "${PROG_NAME}" -- "$@") eval set -- "${OPTS}" @@ -542,7 +557,7 @@ function init_lemper_install() { shift NGINX_VERSION=${1} sed -i "s/INSTALL_NGINX=[a-zA-Z]*/INSTALL_NGINX=true/g" .env - sed -i "s/NGINX_VERSION=\"[0-9a-zA-Z.\ ]*\"/NGINX_VERSION=\"${NGINX_VERSION}\"/g" .env + sed -i "s/NGINX_VERSION=\"[0-9a-zA-Z._-\ ]*\"/NGINX_VERSION=\"${NGINX_VERSION}\"/g" .env shift ;; # Usage: --with-nginx-installer @@ -565,7 +580,7 @@ function init_lemper_install() { shift NGINX_CUSTOMSSL_VERSION=${1-"openssl-1.1.1l"} sed -i "s/NGINX_WITH_CUSTOMSSL=[a-zA-Z]*/NGINX_WITH_CUSTOMSSL=true/g" .env - sed -i "s/NGINX_CUSTOMSSL_VERSION=\"[0-9a-zA-Z.-\ ]*\"/NGINX_CUSTOMSSL_VERSION=\"${NGINX_CUSTOMSSL_VERSION}\"/g" .env + sed -i "s/NGINX_CUSTOMSSL_VERSION=\"[0-9a-zA-Z._-\ ]*\"/NGINX_CUSTOMSSL_VERSION=\"${NGINX_CUSTOMSSL_VERSION}\"/g" .env shift ;; --with-nginx-lua) @@ -585,7 +600,7 @@ function init_lemper_install() { shift NGINX_PCRE_VERSION=${1-"8.45"} sed -i "s/NGINX_WITH_PCRE=[a-zA-Z]*/NGINX_WITH_PCRE=true/g" .env - sed -i "s/NGINX_PCRE_VERSION=\"[0-9a-zA-Z.\ ]*\"/NGINX_PCRE_VERSION=\"${NGINX_PCRE_VERSION}\"/g" .env + sed -i "s/NGINX_PCRE_VERSION=\"[0-9a-zA-Z._-\ ]*\"/NGINX_PCRE_VERSION=\"${NGINX_PCRE_VERSION}\"/g" .env shift ;; --with-nginx-rtmp) @@ -598,7 +613,7 @@ function init_lemper_install() { shift PHP_VERSIONS=${1} sed -i "s/INSTALL_PHP=[a-zA-Z]*/INSTALL_PHP=true/g" .env - sed -i "s/PHP_VERSIONS=\"[0-9.\ ]*\"/PHP_VERSIONS=\"${PHP_VERSIONS}\"/g" .env + sed -i "s/PHP_VERSIONS=\"[0-9a-zA-Z._-\ ]*\"/PHP_VERSIONS=\"${PHP_VERSIONS}\"/g" .env shift ;; # Usage: --with-php-extensions= @@ -606,7 +621,7 @@ function init_lemper_install() { exit_if_optarg_is_empty "${1}" "${2}" shift PHP_EXTENSIONS=$( echo "${1}" | tr '[:upper:]' '[:lower:]' ) - sed -i "s/PHP_EXTENSIONS=\"[a-zA-Z,\ ]*\"/PHP_EXTENSIONS=\"${PHP_EXTENSIONS}\"/g" .env + sed -i "s/PHP_EXTENSIONS=\"[0-9a-zA-Z,._-\ ]*\"/PHP_EXTENSIONS=\"${PHP_EXTENSIONS}\"/g" .env shift ;; # Usage: --with-php-loader @@ -658,7 +673,7 @@ function init_lemper_install() { ;; esac if [ -n "${MYSQL_SERVER_VER}" ]; then - sed -i "s/MYSQL_VERSION=\"[0-9.\ ]*\"/MYSQL_VERSION=\"${MYSQL_SERVER_VER}\"/g" .env + sed -i "s/MYSQL_VERSION=\"[0-9a-zA-Z._-\ ]*\"/MYSQL_VERSION=\"${MYSQL_SERVER_VER}\"/g" .env fi shift ;; @@ -668,7 +683,7 @@ function init_lemper_install() { shift MEMCACHED_VERSION=${1} sed -i "s/INSTALL_MEMCACHED=[a-zA-Z]*/INSTALL_MEMCACHED=true/g" .env - sed -i "s/MEMCACHED_VERSION=\"[0-9a-zA-Z.\ ]*\"/MEMCACHED_VERSION=\"${MEMCACHED_VERSION}\"/g" .env + sed -i "s/MEMCACHED_VERSION=\"[0-9a-zA-Z._-\ ]*\"/MEMCACHED_VERSION=\"${MEMCACHED_VERSION}\"/g" .env shift ;; # Usage: --with-memcached-installer @@ -692,7 +707,7 @@ function init_lemper_install() { shift MONGODB_VERSION=${1} sed -i "s/INSTALL_MONGODB=[a-zA-Z]*/INSTALL_MONGODB=true/g" .env - sed -i "s/MONGODB_VERSION=\"[0-9a-zA-Z.\ ]*\"/MONGODB_VERSION=\"${MONGODB_VERSION}\"/g" .env + sed -i "s/MONGODB_VERSION=\"[0-9a-zA-Z._-\ ]*\"/MONGODB_VERSION=\"${MONGODB_VERSION}\"/g" .env shift ;; # Usage: --with-mongodb-admin @@ -708,7 +723,7 @@ function init_lemper_install() { # Restore default IFS IFS=${_IFS} sed -i "s/MONGODB_ADMIN_USER=\"[0-9a-zA-Z._-]*\"/MONGODB_ADMIN_USER=\"${MONGODB_ADMIN_USER}\"/g" .env - sed -i "s/MONGODB_ADMIN_PASSWORD=\"[0-9a-zA-Z._-]*\"/MONGODB_ADMIN_PASSWORD=\"${MONGODB_ADMIN_PASS}\"/g" .env + sed -i "s/MONGODB_ADMIN_PASSWORD=\"[0-9a-zA-Z._-\ ]*\"/MONGODB_ADMIN_PASSWORD=\"${MONGODB_ADMIN_PASS}\"/g" .env shift ;; # Usage: --with-redis @@ -718,7 +733,7 @@ function init_lemper_install() { REDIS_VERSION=${1} if [ -z "${REDIS_VERSION}" ]; then REDIS_VERSION="stable"; fi sed -i "s/INSTALL_REDIS=[a-zA-Z]*/INSTALL_REDIS=true/g" .env - sed -i "s/REDIS_VERSION=\"[0-9a-zA-Z._-]*\"/REDIS_VERSION=\"${REDIS_VERSION}\"/g" .env + sed -i "s/REDIS_VERSION=\"[0-9a-zA-Z._-\ ]*\"/REDIS_VERSION=\"${REDIS_VERSION}\"/g" .env shift ;; # Usage: --with-redis-installer @@ -728,7 +743,7 @@ function init_lemper_install() { REDIS_INSTALLER=${1} case "${REDIS_INSTALLER}" in source) - sed -i "s/REDIS_INSTALLER=\"[a-zA-Z.\ ]*\"/REDIS_INSTALLER=\"source\"/g" .env + sed -i "s/REDIS_INSTALLER=\"[a-zA-Z]*\"/REDIS_INSTALLER=\"source\"/g" .env ;; *) sed -i "s/REDIS_INSTALLER=\"[a-zA-Z]*\"/REDIS_INSTALLER=\"repo\"/g" .env @@ -745,6 +760,46 @@ function init_lemper_install() { sed -i "s/REDIS_PASSWORD=\"[0-9a-zA-Z._-]*\"/REDIS_PASSWORD=\"${REDIS_PASSWORD}\"/g" .env shift ;; + --with-ftp-server) + exit_if_optarg_is_empty "${1}" "${2}" + shift + sed -i "s/INSTALL_FTP_SERVER=[a-zA-Z]*/INSTALL_FTP_SERVER=true/g" .env + FTP_SERVER=$( echo "${1}" | tr '[:upper:]' '[:lower:]' ) + # Reserve default IFS + _IFS=${IFS} + IFS='-' read -r -a _FTP_SERVER <<< "${FTP_SERVER}" + FTP_SERVER_NAME="${_FTP_SERVER[0]}" + FTP_SERVER_VER="${_FTP_SERVER[1]}" + # Restore default IFS + IFS=${_IFS} + case "${FTP_SERVER_NAME}" in + pureftpd | pure-ftpd) + sed -i "s/FTP_SERVER_NAME=\"[a-zA-Z]*\"/FTP_SERVER_NAME=\"pureftpd\"/g" .env + ;; + vsftpd) + sed -i "s/FTP_SERVER_NAME=\"[a-zA-Z]*\"/FTP_SERVER_NAME=\"vsftpd\"/g" .env + ;; + *) + echo "Selected MySQL Server: ${FTP_SERVER_NAME} is not supported, fallback to VSFTPD." + sed -i "s/FTP_SERVER_NAME=\"[0-9a-zA-Z._-]*\"/FTP_SERVER_NAME=\"vsftpd\"/g" .env + ;; + esac + if [ -n "${FTP_SERVER_VER}" ]; then + sed -i "s/FTP_SERVER_VERSION=\"[0-9a-zA-Z._-\ ]*\"/FTP_SERVER_VERSION=\"${FTP_SERVER_VER}\"/g" .env + fi + shift + ;; + --with-mailer) + sed -i "s/INSTALL_MAILER=[a-zA-Z]*/INSTALL_MAILER=true/g" .env + shift + ;; + --with-mail-sender-domain) + exit_if_optarg_is_empty "${1}" "${2}" + shift + MAIL_SENDER_DOMAIN=${1} + sed -i "s/SENDER_DOMAIN=\"[0-9a-zA-Z._-@\ ]*\"/SENDER_DOMAIN=\"${MAIL_SENDER_DOMAIN}\"/g" .env + shift + ;; --with-ssh-port) exit_if_optarg_is_empty "${1}" "${2}" shift @@ -761,6 +816,20 @@ function init_lemper_install() { sed -i "s/SSH_PASSWORDLESS=[a-zA-Z]*/SSH_PASSWORDLESS=true/g" .env shift ;; + --with-ssh-pub-key) + exit_if_optarg_is_empty "${1}" "${2}" + shift + SSH_PUB_KEY=${1} + sed -i "s/SSH_PUB_KEY=\"[0-9a-zA-Z._-]*\"/SSH_PUB_KEY=\"${SSH_PUB_KEY}\"/g" .env + shift + ;; + -e | --admin-email) + exit_if_optarg_is_empty "${1}" "${2}" + shift + LEMPER_ADMIN_EMAIL=${1} + sed -i "s/LEMPER_ADMIN_EMAIL=\"[0-9a-zA-Z._-@\ ]*\"/LEMPER_ADMIN_EMAIL=\"${LEMPER_ADMIN_EMAIL}\"/g" .env + shift + ;; -B | --fix-broken-install) sed -i "s/FIX_BROKEN_INSTALL=[a-zA-Z]*/FIX_BROKEN_INSTALL=true/g" .env shift @@ -806,13 +875,6 @@ function init_lemper_install() { sed -i "s/ENVIRONMENT=\"[a-zA-Z]*\"/ENVIRONMENT=\"production\"/g" .env shift ;; - --admin-email) - exit_if_optarg_is_empty "${1}" "${2}" - shift - LEMPER_ADMIN_EMAIL=${1} - sed -i "s/LEMPER_ADMIN_EMAIL=\"[0-9a-zA-Z._-@\ ]*\"/LEMPER_ADMIN_EMAIL=\"${LEMPER_ADMIN_EMAIL}\"/g" .env - shift - ;; --) shift break diff --git a/lib/lemper-manage.sh b/lib/lemper-manage.sh index ce5bffd8..eced2309 100755 --- a/lib/lemper-manage.sh +++ b/lib/lemper-manage.sh @@ -565,7 +565,23 @@ function remove_ssl() { # Update vhost config. if [[ "${DRYRUN}" != true ]]; then # Disable HTTPS first. - disable_ssl "${DOMAIN}" + echo "Disabling HTTPS configuration..." + + if [ -f "/etc/nginx/sites-available/${DOMAIN}.nonssl-conf" ]; then + # Disable vhost first. + run unlink "/etc/nginx/sites-enabled/${DOMAIN}.conf" + + # Backup ssl config. + run mv "/etc/nginx/sites-available/${DOMAIN}.conf" "/etc/nginx/sites-available/${DOMAIN}.ssl-conf" + + # Restore non ssl config. + run mv "/etc/nginx/sites-available/${DOMAIN}.nonssl-conf" "/etc/nginx/sites-available/${DOMAIN}.conf" + run ln -s "/etc/nginx/sites-available/${DOMAIN}.conf" "/etc/nginx/sites-enabled/${DOMAIN}.conf" + + reload_nginx + else + error "Something went wrong. You still could disable HTTPS manually." + fi # Remove SSL config. if [ -f "/etc/nginx/sites-available/${DOMAIN}.ssl-conf" ]; then @@ -759,7 +775,7 @@ function reload_nginx() { else error "Configuration couldn't be validated. Please correct the error below:"; nginx -t - exit 1 + [[ ${EXIT} ]] && exit 1 fi # Nginx service dead? Try to start it. else diff --git a/remove.sh b/remove.sh index 98f42f2b..aa08042e 100755 --- a/remove.sh +++ b/remove.sh @@ -103,10 +103,17 @@ if [ -f ./scripts/remove_certbotle.sh ]; then . ./scripts/remove_certbotle.sh fi -### Remove VSFTPD ### -if [ -f ./scripts/remove_vsftpd.sh ]; then - echo "" - . ./scripts/remove_vsftpd.sh +### Remove FTP installation ### +if [[ "${FTP_SERVER_NAME}" == "pureftpd" || "${FTP_SERVER_NAME}" == "pure-ftpd" ]]; then + if [ -f ./scripts/remove_pureftpd.sh ]; then + echo "" + . ./scripts/remove_pureftpd.sh + fi +else + if [ -f ./scripts/remove_vsftpd.sh ]; then + echo "" + . ./scripts/remove_vsftpd.sh + fi fi ### Remove Fail2ban ### diff --git a/scripts/install_dependencies.sh b/scripts/install_dependencies.sh index 4811af6d..827b34a1 100755 --- a/scripts/install_dependencies.sh +++ b/scripts/install_dependencies.sh @@ -40,7 +40,7 @@ run apt-get install -qq -y \ htop iptables libc-bin libc6-dev libcurl4-openssl-dev libgd-dev libgeoip-dev libgpgme11-dev \ libsodium-dev libssl-dev libxml2-dev libpcre3-dev libtool libxslt1-dev locales logrotate lsb-release \ make net-tools openssh-server openssl pkg-config python python3 re2c rsync software-properties-common \ - sasl2-bin sendmail snmp sudo sysstat tar tzdata unzip wget whois xz-utils zlib1g-dev + sasl2-bin snmp sudo sysstat tar tzdata unzip wget whois xz-utils zlib1g-dev # Update locale echo "Reconfigure locale..." diff --git a/scripts/install_mailer.sh b/scripts/install_mailer.sh index fd130347..244aa32d 100755 --- a/scripts/install_mailer.sh +++ b/scripts/install_mailer.sh @@ -39,6 +39,13 @@ function install_postfix() { if [[ ${DO_INSTALL_POSTFIX} == y* || ${DO_INSTALL_POSTFIX} == Y* ]]; then echo "Installing Postfix Mail-Transfer Agent..." + if [[ -n $(command -v sendmail) ]]; then + echo "Remove existing sendmail install..." + run service sendmail stop && \ + run update-rc.d -f sendmail remove && \ + run apt-get remove -qq -y sendmail + fi + run apt-get install -qq -y mailutils postfix # Configure Postfix. diff --git a/scripts/install_pureftpd.sh b/scripts/install_pureftpd.sh new file mode 100755 index 00000000..61cb7f39 --- /dev/null +++ b/scripts/install_pureftpd.sh @@ -0,0 +1,239 @@ +#!/usr/bin/env bash + +# Pure-FTPd Installer +# Min. Requirement : GNU/Linux Ubuntu 18.04 +# Last Build : 07/04/2022 +# Author : MasEDI.Net (me@masedi.net) +# Since Version : 1.0.0 + +# Include helper functions. +if [[ "$(type -t run)" != "function" ]]; then + BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) + # shellcheck disable=SC1091 + . "${BASE_DIR}/helper.sh" + + # Make sure only root can run this installer script. + requires_root "$@" + + # Make sure only supported distribution can run this installer script. + preflight_system_check +fi + +## +# Install Pure-FTPd. +## +function init_pureftpd_install() { + local SELECTED_INSTALLER="" + + if [[ "${AUTO_INSTALL}" == true ]]; then + if [[ "${INSTALL_FTP_SERVER}" == true ]]; then + DO_INSTALL_FTP_SERVER="y" + SELECTED_INSTALLER=${FTP_SERVER_INSTALLER:-"repo"} + else + DO_INSTALL_FTP_SERVER="n" + fi + else + while [[ "${DO_INSTALL_FTP_SERVER}" != "y" && "${DO_INSTALL_FTP_SERVER}" != "n" ]]; do + read -rp "Do you want to install FTP server (Pure-FTPd)? [y/n]: " -i y -e DO_INSTALL_FTP_SERVER + done + fi + + if [[ ${DO_INSTALL_FTP_SERVER} == y* || ${DO_INSTALL_FTP_SERVER} == Y* ]]; then + echo "Available Pure-FTPd installation method:" + echo " 1). Install from Repository (repo)" + echo " 2). Compile from Source (source)" + echo "--------------------------------" + + while [[ ${SELECTED_INSTALLER} != "1" && ${SELECTED_INSTALLER} != "2" && ${SELECTED_INSTALLER} != "none" && \ + ${SELECTED_INSTALLER} != "repo" && ${SELECTED_INSTALLER} != "source" ]]; do + read -rp "Select an option [1-2]: " -e SELECTED_INSTALLER + done + + case "${SELECTED_INSTALLER}" in + 1 | "repo") + echo "Installing FTP server (Pure-FTPd) from repository..." + + run apt-get install -y pure-ftpd-common pure-ftpd + ;; + 2 | "source") + echo "Installing FTP server (Pure-FTPd) from source..." + + local CURRENT_DIR && \ + CURRENT_DIR=$(pwd) + + if [[ "${FTP_SERVER_VERSION}" == "latest" || "${FTP_SERVER_VERSION}" == "stable" ]]; then + PUREFTPD_FILENAME="pure-ftpd-1.0.50.tar.gz" + PUREFTPD_ZIP_URL="https://download.pureftpd.org/pub/pure-ftpd/releases/${PUREFTPD_FILENAME}" + else + PUREFTPD_FILENAME="pure-ftpd-${FTP_SERVER_VERSION}.tar.gz" + PUREFTPD_ZIP_URL="https://download.pureftpd.org/pub/pure-ftpd/releases/${PUREFTPD_FILENAME}" + fi + + run cd "${BUILD_DIR}" && \ + run wget -q "${PUREFTPD_ZIP_URL}" && \ + run tar -zxf "${PUREFTPD_FILENAME}" && \ + run cd "${PUREFTPD_FILENAME%.*.*}" || return 1 + + # Enable MySQL support. + run ./configure --prefix=/usr --with-mysql --with-uploadscript --with-extauth --with-ftpwho --with-wrapper --with-virtualchroot --with-everything && \ + + # Make install. + run make && \ + run make install && \ + run cd "${CURRENT_DIR}" || return 1 + + # Move executable to /usr/sbin. + #if [[ -x /usr/local/sbin/pure-ftpd ]]; then + # run mv /usr/local/sbin/pure-ftpd /usr/sbin/ + #run ln -sf /usr/local/sbin/pure-ftpd /usr/sbin/pure-ftpd + #fi + ;; + *) + # Skip installation. + error "Installer method not supported. Pure-FTPd installation skipped." + ;; + esac + + # Configure Fal2ban. + echo "Configuring FTP server (Pure-FTPd)..." + + if [[ "${DRYRUN}" != true ]]; then + FTP_MIN_PORT=${FTP_MIN_PORT:-45000} + FTP_MAX_PORT=${FTP_MAX_PORT:-45999} + + # Backup original config. + if [[ -f /etc/pure-ftpd/pure-ftpd.conf ]]; then + run cp -f /etc/pure-ftpd/pure-ftpd.conf /etc/pure-ftpd/pure-ftpd.conf.bak + elif [[ ! -d /etc/pure-ftpd ]]; then + run mkdir -p /etc/pure-ftpd + fi + + run touch /etc/pure-ftpd/pure-ftpd.conf + + # Enable jail mode. + cat > /etc/pure-ftpd/pure-ftpd.conf <> /etc/pure-ftpd/pure-ftpd.conf <> /etc/vsftpd.conf </dev/null 2>&1 && pwd ) + # shellcheck disable=SC1091 + . "${BASE_DIR}/helper.sh" + + # Make sure only root can run this installer script. + requires_root "$@" + + # Make sure only supported distribution can run this installer script. + preflight_system_check +fi + +function init_pureftpd_removal() { + # Stop Pure-FTPd process. + if [[ $(pgrep -c pure-ftpd) -gt 0 ]]; then + run systemctl stop pure-ftpd + run systemctl disable pure-ftpd + fi + + if dpkg-query -l | awk '/pure-ftpd/ { print $2 }' | grep -qwE "^pure-ftpd$"; then + echo "Found FTP server (Pure-FTPd) package installation. Removing..." + run apt-get purge -qq -y pure-ftpd pure-ftpd-common pure-ftpd-mysql + else + info "FTP server (Pure-FTPd) package not found, possibly installed from source." + echo "Remove it manually!!" + + PUREFTPD_BIN=$(command -v pure-ftpd) + echo "Deleting Pure-FTPd binary executable: ${PUREFTPD_BIN}" + + [[ -x "${PUREFTPD_BIN}" ]] && run rm -f "${PUREFTPD_BIN}" + fi + + [[ -f /etc/systemd/system/multi-user.target.wants/pure-ftpd.service ]] && \ + run unlink /etc/systemd/system/multi-user.target.wants/pure-ftpd.service + [[ -f /lib/systemd/system/pure-ftpd.service ]] && run rm /lib/systemd/system/pure-ftpd.service && \ + [[ -x /etc/init.d/pure-ftpd ]] && run update-rc.d -f pure-ftpd remove + + # Remove Pure-FTPd config files. + echo "Removing FTP server (Pure-FTPd) configuration..." + warning "!! This action is not reversible !!" + + if [[ "${AUTO_REMOVE}" == true ]]; then + if [[ "${FORCE_REMOVE}" == true ]]; then + REMOVE_PUREFTPD_CONFIG="y" + else + REMOVE_PUREFTPD_CONFIG="n" + fi + else + while [[ "${REMOVE_PUREFTPD_CONFIG}" != "y" && "${REMOVE_PUREFTPD_CONFIG}" != "n" ]]; do + read -rp "Remove FTP server (Pure-FTPd) configuration files? [y/n]: " -e REMOVE_PUREFTPD_CONFIG + done + fi + + if [[ "${REMOVE_PUREFTPD_CONFIG}" == y* || "${REMOVE_PUREFTPD_CONFIG}" == Y* ]]; then + [[ -d /etc/pure-ftpd ]] && run rm -fr /etc/pure-ftpd + [[ -x /etc/init.d/pure-ftpd ]] && run update-rc.d -f pure-ftpd remove + [[ -f /usr/sbin/pure-ftpd-wrapper ]] && run rm -f /usr/sbin/pure-ftpd-wrapper + + echo "All configuration files deleted permanently." + fi + + # Final test. + if [[ "${DRYRUN}" != true ]]; then + run systemctl daemon-reload + + if [[ -z $(command -v pure-ftpd) ]]; then + success "FTP server (Pure-FTPd) removed succesfully." + else + info "Unable to remove FTP server (Pure-FTPd)." + fi + else + info "FTP server (Pure-FTPd) server removed in dry run mode." + fi +} + +echo "Uninstalling FTP server (Pure-FTPd)..." + +if [[ -n $(command -v pure-ftpd) ]]; then + if [[ "${AUTO_REMOVE}" == true ]]; then + REMOVE_PUREFTPD="y" + else + while [[ "${REMOVE_PUREFTPD}" != "y" && "${REMOVE_PUREFTPD}" != "n" ]]; do + read -rp "Are you sure to remove FTP server (Pure-FTPd)? [y/n]: " -e REMOVE_PUREFTPD + done + fi + + if [[ "${REMOVE_PUREFTPD}" == y* || "${REMOVE_PUREFTPD}" == Y* ]]; then + init_pureftpd_removal "$@" + else + echo "Found FTP server (Pure-FTPd), but not removed." + fi +else + info "Oops, FTP server (Pure-FTPd) installation not found." +fi diff --git a/scripts/remove_vsftpd.sh b/scripts/remove_vsftpd.sh index a62c7d50..6564df4a 100755 --- a/scripts/remove_vsftpd.sh +++ b/scripts/remove_vsftpd.sh @@ -23,6 +23,7 @@ function init_vsftpd_removal() { # Stop VSFTPD process. if [[ $(pgrep -c vsftpd) -gt 0 ]]; then run systemctl stop vsftpd + run systemctl disable vsftpd fi if dpkg-query -l | awk '/vsftpd/ { print $2 }' | grep -qwE "^vsftpd$"; then