Skip to content

Instantly share code, notes, and snippets.

@ppmathis
Last active March 30, 2018 08:31
Show Gist options
  • Save ppmathis/8136292 to your computer and use it in GitHub Desktop.
Save ppmathis/8136292 to your computer and use it in GitHub Desktop.

S5

S5 is an abbreviation for Snap Serv Server Stack Script. Basically it is meant for setting up a fresh Debian Wheezy x86/x64 system. You can read everything it does in config.sh, which is an example config. Remember to adjust to example configuration to some sane values.

Usage

  1. Connect to your fresh server

  2. Adjust network configuration if necessary

  3. Download s5.sh and config.sh into /root:

wget -O /root/s5.sh https://gist.github.com/NeoXiD/8136292/raw/s5.sh
wget -O /root/config.sh https://gist.github.com/NeoXiD/8136292/raw/config.sh
  1. Change owner of config.sh to root and set chmod of 600:
chown root:root /root/config.sh
chmod 600 /root/config.sh
  1. Adjust example configuration ('config.sh') to some sane values with nano, vim, vi or whatever...

  2. Execute S5:

/bin/bash /root/s5.sh
  1. Reboot when S5 finished. This step is not necessary, but recommended.

And that's it! Need help? Contact me via dev (at) snapserv (dot) net.

###
# Should be always enabled and configures the host so
# it has the given name and FQDN. The last option specifies
# if IPv4 should be preferred over IPv6, this can be especially
# useful on IPv4-only hosts.
###
S5_HOST_CONFIGURE=true
S5_HOST_NAME='bumblebee'
S5_HOST_FQDN='bumblebee.example.com'
S5_PREFER_IPV4_OVER_IPV6=true
###
# Configures your system to the given DNS servers
# if enabled. You can also specify some search domains.
###
S5_DNS_CONFIGURE=true
S5_DNS_SEARCH_DOMAINS=('example.net')
S5_DNS_SERVERS_IPV4=('8.8.8.8' '8.8.4.4')
S5_DNS_SERVERS_IPV6=('2001:4860:4860::8888' '2001:4860:4860::8844')
###
# If enabled, your software repositories will be configured.
# Afterwards, the package lists will be updated and outdated
# packages will be automatically upgraded to their newest version.
#
# Should always be enabled, otherwise ensure that your package
# lists are up2date before running S5.
###
S5_SOFTWARE_CONFIGURE=true
S5_SOFTWARE_REPOSITORIES=(
'deb http://ftp.nl.debian.org/debian/ wheezy main'
'deb-src http://ftp.nl.debian.org/debian/ wheezy main'
''
'deb http://ftp.nl.debian.org/debian/ wheezy-updates main'
'deb-src http://ftp.nl.debian.org/debian/ wheezy-updates main'
''
'deb http://security.debian.org/ wheezy/updates main'
'deb-src http://security.debian.org/ wheezy/updates main'
)
###
# If enabled, the NTP daemon gets installed and configured with
# the servers listed below. That's it!
###
S5_NTP_CONFIGURE=true
S5_NTP_SERVERS=('0.ch.pool.ntp.org' '1.ch.pool.ntp.org' '2.ch.pool.ntp.org' '3.ch.pool.ntp.org')
###
# Creates a new administrative user account. This account will be
# added to the predefined 'sudo' group. You can specify one SSH key
# which will be used to login via SSH.
#
# If enabled, this section will also LOCK YOUR ROOT ACCOUNT, so please
# be careful. The newly created account won't have any password, so
# an SSH keyfile is your only option to login.
#
# Most of the options should be self-explanatory. 'S5_USER_OVERWRITE_EXISTING_SSH_KEYS'
# specifies if the allowed SSH keys should be overwritten if they already exist.
###
S5_USER_CONFIGURE=true
S5_USER_NAME='admin' # Username
S5_USER_GROUP='admin' # Primary group
S5_USER_HOME_DIR=/home/admin # Preferred home directory
S5_USER_SSH_KEY='ssh-rsa yourkeyhere admin@bumblebee' # Replace this with your generated SSH keyfile
S5_USER_OVERWRITE_EXISTING_SSH_KEYS=false # Overwrite existing ~/.ssh/authorized_keys file
S5_USER_LOCK_ROOT_ACCOUNT=true # Lock root account
###
# If enabled, OpenSSH will be installed and configured. Some settings will be
# tweaked to ensure maximum security. Also, the server keys are getting regenerated,
# so do not wonder about any warnings after running S5.
#
# You should tweak the options listed below to your needs. Port should be self-explanatory,
# and the other settings represent 'X11Forwarding', 'PermitTunnel' and 'AllowTcpForwarding'.
# If some help is needed, you can read more about these three options in the man page
# of the OpenSSH server: http://www.openbsd.org/cgi-bin/man.cgi?query=sshd_config&sektion=5
###
S5_SSH_CONFIGURE=true
S5_SSH_PORT_NUMBER=6556
S5_SSH_X11_FORWARDING=false
S5_SSH_PERMIT_TUNNEL=false
S5_SSH_ALLOW_TCP_FORWARDING=true
###
# If this option is enabled, sudo will be installed and configured.
# Because I like to avoid passwords whenever as possible and the initial
# administrator account was created without any password, you can only use
# keyfiles to authenticate against sudo.
#
# Remember to enable agent forwarding, otherwise you will not be able
# to use sudo.
#
# Enable agent forwarding in PuTTY: Connection -> SSH -> Auth -> Allow agent forwarding
# Enable agent forwarding with SSH: ssh -A user@example.com or 'ForwardAgent yes' in ~/.ssh/config
###
S5_SUDO_CONFIGURE=true
###
# Automatically create a '~/.bash_aliases' file for the users listed in
# 'S5_BASH_AFFECTED_USERS', if 'S5_BASH_CONFIGURE' is enabled. The contents
# of the file can be specified within the heredoc tags.
#
# The example code will provide you with a nice and colored shell.
###
S5_BASH_CONFIGURE=true
S5_BASH_AFFECTED_USERS=("$S5_USER_NAME")
S5_BASH_ALIASES=$(cat <<-EOL
export PS1="\[\e[32;1m\]\u\[\e[0m\]\[\e[32m\]@\h\[\e[36m\]\w \[\e[33m\]\$ \[\e[0m\]"
EOL
)
###
# This section configures the usage of DuoUnix. DuoUnix is a
# two-factor authentication provided by DuoSecurity. By setting
# the appropriate values, DuoUnix will be automatically installed
# and configured.
#
# If 'S5_DUO_UNIX_WHITELIST_SFTP' is enabled, the SFTP subsystem
# '/usr/lib/openssh/sftp-server' gets added to /etc/duo/subsystem.whitelist.
# Every subsystem which is listed there does not require two-factor
# authentication. It could be useful to add e.g. rsync.
###
S5_DUO_UNIX_CONFIGURE=false # Should DuoUnix two-factor authentication be used?
S5_DUO_UNIX_IKEY='' # DuoUnix integration key
S5_DUO_UNIX_SKEY='' # DuoUnix secret key
S5_DUO_UNIX_HOST='' # DuoUnix host key
S5_DUO_UNIX_WHITELIST_SFTP=true # If set to true, SFTP will not require two-factor auth
###
# This section configures if a dynamic message of the day should be
# used or not. This is a script especially written for S5 which provides
# various system informations at logon.
#
# An ascii banner can also be provided which will be prepended to the
# dynamic message of the day. The example below was generated with
# http://www.network-science.de/ascii/, font: big
#
# Example dynamic MOTD can be seen here:
# http://screens.snapserv.net/ylhmu5ub3h_2013-12-26_17.54.08.png
#
# You can later on adjust the banner by editing /etc/motd-banner.
# Also you can provide maintenance informations by editing /etc/motd-maintenance.
###
S5_DYN_MOTD_CONFIGURE=true
S5_DYN_MOTD_BANNER=$(cat <<-'EOL'
_
| |
_____ ____ _ _ __ ___ _ __ | | ___
/ _ \ \/ / _` | '_ ` _ \| '_ \| |/ _ \
| __/> < (_| | | | | | | |_) | | __/
\___/_/\_\__,_|_| |_| |_| .__/|_|\___| .com
| |
|_|
EOL
)
###
# If this section is enabled, a send-only mail server based on exim4
# will be installed and configured. Remember to adjust the postmaster
# email adresses too. ('root' should always be the first postmaster address)
###
S5_MAIL_CONFIGURE=true
S5_MAIL_POSTMASTER_ADDRESSES=('root' 'postmaster@example.com')
###
# Configures if apticron should be enabled and which alert email should
# be used. Apticron is a small and lightweight tool which will send an
# email as soon as some package updates are available.
###
S5_APTICRON_CONFIGURE=true
S5_APTICRON_ALERT_MAIL='watchdog@example.com'
#!/bin/bash
# SnapServ Server StackScript (S5)
#
# Copyright (c) 2013 Pascal Mathis <dev@snapserv.net>
###
# Flags and includes
###
set -o nounset
set -o errexit
export FANCYTTY=1
. /lib/lsb/init-functions
###
# Configuration
###
CONFIG_FILE="/root/config.sh"
LOG_FILE='/root/s5.log'
###
# Config file paths
###
readonly CNF_HOSTNAME='/etc/hostname'
readonly CNF_HOSTS='/etc/hosts'
readonly CNF_INTERFACES='/etc/network/interfaces'
readonly CNF_DNS_RESOLV='/etc/resolv.conf'
readonly CNF_GAI='/etc/gai.conf'
readonly CNF_SOFTWARE_REPOSITORIES='/etc/apt/sources.list'
readonly CNF_NTP='/etc/ntp.conf'
readonly CNF_OPENSSH_SERVER='/etc/ssh/sshd_config'
readonly CNF_DUO_UNIX='/etc/duo/login_duo.conf'
readonly CNF_MAILNAME='/etc/mailname'
readonly CNF_APTICRON='/etc/apticron/apticron.conf'
###
# Download URLs
###
readonly URL_PAM_SSH_AGENT_AUTH='http://garr.dl.sourceforge.net/project/pamsshagentauth/pam_ssh_agent_auth/v0.9.5/pam_ssh_agent_auth-0.9.5.tar.bz2'
readonly URL_DUO_UNIX='https://dl.duosecurity.com/duo_unix-latest.tar.gz'
###
# Error codes
###
readonly ERR_NO_CONFIG_FILE=0
readonly ERR_MISSING_CONFIG_KEY=1
readonly ERR_MUST_RUN_AS_ROOT=2
readonly ERR_USER_DOES_NOT_EXIST=3
readonly ERR_INVALID_CONFIG_FILE=4
readonly ERR_MISSING_PAM_SECURITY_FOLDER=5
###
# Helper functions
###
require_config() {
local CONFIG_KEY
CONFIG_KEY=${1}
if [[ -z ${!CONFIG_KEY:-} ]]; then
step_echo "Missing configuration key: ${CONFIG_KEY}"
exit ${ERR_MISSING_CONFIG_KEY}
fi
}
begin_step() {
local SECTION_NAME
local STEP_DESCRIPTION
SECTION_NAME=${1}
STEP_DESCRIPTION=${2}
log_action_begin_msg "[${SECTION_NAME}] ${STEP_DESCRIPTION}"
echo "--------------- [${SECTION_NAME}] ${STEP_DESCRIPTION} ---------------" >>${LOG_FILE}
trap step_trap ERR EXIT
}
end_step() {
trap - ERR EXIT
log_action_end_msg 0
}
step_echo() {
echo "${@}"
}
# We need to declare 'ERROR_CODE' here, because the local statement
# already resets the $? variable.
ERROR_CODE=0
step_trap() {
ERROR_CODE=${?}
trap - ERR EXIT
log_action_end_msg ${ERROR_CODE}
}
###
# Clear logfile
###
echo -n '' >${LOG_FILE}
###
# Check for configuration file and load if available
###
if [[ ! -z ${CONFIG_FILE:-} ]] && [[ -f ${CONFIG_FILE} ]]; then
# Check permissions of configuration file
FILE_OWNER=$(stat -c '%u' ${CONFIG_FILE})
FILE_CHMOD=$(stat -c '%a' ${CONFIG_FILE})
if [[ ${FILE_CHMOD} != '600' ]] || [[ ${FILE_OWNER} != '0' ]]; then
echo "For security reasons, the configuration file needs to belong to root with chmod 600." 1>&2
exit ${ERR_INVALID_CONFIG_FILE}
else
. ${CONFIG_FILE}
fi
else
echo "Configuration file '${CONFIG_FILE}' was not found." 1>&2
exit ${ERR_NO_CONFIG_FILE}
fi
###
# Check if script runs as root
###
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root." 1>&2
exit ${ERR_MUST_RUN_AS_ROOT}
fi
###
# [Network] Configure hostname and hosts file
###
if [[ ! -z ${S5_HOST_CONFIGURE:-} ]] && ${S5_HOST_CONFIGURE}; then
begin_step 'Network' 'Configuring host'
require_config 'S5_HOST_NAME'
require_config 'S5_HOST_FQDN'
require_config 'S5_PREFER_IPV4_OVER_IPV6'
# Change hostname
echo "${S5_HOST_FQDN}" >${CNF_HOSTNAME}
hostname "${S5_HOST_FQDN}"
# Adjust hosts file
HOST_IP_ADDRESS=$(hostname -I)
cat >${CNF_HOSTS} <<-EOL
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
${HOST_IP_ADDRESS} ${S5_HOST_FQDN} ${S5_HOST_NAME}
EOL
# Change precedence of getaddrinfo()
if ${S5_PREFER_IPV4_OVER_IPV6}; then
sed -i -e 's/^#precedence ::ffff:0:0\/96 100/precedence ::ffff:0:0\/96 100/' ${CNF_GAI}
else
sed -i -e 's/^precedence ::ffff:0:0\/96 100/#precedence ::ffff:0:0\/96 100/' ${CNF_GAI}
fi
end_step
fi
###
# [Network] DNS resolvers
###
if [[ ! -z ${S5_DNS_CONFIGURE:-} ]] && ${S5_DNS_CONFIGURE}; then
begin_step 'Network' 'Configuring DNS resolvers'
require_config 'S5_DNS_SEARCH_DOMAINS'
require_config 'S5_DNS_SERVERS_IPV4'
require_config 'S5_DNS_SERVERS_IPV6'
# Strip existing DNS resolvers from interfaces-config
sed -i -e '/^dns-nameservers/ d' ${CNF_INTERFACES}
# Write new configuration file
echo -n '' >${CNF_DNS_RESOLV}
for SEARCH_DOMAIN in "${S5_DNS_SEARCH_DOMAINS[@]}"; do
echo "search ${SEARCH_DOMAIN}" >>${CNF_DNS_RESOLV}
done
for SERVER_IPV4 in "${S5_DNS_SERVERS_IPV4[@]}"; do
echo "nameserver ${SERVER_IPV4}" >>${CNF_DNS_RESOLV}
done
for SERVER_IPV6 in "${S5_DNS_SERVERS_IPV6[@]}"; do
echo "nameserver ${SERVER_IPV6}" >>${CNF_DNS_RESOLV}
done
end_step
fi
###
# [Software] Update repositoriers
###
if [[ ! -z ${S5_SOFTWARE_CONFIGURE:-} ]] && ${S5_SOFTWARE_CONFIGURE}; then
begin_step 'Software' 'Updating repositories and installed packages'
# Modify repositories
echo -n '' >${CNF_SOFTWARE_REPOSITORIES}
for REPOSITORY in "${S5_SOFTWARE_REPOSITORIES[@]}"; do
echo "${REPOSITORY}" >>${CNF_SOFTWARE_REPOSITORIES}
done
# Update package lists and installed packaes
apt-get -q -y update 2>&1 &>>${LOG_FILE}
apt-get -q -y upgrade 2>&1 &>>${LOG_FILE}
end_step
fi
###
# [NTP] Install and configure NTPd
###
if [[ ! -z ${S5_NTP_CONFIGURE:-} ]] && ${S5_NTP_CONFIGURE}; then
begin_step 'Software' 'Installing and configuring NTP daemon'
require_config 'S5_NTP_SERVERS'
# Install ntp daemon from software repositories
apt-get -q -y install ntp &>>${LOG_FILE}
# Write first part of configuration
cat >${CNF_NTP} <<-EOL
driftfile /var/lib/ntp/ntp.drift
statistics loopstats peerstats clockstats
filegen loopstats file loopstats type day enable
filegen peerstats file peerstats type day enable
filegen clockstats file clockstats type day enable
EOL
# Write NTP servers into NTP configuration
for NTP_SERVER in "${S5_NTP_SERVERS[@]}"; do
echo "server ${NTP_SERVER}" >>${CNF_NTP}
done
# Write second part of configuration
cat >>${CNF_NTP} <<-EOL
restrict -4 default kod notrap nomodify nopeer noquery
restrict -6 default kod notrap nomodify nopeer noquery
restrict 127.0.0.1
restrict ::1
EOL
# Restart NTP daemon
service ntp restart >>${LOG_FILE}
end_step
fi
###
# [User] Lock root account, create new account and assign SSH keys
###
if [[ ! -z ${S5_USER_CONFIGURE:-} ]] && ${S5_USER_CONFIGURE}; then
begin_step 'User' 'Setting up initial user configuration'
require_config 'S5_USER_NAME'
require_config 'S5_USER_GROUP'
require_config 'S5_USER_HOME_DIR'
require_config 'S5_USER_SSH_KEY'
require_config 'S5_USER_OVERWRITE_EXISTING_SSH_KEYS'
require_config 'S5_USER_LOCK_ROOT_ACCOUNT'
# Create user if nonexistant
if ! id -u ${S5_USER_NAME} &>/dev/null; then
groupadd ${S5_USER_GROUP} >>${LOG_FILE}
useradd -g ${S5_USER_GROUP} -m -d ${S5_USER_HOME_DIR} -s /bin/bash ${S5_USER_NAME} >>${LOG_FILE}
usermod --lock ${S5_USER_NAME} >>${LOG_FILE}
passwd --delete ${S5_USER_NAME} >>${LOG_FILE}
else
echo "User ${S5_USER_NAME} already exists and therefore won't be created." >>${LOG_FILE}
fi
# Copy SSH keys into new user
if [[ ! -f "${S5_USER_HOME_DIR}/.ssh/authorized_keys" ]] || ${S5_USER_OVERWRITE_EXISTING_SSH_KEYS}; then
mkdir -p "${S5_USER_HOME_DIR}/.ssh"
touch "${S5_USER_HOME_DIR}/.ssh/authorized_keys"
chown -R "${S5_USER_NAME}:${S5_USER_GROUP}" "${S5_USER_HOME_DIR}/.ssh/"
chmod 700 "${S5_USER_HOME_DIR}/.ssh/"
chmod 600 "${S5_USER_HOME_DIR}/.ssh/authorized_keys"
echo "${S5_USER_SSH_KEY}" >"${S5_USER_HOME_DIR}/.ssh/authorized_keys"
else
echo "SSH keys for user ${S5_USER_NAME} already exist. For safety reasons, they won't be overwritten unless specified with 'S5_USER_OVERWRITE_EXISTING_SSH_KEYS'." >>${LOG_FILE}
fi
# Lock root account completely
if ${S5_USER_LOCK_ROOT_ACCOUNT}; then
usermod --lock root >>${LOG_FILE}
passwd --delete root >>${LOG_FILE}
fi
end_step
fi
###
# [SSH] Install and confiĝure OpenSSH server
###
if [[ ! -z ${S5_SSH_CONFIGURE:-} ]] && ${S5_SSH_CONFIGURE}; then
begin_step 'Software' 'Installing and configuring OpenSSH server'
require_config 'S5_SSH_PORT_NUMBER'
require_config 'S5_SSH_PERMIT_TUNNEL'
require_config 'S5_SSH_ALLOW_TCP_FORWARDING'
require_config 'S5_SSH_X11_FORWARDING'
# Install OpenSSH server from software repositories
apt-get -q -y install openssh-server &>>${LOG_FILE}
# Configure OpenSSH server
cat >${CNF_OPENSSH_SERVER} <<-EOL
# Generic options
Port ${S5_SSH_PORT_NUMBER}
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
UsePrivilegeSeparation yes
PrintMotd no
PrintLastLog yes
Subsystem sftp /usr/lib/openssh/sftp-server
# Logging options
SyslogFacility AUTH
LogLevel INFO
# Security options
KeyRegenerationInterval 300
ServerKeyBits 4096
LoginGraceTime 120
StrictModes yes
PermitRootLogin no
PermitEmptyPasswords no
PasswordAuthentication no
IgnoreRhosts yes
RhostsRSAAuthentication no
HostbasedAuthentication no
KerberosAuthentication no
AllowUsers ${S5_USER_NAME}
# Tunnel policies
EOL
# Add custom configuration
if ${S5_SSH_X11_FORWARDING}; then
echo 'X11Forwarding yes' >>${CNF_OPENSSH_SERVER}
else
echo 'X11Forwarding no' >> ${CNF_OPENSSH_SERVER}
fi
if ${S5_SSH_ALLOW_TCP_FORWARDING}; then
echo 'AllowTcpForwarding yes' >>${CNF_OPENSSH_SERVER}
else
echo 'AllowTcpForwarding no' >> ${CNF_OPENSSH_SERVER}
fi
if ${S5_SSH_PERMIT_TUNNEL}; then
echo 'PermitTunnel yes' >>${CNF_OPENSSH_SERVER}
else
echo 'PermitTunnel no' >> ${CNF_OPENSSH_SERVER}
fi
# Regenerate server keys
rm /etc/ssh/ssh_host_*
dpkg-reconfigure openssh-server &>>${LOG_FILE}
# Restart OpenSSH daemon
service ssh restart >>${LOG_FILE}
end_step
fi
###
# [sudo] Setup sudo
###
if [[ ! -z ${S5_SUDO_CONFIGURE:-} ]] && ${S5_SUDO_CONFIGURE}; then
begin_step 'Software' 'Installing and configuring sudo'
# Install sudo and required build dependencies from software repositories
apt-get -q -y install sudo &>>${LOG_FILE}
apt-get -q -y install build-essential libpam-dev libssl-dev &>>${LOG_FILE}
# Update sudoers file
cat >/tmp/sudoers.new <<-EOL
Defaults env_reset
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Defaults env_keep+=SSH_AUTH_SOCK
Defaults passwd_tries=1
# User privilege specification
root ALL=(ALL:ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
EOL
EDITOR='cp /tmp/sudoers.new' visudo
# Add user account to sudo group
usermod -a -G sudo ${S5_USER_NAME}
# Compile, make and install pam_ssh_agent_auth
pushd /usr/local/src >>${LOG_FILE}
wget --quiet -O 'pam_ssh_agent_auth.tar.bz2' ${URL_PAM_SSH_AGENT_AUTH} >>${LOG_FILE}
tar xf 'pam_ssh_agent_auth.tar.bz2' >>${LOG_FILE}
pushd /usr/local/src/pam_ssh_agent_auth* >>${LOG_FILE}
./configure 2>&1 >>${LOG_FILE}
make 2>&1 &>>${LOG_FILE}
make install 2>&1 &>>${LOG_FILE}
if [[ -d '/lib/x86_64-linux-gnu/security' ]]; then
PAM_SECURITY_FOLDER='/lib/x86_64-linux-gnu/security'
elif [[ -d '/lib/i386-linux-gnu/security' ]]; then
PAM_SECURITY_FOLDER='/lib/i386-linux-gnu/security'
elif [[ -d '/lib/i686-linux-gnu/security' ]]; then
PAM_SECURITY_FOLDER='/lib/i686-linux-gnu/security'
else
echo "Could not find PAM security library folder." 2>&1
exit ${ERR_MISSING_PAM_SECURITY_FOLDER}
fi
rm -f "${PAM_SECURITY_FOLDER}/pam_ssh_agent_auth.so"
ln -s /usr/local/libexec/pam_ssh_agent_auth.so ${PAM_SECURITY_FOLDER}
popd >>${LOG_FILE}
popd >>${LOG_FILE}
# Adjust sudo pam configuration
cat >/etc/pam.d/sudo <<-EOL
#%PAM-1.0
# @include common-auth
auth sufficient pam_ssh_agent_auth.so file=%h/.ssh/authorized_keys
auth required pam_deny.so
@include common-account
@include common-session-noninteractive
EOL
end_step
fi
###
# [bash] Setup bash aliases
###
if [[ ! -z ${S5_BASH_CONFIGURE:-} ]] && ${S5_BASH_CONFIGURE}; then
begin_step 'Software' 'Configuring bash aliases'
require_config 'S5_BASH_ALIASES'
require_config 'S5_BASH_AFFECTED_USERS'
for AFFECTED_USER in "${S5_BASH_AFFECTED_USERS[@]}"; do
# Check if user exists
if ! id -u ${AFFECTED_USER} &>/dev/null; then
echo "User ${AFFECTED_USER} does not exist." 2>&1
exit ${ERR_USER_DOES_NOT_EXIST}
fi
HOMEDIR=$(eval "echo ~${AFFECTED_USER}")
echo "${S5_BASH_ALIASES}" >"${HOMEDIR}/.bash_aliases"
done
end_step
fi
###
# [DuoUnix] Setup two-factor authentication
###
if [[ ! -z ${S5_DUO_UNIX_CONFIGURE:-} ]] && ${S5_DUO_UNIX_CONFIGURE}; then
begin_step 'Security' 'Setting up DuoUnix two-factor authentication'
require_config 'S5_DUO_UNIX_IKEY'
require_config 'S5_DUO_UNIX_SKEY'
require_config 'S5_DUO_UNIX_HOST'
# Compile, make and install duo_unix
pushd /usr/local/src >>${LOG_FILE}
wget --quiet -O 'duo_unix.tar.gz' ${URL_DUO_UNIX} >>${LOG_FILE}
tar xf 'duo_unix.tar.gz' >>${LOG_FILE}
pushd /usr/local/src/duo_unix* >>${LOG_FILE}
./configure --prefix=/usr 2>&1 >>${LOG_FILE}
make 2>&1 &>>${LOG_FILE}
make install 2>&1 &>>${LOG_FILE}
popd >>${LOG_FILE}
popd >>${LOG_FILE}
# Configure DuoUnix
cat >${CNF_DUO_UNIX} <<-EOL
[duo]
ikey = ${S5_DUO_UNIX_IKEY}
skey = ${S5_DUO_UNIX_SKEY}
host = ${S5_DUO_UNIX_HOST}
pushinfo = yes
autopush = no
prompts = 1
motd = no
EOL
# Write DuoUnix wrapper script
cat >/usr/local/bin/duoauth <<-'EOL'
#!/bin/bash
# Immediately kill connection if user tries to abort this script
trap jail INT
jail() {
kill -9 ${PPID}
exit 1
}
# Handle connection based on subsystem
if [ -z "${SSH_ORIGINAL_COMMAND}" ]; then
# SSH connection without any subsystem
/usr/sbin/login_duo "${SHELL} -l"
exit 0
else
# SSH connection with specified subsystem e.g. SFTP, rsync...
if [[ -r /etc/duo/subsystem.whitelist ]] && grep -Fxq "${SSH_ORIGINAL_COMMAND}" /etc/duo/subsystem.whitelist; then
${SHELL} -c '${SSH_ORIGINAL_COMMAND}'
exit 0
else
/usr/sbin/login_duo "${SHELL} -c '${SSH_ORIGINAL_COMMAND}'"
exit 0
fi
fi
# Default action is to deny connection
kill -9 ${PPID}
exit 1
EOL
chmod 755 /usr/local/bin/duoauth
# Create subsystem whitelist
if ${S5_DUO_UNIX_WHITELIST_SFTP}; then
cat >/etc/duo/subsystem.whitelist <<-EOL
/usr/lib/openssh/sftp-server
EOL
else
echo -n '' >/etc/duo/subsystem.whitelist
fi
chmod 644 /etc/duo/subsystem.whitelist
# Inject DuoUnix into SSH configuration
if [[ ! -z ${S5_SSH_CONFIGURE:-} ]] && ${S5_SSH_CONFIGURE}; then
cat >>${CNF_OPENSSH_SERVER} <<-EOL
# DuoUnix integration
ForceCommand /usr/local/bin/duoauth
EOL
service ssh restart >>${LOG_FILE}
fi
end_step
fi
###
# [DynMOTD] Dynamic message of the day
###
if [[ ! -z ${S5_DYN_MOTD_CONFIGURE:-} ]] && ${S5_DYN_MOTD_CONFIGURE}; then
begin_step 'Software' 'Setting up dynamic message of the day'
require_config 'S5_DYN_MOTD_BANNER'
# Write DynMOTD script
cat >/etc/profile.d/dynmotd.sh <<-'EOL'
#!/bin/bash
HOSTNAME=$(hostname -f)
IP_ADDRESS=$(hostname -I | tr -d ' ')
KERNEL_VERSION=$(uname -r)
UPTIME=$(uptime | sed -n 's/.*up \([^,]*\), \([0-9:]*\), .*/\1 \2 hours/p')
if [[ ! -n ${UPTIME} ]]; then
UPTIME=$(uptime | sed -n 's/.*up \([^,]*\), .*/\1 hours/p')
fi
UPTIME=$(echo "${UPTIME}" | sed 's/^ *//g')
CPU_MODEL=$(grep -m 1 'model name' /proc/cpuinfo | cut -d: -f2 | sed 's/^ *//g' | sed -n 's/ \+/ /gp')
PROCESS_COUNT=$(ps aux | tail -n +2 | wc -l)
LOAD=$(cat /proc/loadavg | cut -d ' ' -f 1,2,3)
MEM_TOTAL=$(free -t -m | grep "Total" | awk '{print $2}')
MEM_USED=$(free -t -m | grep "Total" | awk '{print $3}')
USERNAME=$(whoami)
PRIMARY_GROUP=$(id -gn)
USER_SESSION_COUNT=$(who | grep ${USERNAME} | wc -l)
if [[ $(id -Gn) == *sudo* ]]; then
USERTYPE='Administrator'
else
USERTYPE='User'
fi
BANNER=$(cat /etc/motd-banner 2>/dev/null)
MAINTENANCE_INFO=$(cat /etc/motd-maintenance 2>/dev/null)
if [[ ! -n ${MAINTENANCE_INFO} ]]; then
MAINTENANCE_INFO='Nothing to report.'
fi
echo -e "\033[1;32m${BANNER}
\033[0;35m++++++++++++++++++++: \033[0;37mSystem Data\033[0;35m :++++++++++++++++++++++
\033[0;35m+ \033[0;37mHostname \033[0;35m= \033[1;32m${HOSTNAME}
\033[0;35m+ \033[0;37mAddress \033[0;35m= \033[1;32m${IP_ADDRESS}
\033[0;35m+ \033[0;37mKernel \033[0;35m= \033[1;32m${KERNEL_VERSION}
\033[0;35m+ \033[0;37mUptime \033[0;35m= \033[1;32m${UPTIME}
\033[0;35m+ \033[0;37mProcesses \033[0;35m= \033[1;32m${PROCESS_COUNT} running processes
\033[0;35m+ \033[0;37mAvg. Load \033[0;35m= \033[1;32m${LOAD}
\033[0;35m+ \033[0;37mCPU \033[0;35m= \033[1;32m${CPU_MODEL}
\033[0;35m+ \033[0;37mMemory \033[0;35m= \033[1;32m${MEM_USED} MiB of ${MEM_TOTAL} MiB
\033[0;35m+++++++++++++++++++++: \033[0;37mUser Data\033[0;35m :+++++++++++++++++++++++
\033[0;35m+ \033[0;37mType \033[0;35m= \033[1;32m${USERTYPE}
\033[0;35m+ \033[0;37mUsername \033[0;35m= \033[1;32m${USERNAME}
\033[0;35m+ \033[0;37mGroup \033[0;35m= \033[1;32m${PRIMARY_GROUP} (primary)
\033[0;35m+ \033[0;37mSessions \033[0;35m= \033[1;32m${USER_SESSION_COUNT} sessions active
\033[0;35m++++++++++++++: \033[0;37mMaintenance Information\033[0;35m :++++++++++++++++
\033[0;35m+ \033[0;37m${MAINTENANCE_INFO}
\033[0;35m+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\033[0m"
EOL
chmod 644 /etc/profile.d/dynmotd.sh
# Create banner and maintenance info files
cat >/etc/motd-banner <<-EOL
${S5_DYN_MOTD_BANNER}
EOL
touch /etc/motd-maintenance
chmod 644 /etc/motd-banner
chmod 644 /etc/motd-maintenance
end_step
fi
###
# [Mail] Install and configure exim4 in send-only mode
###
if [[ ! -z ${S5_MAIL_CONFIGURE:-} ]] && ${S5_MAIL_CONFIGURE}; then
begin_step 'Mail' 'Installing and configuring send-only mail server'
require_config 'S5_HOST_NAME'
require_config 'S5_HOST_FQDN'
require_config 'S5_MAIL_POSTMASTER_ADDRESSES'
# Purge existing exim4 installation
apt-get -q -y purge exim4-config &>>${LOG_FILE}
# Automate exim4 installation (non-interactive)
echo -n "${S5_HOST_FQDN}" >${CNF_MAILNAME}
debconf-set-selections <<-EOL
exim4-config exim4/mailname string ${S5_HOST_FQDN}
exim4-config exim4/dc_localdelivery select Maildir format in home directory
exim4-config exim4/dc_local_interfaces string 127.0.0.1 ; ::1
exim4-config exim4/dc_minimaldns boolean false
exim4-config exim4/dc_other_hostnames string ${S5_HOST_FQDN}; ${S5_HOST_NAME}; localhost.localdomain; localhost
exim4-config exim4/dc_eximconfig_configtype select internet site; mail is sent and received directly using SMTP
exim4-config exim4/no_config boolean true
exim4-config exim4/dc_postmaster string ${S5_MAIL_POSTMASTER_ADDRESSES[@]}
exim4-config exim4/use_split_config boolean false
exim4-config exim4/dc_relay_nets string
exim4-config exim4/dc_relay_domains string
EOL
# Install exim4 from software repositories
apt-get -q -y install exim4 &>>${LOG_FILE}
end_step
fi
###
# [Software] Install and configure apticron
###
if [[ ! -z ${S5_APTICRON_CONFIGURE:-} ]] && ${S5_APTICRON_CONFIGURE}; then
begin_step 'Software' 'Installing and configuring apticron'
require_config 'S5_APTICRON_ALERT_MAIL'
# Install apticron from software repositories
apt-get -q -y install apticron &>>${LOG_FILE}
# Configure apticron
cat >${CNF_APTICRON} <<-EOL
EMAIL="${S5_APTICRON_ALERT_MAIL}"
IPADDRESSNUM="1"
EOL
end_step
fi
###
# S5 has finished
###
log_success_msg 'SnapServ Server StackScript (S5) was successfully executed.'
log_warning_msg 'It seems like S5 has finished. Please reboot this host to apply all changes.'
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment