Web - Sql - Mail - Python - Server

by tirsvad
71 deployments · 2 still active · last rev. 8 months ago

Debian installation

Hostname creation
Create user with some options like ssh-key, disable password.
Sql server Pregresql or MariaDb
Firewall secure server
NGINX or apache as an choice
SQL server choices (MariaDb, postgresql) with some options

TODO Mail server as an choise

Compatible with: Debian 8
						#!/bin/bash
#
# Installs a complete web environment with Nginx, Python, and PostgreSQL.
# Source https://github.com/linode-scripts/NGINX-SQL-Python/edit/master/14032
#
# <UDF name="user_name" label="Unprivileged user account name" example="This is the account that you will be using to log in." />
# <UDF name="user_password" label="Unprivileged user password"/>
# <UDF name="user_sshkey" default="" label="Public Key for User" example="Recommended method of authentication. It is more secure than password log in." />
# <UDF name="user_shell" label="Shell" oneof="/bin/zsh,/bin/bash" default="/bin/bash" />
# <UDF name="sshd_passwordauth" label="Use SSH password authentication" oneof="Yes,No" default="No" example="Turn off password authentication if you have added a Public Key." />
# <UDF name="sshd_permitrootlogin" label="Permit SSH root login" oneof="No,Yes" default="No" example="Root account should not be exposed." />
#
# <UDF name="host_name" label="Hostname" default="" example="leave empty to set the default hostname" />
# <UDF name="SQL_SERVER" Label="Pick one of" oneOf="postgresql,mariadb,none" example="Choose your sql server. (Mysql password is the same as superuser)" />
#
# <UDF name="webserver" label="Webserver" oneof="none,nginx,apache" default="none" />
#
# <UDF name="install_postfix" label="Postfix for mail" oneof="No,Yes" default="No" example="Postfix for transport of emails" />
# <UDF name="postfix_hostmaster" label="Which hostname used for outbound mail" default="yourhostname.com" example="Only answer if using postfix" />


set -e # Exit immediately if a command exits with a non-zero status.
set -u #

exec &> /root/stackscript.log

export DEBIAN_FRONTEND=noninteractive

###########################################################
# Configuration file that could be change to your needs
###########################################################

USER_GROUPS=sudo
SQL_SERVER_ROOT_PASSWORD=$USER_PASSWORD
FIREWALL_RULES_UP_FILENAME="/etc/iptables.up.rules"

FIREWALL_WEBSERVER_NOT_CHOOSEN_OPEN_PORTS_ANYWAY=no
# FIREWALL_WEBSERVER_SSL_PORT_ACCEPT=443
# FIREWALL_WEBSERVER_PORT_ACCEPT=80
# FIREWALL_WEBSERVER_ALT_PORT_ACCEPT=8080

# Mail settings
DB_MAIL_DB_NAME="servermail"
DB_MAIL_USER="usermail"
DB_MAIL_USER_PASSWORD="mailpassword"

FIREWALL_SENDMAIL=25
FIREWALL_SENDMAIL_SUBMISSION=587
FIREWALL_IMAP=143
FIREWALL_IMAPS=993
FIREWALL_POP=110
FIREWALL_POPS=465
FIREWALL_POPS3=993

###########################################################
# Create user
###########################################################

function lower {
    echo $1 | tr '[:upper:]' '[:lower:]'
}

function system_add_user {
    # system_add_user (USERNAME, USER_PASSWORD, USER_GROUPS, USER_SHELL=/bin/bash)
    USERNAME=`lower $1`
    USER_PASSWORD=$2
    USER_GROUPS=$3
    USER_SHELL=$4
    if [ -z "$4" ]; then
        SHELL="/bin/bash"
    fi
    useradd --create-home -G "$USER_GROUPS" -s "$USER_SHELL" "$USERNAME"
    echo "$USERNAME:$USER_PASSWORD" | chpasswd
}

function system_get_user_home {
    # system_get_user_home(username)
    cat /etc/passwd | grep "^$1:" | cut --delimiter=":" -f6
}

function system_user_add_ssh_key {
    # system_user_add_ssh_key(username, ssh_key)
    USERNAME=`lower $1`
    USER_HOME=`system_get_user_home "$USERNAME"`
    sudo -u "$USERNAME" mkdir "$USER_HOME/.ssh"
    sudo -u "$USERNAME" touch "$USER_HOME/.ssh/authorized_keys"
    sudo -u "$USERNAME" echo "$2" >> "$USER_HOME/.ssh/authorized_keys"
    chmod 0600 "$USER_HOME/.ssh/authorized_keys"
}

function system_sshd_edit_bool {
    # system_sshd_edit_bool (param_name, "Yes"|"No")
    VALUE=`lower $2`
    if [ "$VALUE" == "yes" ] || [ "$VALUE" == "no" ]; then
        sed -i "s/^#*\($1\).*/\1 $VALUE/" /etc/ssh/sshd_config
    fi
}

function system_sshd_permitrootlogin {
    system_sshd_edit_bool "PermitRootLogin" "$1"
}

function system_sshd_passwordauthentication {
    system_sshd_edit_bool "PasswordAuthentication" "$1"
}

###########################################################
# System
###########################################################

function system_update {
    apt-get -q update
    apt-get -y -q install aptitude
    aptitude -y -q full-upgrade
}

function system_primary_ip {
    # returns the primary IP assigned to eth0
    echo $(ifconfig eth0 | awk -F: '/inet addr:/ {print $2}' | awk '{ print $1 }')
}

function get_rdns {
    # calls host on an IP address and returns its reverse dns

    if [ ! -e /usr/bin/host ]; then
        aptitude -yqq install dnsutils > /dev/null
    fi
    echo $(host $1 | awk '/pointer/ {print $5}' | sed 's/\.$//')
}

function get_rdns_primary_ip {
    # returns the reverse dns of the primary IP assigned to this system
    echo $(get_rdns $(system_primary_ip))
}

function system_set_hostname {
    # $1 - The hostname to define
    HOSTNAME="$1"
        
    if [ ! -n "$HOSTNAME" ]; then
        echo "Hostname undefined"
        return 1;
    fi
    
    echo "$HOSTNAME" > /etc/hostname
    hostname -F /etc/hostname
}

###########################################################
# Helping tools
###########################################################

firewall_delete_rule () {
  grep -v "$1" $FIREWALL_RULES_UP_FILENAME > /etc/iptables.new.rules
  iptables-restore < /etc/iptables.new.rules
  iptables-save > /etc/iptables.up.rules
}

firewall_add_rule () {
  firewall_delete_rule "dport $1"
  firewall_delete_rule "sport $1"
  iptables -A INPUT -p tcp --dport $1 -m state --state NEW,ESTABLISHED -j ACCEPT
  iptables -A OUTPUT -p tcp --sport $1 -m state --state ESTABLISHED -j ACCEPT
  iptables-save > /etc/iptables.up.rules
}

###########################################################
# Setting hostname
###########################################################

echo -e "\n********************************************************"
echo -e "* Setting hostname"
echo -e "********************************************************"
if [ -z "${HOST_NAME}" ]; then
  HOST_NAME="$(get_rdns_primary_ip)"
fi
echo "$HOST_NAME" > /etc/hostname
hostname -F /etc/hostname

echo "Hostname : $HOST_NAME"
echo -e "\nFinish"

###########################################################
# Setting superuser
###########################################################

echo -e "\n********************************************************"
echo -e "* Create superuser"
echo -e "********************************************************"

system_add_user "$USER_NAME" "$USER_PASSWORD" "$USER_GROUPS" "$USER_SHELL"

if [ "$USER_SSHKEY" ]; then
    system_user_add_ssh_key "$USER_NAME" "$USER_SSHKEY"
fi

# Configure sshd
system_sshd_permitrootlogin "$SSHD_PERMITROOTLOGIN"
system_sshd_passwordauthentication "$SSHD_PASSWORDAUTH"

echo -e "\nFinish"

###########################################################
# Updating system software
###########################################################

echo -e "\n********************************************************"
echo -e "* Update software"
echo -e "********************************************************"
system_update

echo -e "\nFinish"

###########################################################
# Secure server with firewall
###########################################################

echo -e "\n********************************************************"
echo -e "* Firewall reject all traffic except ping and port 22 for remote admin of server"
echo -e "********************************************************"

# delete rules
iptables -F

# drop all traffic
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP

# Blocking null packets
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP

# Reject syn-flood attack
iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP

# Reject XMAS packets, which also is a recon packet
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP

# DNS lookup
iptables -A OUTPUT -p tcp --dport 53 -m state --state NEW -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -m state --state NEW -j ACCEPT

# Allow apt-get update
iptables -A INPUT -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT

# Allow loop connection
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# SSH connection for remote control of server
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

/sbin/iptables-save > /etc/iptables.up.rules

cat <<EOT >> /etc/network/if-pre-up.d/iptables
#!/bin/sh
/sbin/iptables-restore < /etc/iptables.up.rules
EOT
chmod +x /etc/network/if-pre-up.d/iptables

iptables-restore < /etc/iptables.up.rules

iptables -L

echo -e "DONE first step of secure server with firewall"

###########################################################
# Sql server
###########################################################

case "${SQL_SERVER}" in 
  postgresql)
    echo -e "\n********************************************************"
    echo -e "* Install Postgresql server"
    echo -e "********************************************************"
    aptitude -y -q install postgresql postgresql-client
    echo " DONE"
    ;;
  mariadb)
    echo -e "\n********************************************************"
    echo -e "* Install mariaDb server"
    echo -e "********************************************************"
    debconf-set-selections <<< "maria-db mysql-server/root_password password $SQL_SERVER_ROOT_PASSWORD"
    debconf-set-selections <<< "maria-db mysql-server/root_password_again password $SQL_SERVER_ROOT_PASSWORD"
    aptitude -y -q install mariadb-server mariadb-client
    # Secure Mariadb
    echo -e "\n* Secure MariaDb"
    mysql -u root -p"$SQL_SERVER_ROOT_PASSWORD" -e "UPDATE mysql.user SET Password=PASSWORD('$SQL_SERVER_ROOT_PASSWORD') WHERE User='root'"
    mysql -u root -p"$SQL_SERVER_ROOT_PASSWORD" -e "DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1')"
    mysql -u root -p"$SQL_SERVER_ROOT_PASSWORD" -e "DELETE FROM mysql.user WHERE User=''"
    mysql -u root -p"$SQL_SERVER_ROOT_PASSWORD" -e "DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%'"
    mysql -u root -p"$SQL_SERVER_ROOT_PASSWORD" -e "FLUSH PRIVILEGES"
    echo -e "DONE install of mariaDb"
    ;;
esac

###########################################################
# Postfix
###########################################################

echo -e "\n********************************************************"
echo -e "* Installing postfix and dovecot"
echo -e "********************************************************"

debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Internet Site'"
debconf-set-selections <<< "postfix postfix/mailname string $POSTFIX_HOSTMASTER"

aptitude -y -q install postfix
aptitude -y -q install dovecot-core
aptitude -y -q install dovecot-lmtpd
[[ -n "$FIREWALL_IMAP" || -n "$FIREWALL_IMAPS" ]] && aptitude -y -q install dovecot-imapd
[[ -n "$FIREWALL_POP" || -n "$FIREWALL_POPS" || -n "$FIREWALL_POPS3" ]] && aptitude -y -q install dovecot-pop3d


case "${SQL_SERVER}" in
  psql)
    aptitude -y -q install postfix-pgsql
    aptitude -y -q install dovecot-pgsql
  ;;
  mysql)
    aptitude -y -q install postfix-mysql
    aptitude -y -q install dovecot-mysql
  ;;
esac

echo -e "\n********************************************************"
echo -e "* Setting firewall"
echo -e "********************************************************"

# Allow Sendmail
[ ! -z "$FIREWALL_SENDMAIL" ] && firewall_add_rule $FIREWALL_SENDMAIL

# Allow sendmail via submission port
[ ! -z "$FIREWALL_SENDMAIL_SUBMISSION" ] && firewall_add_rule $FIREWALL_SENDMAIL_SUBMISSION

# Allow IMAP
[ ! -z "$FIREWALL_IMAP" ] && firewall_add_rule $FIREWALL_IMAP

# Allow IMAPs
[ ! -z "$FIREWALL_IMAPS" ] && firewall_add_rule $FIREWALL_IMAPS

# Allow pop
[ ! -z "$FIREWALL_POP" ] && firewall_add_rule $FIREWALL_POP

# Allow pops
[ ! -z "$FIREWALL_POPS" ] && firewall_add_rule $FIREWALL_POPS

# Allow pop3s
[ ! -z "$FIREWALL_POPS3" ] && firewall_add_rule $FIREWALL_POPS3

echo -e "\n********************************************************"
echo -e "* Making database for user authentication"
echo -e "********************************************************"

[ -z "$SQL_SERVER" ] && {
  echo "* Missing SQL server. Can't find any one installed :("
  exit 1
}

case "${SQL_SERVER}" in
  psql)
    #TODO sql script that make DB for dovecot
  ;;
  mysql)
    cat <<EOF | mysql -uroot -p$SQL_SERVER_ROOT_PASSWORD
    
    	CREATE DATABASE IF NOT EXISTS $DB_MAIL_DB_NAME;
    	GRANT SELECT ON $DB_MAIL_DB_NAME.* TO '$DB_USER'@'127.0.0.1' IDENTIFIED BY '$DB_USER_PASS';
    	FLUSH PRIVILEGES;
    	USE $DB_MAIL_DB_NAME;
    	CREATE TABLE IF NOT EXISTS virtual_domains (
    	id  INT NOT NULL AUTO_INCREMENT,
    	name VARCHAR(50) NOT NULL,
    	PRIMARY KEY (id)
    	) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    	CREATE TABLE IF NOT EXISTS virtual_users (
    	id INT NOT NULL AUTO_INCREMENT,
    	domain_id INT NOT NULL,
    	password VARCHAR(106) NOT NULL,
    	email VARCHAR(120) NOT NULL,
    	PRIMARY KEY (id),
    	UNIQUE KEY email (email),
    	FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
    	) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    	CREATE TABLE IF NOT EXISTS virtual_aliases (
    	id INT NOT NULL AUTO_INCREMENT,
    	domain_id INT NOT NULL,
    	source varchar(100) NOT NULL,
    	destination varchar(100) NOT NULL,
    	PRIMARY KEY (id),
    	FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
    	) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    	INSERT INTO servermail.virtual_domains
    	(id ,name)
    	VALUES
    	('1', '$DOMAIN'),
    	('2', 'mail.$DOMAIN');
    	INSERT INTO servermail.virtual_users
    	(id, domain_id, password , email)
    	VALUES
    	('1', '1', ENCRYPT('$PASSWORD', CONCAT('\$6\$', SUBSTRING(SHA(RAND()), -16))), '$EMAIL');
EOF
  ;;
esac
echo -e "DONE install postfix"

###########################################################
# Webserver
###########################################################

case "${WEBSERVER}" in
    nginx)
        echo -e "\n********************************************************"
        echo -e "* Installing nginx"
        echo -e "********************************************************"
        aptitude -y -q install nginx
        update-rc.d nginx defaults
    ;;&
    apache)
        echo -e "\n********************************************************"
        echo -e "* Installing apache"
        echo -e "********************************************************"
        aptitude -y -q install apache
    ;&
    nginx|apache)
        echo "open ports in firewall"
        iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
        iptables-save > /etc/iptables.up.rules
        iptables -L
        echo -e "DONE install webserver"
    ;;
    none)
        if [[$FIREWALL_WEBSERVER_NOT_CHOOSEN_OPEN_PORTS_ANYWAY == yes]]; then
            echo "open webports in firewall"
            iptables -A INPUT -p tcp --dport 8080 --state NEW,ESTABLISHED -j ACCEPT
            iptables -A INPUT -p tcp --dport 443 --state NEW,ESTABLISHED -j ACCEPT
            iptables-save > /etc/iptables.up.rules
            echo "DONE"
        fi
esac

echo -e "Script Finish :)"