Skip to content

Instantly share code, notes, and snippets.

@cballou
Created July 19, 2011 14:09
Show Gist options
  • Save cballou/1092473 to your computer and use it in GitHub Desktop.
Save cballou/1092473 to your computer and use it in GitHub Desktop.
An advanced Linode StackScript for deploying a CentOs 64bit LEMP Stack with a ton of extras and configuration: MySQL, Suhosin, Memcached, Monit, Supervisord, Gearman, Beanstalk, Fail2Ban, IPTables Firewall, SSH
#!/bin/bash
#
# MYSQL CONFIG
# ============
# <UDF name="db_password" Label="Choose a MySQL Root Password" />
# <UDF name="db_name" Label="MySQL - Database Name" default="" example="Optionally create this database." />
# <UDF name="db_user" Label="MySQL - Username" default="" example="Optionally create this user." />
# <UDF name="db_user_password" Label="MySQL - Password" default="" example="The user password." />
#
# OPTIONAL LIBRARIES TO INSTALL
# =============================
# <UDF name="suhosin_enabled" label="Would you like to install Suhosin?" oneOf="yes,no" default="yes" example="Suhosin is an advanced protection system for PHP installations." />
# <UDF name="memcached_enabled" label="Would you like to install memcached (pecl-memcache)?" oneOf="yes,no" default="no" example="APC is already enabled so the choice is yours. You can use memcached with gearman for persistent queues as opposed to libdrizzle." />
# <UDF name="monit_enabled" label="Would you like to install monit?" oneOf="yes,no" default="yes" example="Monit can start a process if it does not run, restart a process if it does not respond and stop a process if it uses too much resources." />
# <UDF name="supervisord_enabled" label="Would you like to install supervisord?" oneOf="yes,no" default="yes" example="is a client/server system that allows its users to monitor and control a number of processes (daemons) on UNIX-like operating systems." />
# <UDF name="gearman_enabled" label="Would you like to install gearman?" oneOf="yes,no" default="yes" example="Gearman provides a generic application framework to farm out work to other machines or processes that are better suited to do the work." />
# <UDF name="beanstalk_enabled" label="Would you like to install beanstalk?" oneOf="yes,no" default="yes" example="Beanstalk is a simple, fast work queue originally designed for reducing the latency of page views in high-volume web applications by running time-consuming tasks asynchronously." />
# <UDF name="fail2ban_enabled" label="Would you like to install fail2ban?" oneOf="yes,no" default="yes" example="Fail2ban scans log files like /var/log/pwdfail or /var/log/apache/error_log and bans IP that makes too many password failures." />
#
# LIBDRIZZLE MYSQL CONFIG
# =======================
# <UDF name="drizzle_enabled" label="Would you like to install libdrizzle as gearman's persistent queue store?" oneOf="yes,no" default="yes" example="Skip this section if you aren't using gearman." />
# <UDF name="drizzle_db_name" label="Name of your database (we suggest gearman)" default="gearman" />
# <UDF name="drizzle_db_table" label="Name of your database table (we suggest gearman_queue)" default="gearman_queue" />
# <UDF name="drizzle_db_user" label="Name of your database user (we suggest gearman)" default="gearman" />
# <UDF name="drizzle_db_user_password" label="Password of your database user" default="" />
#
# IPTABLES FIREWALL CONFIG
# ========================
# <UDF name="allow" label="Allowed services" example="Punch holes in the firewall for these services. SSH is already open on port 22 (see Restrict SSH)." default="" manyOf="FTP Server: TCP 21,Telnet: TCP 23,SMTP: TCP 25,DNS Server: TCP/UDP 53,Web Server: TCP 80,POP3 Mail Service: TCP 110,NTP Service: UDP 123,IMAP Mail Service: TCP 143,SSL Web Server: TCP 443,Mail Submission: TCP 587,SSL IMAP Server: TCP 993,OpenVPN Server: UDP 1194,IRC Server: TCP 6667" />
# <UDF name="extraT" label="Extra TCP holes (SSH is already handled for you)" example="Extra holes in the firewall for TCP. Understands service names ('kerberos') and port numbers ('31337'), separate by spaces." default="" />
# <UDF name="extraU" label="Extra UDP holes" example="Extra holes in the firewall for UDP. Understands service names ('daytime') and port numbers ('1094'), separate by spaces." default="" />
# <UDF name="icmplevel" label="ICMP paranoia level" example="Rules for ICMP. You should leave this at the default to be a good net citizen." oneOf="Well-behaved,Only allow pings,Ignore all ICMP" default="None" />
# <UDF name="loglevel" label="Logging level" example="How much to log. This can generate a lot of output." oneOf="Nothing,Some stuff,Everything" default="Nothing" />
#
# SSH SECURITY CONFIG (via Donald von Stufft <donald.stufft@gmail.com>)
# ===================
# <udf name="user_name" label="SSH User Name" />
# <udf name="user_password" label="SSH User Password" />
# <udf name="user_sshkey" label="Public Key for User" default="" />
#
# <udf name="sshrange" label="Restrict SSH" example="Will restrict SSH access to the given CIDR range. Leave empty for no restrictions." default="0/0" />
# <udf name="sshd_port" label="SSH Port" default="22" />
# <udf name="sshd_protocol" label="SSH Protocol" oneOf="1,2,1 and 2" default="2" />
# <udf name="sshd_permitroot" label="SSH Permit Root Login" oneof="No,Yes" default="No" />
# <udf name="sshd_passwordauth" label="SSH Password Authentication" oneOf="No,Yes" default="No" />
# <udf name="sshd_group" label="SSH Allowed Groups" default="sshusers" example="List of groups seperated by spaces" />
#
# <udf name="sudo_usergroup" label="Usergroup to use for Sudo Accounts" default="wheel" />
# <udf name="sudo_passwordless" label="Passwordless Sudo" oneof="Require Password,Do Not Require Password", default="Require Password" />
###########################################################
# include the StackScript Bash Library for RH Derivatives #
###########################################################
source <ssinclude StackScriptID="154">
####################
# useful functions #
####################
function mysql_create_table {
# $1 - the mysql root password
# $2 - the table create statement
if [ ! -n "$1" ]; then
echo "mysql_grant_user_table() requires the root pass as its first argument"
return 1;
fi
if [ ! -n "$2" ]; then
echo "mysql_grant_user_table() requires a creation statement as the argument"
fi
echo "$2" | mysql -u root -p"$1"
}
function mysql_grant_user_table {
# $1 - the mysql root password
# $2 - the username to grant table access
# $3 - the database
# $4 - the table
if [ ! -n "$1" ]; then
echo "mysql_grant_user_table() requires the root pass as its first argument"
return 1;
fi
if [ ! -n "$2" ]; then
echo "mysql_grant_user_table() requires username as the second argument"
return 1;
fi
if [ ! -n "$3" ]; then
echo "mysql_grant_user_table() requires a database as the third argument"
return 1;
fi
if [ ! -n "$4" ]; then
echo "mysql_grant_user_table() requires a table as the fourth argument"
fi
echo "GRANT ALL PRIVILEGES ON $3.$4 TO '$2'@'localhost';" | mysql -u root -p"$1"
echo "FLUSH PRIVILEGES;" | mysql -u root -p"$1"
}
function overwrite_sysctl_config {
cat <<- _EOF_
# Controls IP packet forwarding
net.ipv4.ip_forward = 0
# Do not accept source routing
net.ipv4.conf.default.accept_source_route = 0
# Controls the System Request debugging functionality of the kernel
kernel.sysrq = 0
# Controls whether core dumps will append the PID to the core filename
# Useful for debugging multi-threaded applications
kernel.core_uses_pid = 1
# Controls the use of TCP syncookies
net.ipv4.tcp_syncookies = 1
# Controls the maximum size of a message, in bytes
kernel.msgmnb = 65536
# Controls the default maxmimum size of a message queue
kernel.msgmax = 65536
# Controls the maximum shared segment size, in bytes
kernel.shmmax = 68719476736
# Controls the maximum number of shared memory segments, in pages
kernel.shmall = 4294967296
####################################
# CUSTOM OPTIMIZATIONS STACKSCRIPT #
####################################
# Disables IP source routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.lo.accept_source_route = 0
net.ipv4.conf.eth0.accept_source_route = 0
# Enable IP spoofing protection, turn on source route verification
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.lo.rp_filter = 1
net.ipv4.conf.eth0.rp_filter = 1
# Disable ICMP Redirect Acceptance
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.lo.accept_redirects = 0
net.ipv4.conf.eth0.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
# Enable Log Spoofed Packets, Source Routed Packets, Redirect Packets
net.ipv4.conf.default.log_martians = 0
net.ipv4.conf.all.log_martians = 0
net.ipv4.conf.lo.log_martians = 0
net.ipv4.conf.eth0.log_martians = 0
# Decrease the time default value for tcp_fin_timeout connection
net.ipv4.tcp_fin_timeout = 15
# Decrease the time default value for tcp_keepalive_time connection
net.ipv4.tcp_keepalive_time = 1800
# Turn off the tcp_window_scaling
net.ipv4.tcp_window_scaling = 0
# Turn off the tcp_sack
net.ipv4.tcp_sack = 0
# Turn off the tcp_timestamps
net.ipv4.tcp_timestamps = 0
# Enable ignoring broadcasts request
net.ipv4.icmp_echo_ignore_broadcasts = 1
# Enable bad error message Protection
net.ipv4.icmp_ignore_bogus_error_responses = 1
# Increases the size of the socket queue (effectively, q0).
net.ipv4.tcp_max_syn_backlog = 1024
# Increase the tcp-time-wait buckets pool size
net.ipv4.tcp_max_tw_buckets = 1440000
# Allowed local port range
net.ipv4.ip_local_port_range = 1024 65000
# bump up the memory
net.core.rmem_default = 256960
net.core.rmem_max = 256960
net.core.wmem_default = 256960
net.core.wmem_max = 256960
# Linode Xen Virtualization specific
vm.swappiness = 25
_EOF_
}
function overwrite_gearman_sysconfig {
cat <<- _EOF_
#OPTIONS="-q libdrizzle --libdrizzle-host=127.0.0.1 --libdrizzle-user=${DRIZZLE_DB_USER} --libdrizzle-password=${DRIZZLE_DB_PASSWORD} --libdrizzle-db=${DRIZZLE_DB_NAME} --libdrizzle-table=gearman_queue --libdrizzle-mysql"
_EOF_
}
function lemp_install_drizzle_repo {
cat <<- _EOF_
[drizzle]
name=drizzle
baseurl=http://5dollarwhitebox.org/repos/drizzle/dev/Redhat/5/$basearch/
enabled=1
gpgcheck=0
[drizzle-src]
name=drizzle-src
baseurl=http://5dollarwhitebox.org/repos/drizzle/dev/Redhat/5/SRPMS
enabled=1
gpgcheck=0
_EOF_
}
#################################
# system update #
#################################
function lemp_system_update {
echo "" >> /var/log/stackscript.log
echo "Ensuring YUM priorities are in check..." >> /var/log/stackscript.log
# enable yum priorities to avoid rpm conflicts
yum -y install yum-priorities
echo "Adding EPEL and IUS repos to yum..." >> /var/log/stackscript.log
# install latest EPEL and IUS repos
# http://rob.olmos.name/2010/08/centos-5-5-php-5-3-3-php-fpm-nginx-rpms/
rpm -Uvh http://dl.iuscommunity.org/pub/ius/stable/Redhat/5/x86_64/epel-release-1-1.ius.el5.noarch.rpm
rpm -Uvh http://dl.iuscommunity.org/pub/ius/stable/Redhat/5/x86_64/ius-release-1.0-6.ius.el5.noarch.rpm
echo "Altering /etc/yum.repos.d/ius.repo params..." >> /var/log/stackscript.log
# need to force IUS repo to use CentOS 5.5
# comment out the following mirrorlist
# mirrorlist=http://dmirr.iuscommunity.org/mirrorlist?repo=ius-el5&arch=$basearch
sed -i 's/mirrorlist=http:\/\/dmirr.iuscommunity.org\/mirrorlist?repo=ius-el5\&arch=\$basearch/#mirrorlist=http:\/\/dmirr.iuscommunity.org\/mirrorlist?repo=ius-el5\&arch=\$basearch/g' /etc/yum.repos.d/ius.repo
# add the following to the bottom of the file
# comment out the baseurl in favor of 5.5
# baseurl=http://dl.iuscommunity.org/pub/ius/stable/Redhat/5.5/$basearch
sed -i 's/#baseurl=http:\/\/dl.iuscommunity.org\/pub\/ius\/stable\/Redhat\/5\/\$basearch/baseurl=http:\/\/dl.iuscommunity.org\/pub\/ius\/stable\/Redhat\/5.5\/\$basearch/g' /etc/yum.repos.d/ius.repo
# update the system
echo "Performing a system update..." >> /var/log/stackscript.log
yum -yq upgrade
}
#################################
# optimize a few basics #
#################################
function lemp_system_optimize {
echo "" >> /var/log/stackscript.log
echo "Optimizing max file descriptors and sysctl.conf..." >> /var/log/stackscript.log
# increase the max number of file descriptors
echo 512000 > /proc/sys/fs/file-max
# backup limits.conf for safety
cp /etc/security/limits.conf /etc/security/limits.conf.bak
# increase file descriptors per user_name (requires re-login or reboot to take effect)
echo -e "*\t\t-\tnofile\t\t8192" >> /etc/security/limits.conf
# backup sysctl.conf for safety
cp /etc/sysctl.conf /etc/sysctl.conf.bak
# tweak variables in sysctl.conf
overwrite_sysctl_config > /etc/sysctl.conf
# save the changes to sysctl.conf
sysctl -p
}
#################################
# install some useful packages #
#################################
function lemp_install_basics {
echo "" >> /var/log/stackscript.log
echo "Installing the following basic applications:" >> /var/log/stackscript.log
echo "yum-priorities wget jwhois rsync openssh-clients sudo subversion git gcc libjpeg-devel libpng-devel libmcrypt libmcrypt-devel pcre pcre-devel curl curl-devel" >> /var/log/stackscript.log
# install some popular shit, maybe not so much for you
yum install -y wget jwhois rsync openssh-clients sudo subversion git gcc libjpeg-devel libpng-devel libmcrypt libmcrypt-devel pcre pcre-devel curl curl-devel
# install optional shit
test "${MONIT_ENABLED}" == "yes" && (yum install -y monit)
test "${FAIL2BAN_ENABLED}" == "yes" && (yum install -y fail2ban)
test "${BEANSTALK_ENABLED}" == "yes" && (yum install -y beanstalkd)
test "${SUPERVISORD_ENABLED}" == "yes" && (yum install -y supervisord)
# make sure we set optional shit to restart later
test "${MONIT_ENABLED}" == "yes" && (touch /tmp/restart-monit)
test "${FAIL2BAN_ENABLED}" == "yes" && (touch /tmp/restart-fail2ban)
test "${BEANSTALK_ENABLED}" == "yes" && (touch /tmp/restart-beanstalkd)
test "${SUPERVISORD_ENABLED}" == "yes" && (touch /tmp/restart-supervisord)
}
#############################################
# optionally install gearman and libdrizzle #
#############################################
function lemp_install_gearman {
echo "" >> /var/log/stackscript.log
#echo "Adding webtatic repo for gearman..." >> /var/log/stackscript.log
#rpm -ivh http://repo.webtatic.com/yum/centos/5/`uname -i`/webtatic-release-5-1.noarch.rpm
rpm -ivh http://www.alunduil.com/svn/RHELL/trunk/libgearman-0.14-3.x86_64.rpm http://www.alunduil.com/svn/RHELL/trunk/libgearman-devel-0.14-3.x86_64.rpm http://www.alunduil.com/svn/RHELL/trunk/gearmand-0.14-3.x86_64.rpm
# install optional libdrizzle
test "${DRIZZLE_ENABLED}" == "yes" && (echo "Installing libdrizzle dependencies..." >> /var/log/stackscript.log)
test "${DRIZZLE_ENABLED}" == "yes" && (yum -y install autoconf automake bison-devel bison bzr cpp curl-devel e2fsprogs-devel.i386 e2fsprogs-devel.x86_64 gcc gcc-c++.x86_64 gcc.x86_64 glib2-devel glibc-devel.x86_64 glibc.x86_64 gperf intltool libevent-devel.x86_64 libstdc++.i386 libtool ncurses-devel.i386 make ncurses-devel.x86_64 ncurses.x86_64 pam-devel pcre-devel.x86_64 pcre.i386 pcre.x86_64 readline-devel.x86_64 readline.x86_64 zlib-devel.x86_64 boost-devel)
# handle drizzle server install
test "${DRIZZLE_ENABLED}" == "yes" && (echo "Installing libdrizzle for persistent queues with gearman..." >> /var/log/stackscript.log)
test "${DRIZZLE_ENABLED}" == "yes" && (echo "Installing drizzle server..." >> /var/log/stackscript.log)
test "${DRIZZLE_ENABLED}" == "yes" && (echo "Adding unofficial drizzle repo for gearman..." >> /var/log/stackscript.log)
test "${DRIZZLE_ENABLED}" == "yes" && (echo "More info at: http://wiki.drizzle.org/RPMInstallation#Official_Fedora.2FEPEL_Packages" >> /var/log/stackscript.log)
test "${DRIZZLE_ENABLED}" == "yes" && (lemp_install_drizzle_repo > /etc/yum.repos.d/drizzle.repo
test "${DRIZZLE_ENABLED}" == "yes" && (yum -y install drizzle7 drizzle7-client drizzle7-lib drizzle7-mysql-protocol)
# handle libdrizzle database
test "${DRIZZLE_ENABLED}" == "yes" && (echo "Setting up gearman libdrizzle database queue..." >> /var/log/stackscript.log)
test "${DRIZZLE_ENABLED}" == "yes" && (mysql_create_database "$DRIZZLE_DB_PASSWORD" "$DRIZZLE_DB_NAME")
test "${DRIZZLE_ENABLED}" == "yes" && (mysql_create_user "$DRIZZLE_DB_PASSWORD" "$DRIZZLE_DB_USER" "$DRIZZLE_DB_USER_PASSWORD")
test "${DRIZZLE_ENABLED}" == "yes" && (mysql_create_table "$DRIZZLE_DB_PASSWORD" "CREATE TABLE $DRIZZLE_DB_NAME.$DRIZZLE_DB_TABLE (unique_key VARCHAR(64) PRIMARY KEY, function_name VARCHAR(255), priority INT, data LONGBLOB);")
test "${DRIZZLE_ENABLED}" == "yes" && (mysql_grant_user_table "$DRIZZLE_DB_PASSWORD" "$DRIZZLE_DB_USER" "$DRIZZLE_DB_NAME" "$DRIZZLE_DB_TABLE")
echo "Installing gearman..." >> /var/log/stackscript.log
yum -y install gearmand libgearman libgearman-devel php-pecl-gearman --enablerepo=webtatic
touch /tmp/restart-gearmand
# fix the gearman config
test "${DRIZZLE_ENABLED}" == "yes" && (echo "Modifying the gearmand sysconfig to use libdrizzle..." >> /var/log/stackscript.log)
test "${DRIZZLE_ENABLED}" == "yes" && (overwrite_gearman_sysconfig > /etc/sysconfig/gearmand)
# ensure it restarts
test "${DRIZZLE_ENABLED}" == "yes" && (touch /tmp/restart-drizzled)
}
#############################
# install mysql and php 5.3 #
#############################
function lemp_install_lemp {
# first install latest mysql version
echo "Installing mysql 5.0.77..." >> /var/log/stackscript.log
yum install -y mysql mysql-server
touch /tmp/restart-mysqld
# install php with some added bonuses
echo "Installing php-fpm 5.3 (including APC, CLI, GD, mbstring, mcrypt, mysql, suhosin)" >> /var/log/stackscript.log
yum install -y php53-fpm php53-pecl-apc php53-cli php53-devel php53-xml php53-gd php53-mbstring php53-mcrypt php53-mysql
touch /tmp/restart-php-fpm
# optionally install suhosin
test "${SUHOSIN_ENABLED}" == "yes" && (echo Installing php53-suhosin)
test "${SUHOSIN_ENABLED}" == "yes" && (yum install -y php53-suhosin)
# optionally install memcached
test "${MEMCACHED_ENABLED}" == "yes" && (echo Installing the REMI repository specifically for libmemcached...)
test "${MEMCACHED_ENABLED}" == "yes" && (rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-5.rpm)
test "${MEMCACHED_ENABLED}" == "yes" && (echo Installing libmemcached libmemcached-devel memcached php53-pecl-memcache)
test "${MEMCACHED_ENABLED}" == "yes" && (yum install -y libmemcached libmemcached-devel memcached php53-pecl-memcache --enablerepo=remi)
# install nginx
echo "Installing nginx 0.8.53..." >> /var/log/stackscript.log
yum install -y nginx
touch /tmp/restart-nginx
}
##########################################
# setup chkconfig to auto-start services #
##########################################
function lemp_setup_chkconfig {
echo "" >> /var/log/stackscript.log
echo "Ensuring all processes are set to auto-start on boot in chkconfig..." >> /var/log/stackscript.log
# ensure nginx starts up
chkconfig --level=345 nginx on
# ensure php-fpm starts up
chkconfig --level=345 php-fpm on
# ensure mysqld starts up
chkconfig --level=345 mysqld on
# ensure iptables starts up
chkconfig --level=345 iptables on
# ensure postfix starts up
chkconfig --level=345 postfix on
# ensure fail2ban is initialized
test "${FAIL2BAN_ENABLED}" == "yes" && (chkconfig --level=345 fail2ban on)
# ensure monit starts up
test "${MONIT_ENABLED}" == "yes" && (chkconfig --level=345 monit on)
# ensure supervisord starts up
test "${SUPERVISORD_ENABLED}" == "yes" && (chkconfig --level=345 supervisord on)
# ensure gearman starts up
test "${GEARMAN_ENABLED}" == "yes" && (chkconfig --level=345 gearmand on)
# ensure drizzle starts up
test "${GEARMAN_ENABLED}" == "yes" && test "${DRIZZLE_ENABLED}" == "yes" && (chkconfig --level=345 drizzled on)
# ensure beanstalk starts up
test "${BEANSTALK_ENABLED}" == "yes" && (chkconfig --level=345 beanstalkd on)
}
###################################
# IPTables security configuration #
###################################
function lemp_setup_firewall {
echo "" >> /var/log/stackscript.log
echo "Configuring iptables firewall..." >> /var/log/stackscript.log
IFUP=/etc/sysconfig/network-scripts/ifup-iptables.sh
IFDOWN=/etc/sysconfig/network-scripts/ifdown-iptables.sh
IPTABLES() {
echo iptables $@ >&1 2>&1
iptables $@
}
# Set up scripts to load/unload the rules at ifup/ifdown
echo "Generating iptables store/restore scripts..." >> /var/log/stackscript.log
for i in $IFUP $IFDOWN; do
echo $i
touch $i && chmod 744 $i
echo >$i "#!/bin/bash"
echo >>$i "# Generated by RHEL IPTables"
echo >>$i
done
echo >>$IFUP "iptables-restore < /etc/sysconfig/firewall.conf"
echo >>$IFDOWN "iptables-save > /etc/sysconfig/firewall.conf"
# Fix sysctl so this will not log to console
# The distro-default kernel printk is commented out, so we cheat and add
#echo Changing kernel.printk in the kernel.
#echo "3 1 1 1" > /proc/sys/kernel/printk
#echo Modifying /etc/sysctl.conf.
#echo >>/etc/sysctl.conf
#echo "# Added by iptables StackScript, to not log iptables information to console" >>/etc/sysctl.conf
#echo 'kernel.printk = "3 1 1 1"' >>/etc/sysctl.conf
# Build iptables
echo "Building iptables rules." >> /var/log/stackscript.log
for i in INPUT OUTPUT; do IPTABLES -P $i ACCEPT && IPTABLES -F $i; done
IPTABLES -P FORWARD DROP && IPTABLES -F FORWARD
for i in DROP1 DROP2 TCP UDP; do
IPTABLES -F $i >/dev/null 2>/dev/null
IPTABLES -X $i >/dev/null 2>/dev/null
IPTABLES -N $i
done
# Dropper rules based on selected loglevel
# Drop1 is logged if loglevel >= Some Stuff, Drop2 if loglevel = Everything
test "${LOGLEVEL}" == "Everything" && (for i in DROP1 DROP2; do IPTABLES -A $i -j LOG --log-level notice --log-prefix "iptables: "; done)
test "${LOGLEVEL}" == "Some stuff" && (IPTABLES -A DROP1 -j LOG --log-level notice --log-prefix "iptables: ")
for i in DROP1 DROP2; do IPTABLES -A $i -j DROP; done
# Preamble
IPTABLES -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
IPTABLES -A INPUT -m state --state INVALID -j DROP1
IPTABLES -A INPUT -i lo -j ACCEPT
IPTABLES -A INPUT -p tcp -j TCP
IPTABLES -A INPUT -p udp -j UDP
# ICMP
echo "Configuring ICMP behavior..."
test "${ICMPLEVEL}" == "Well-behaved" && (IPTABLES -A INPUT -p icmp -j ACCEPT)
test "${ICMPLEVEL}" == "Only allow pings" && (IPTABLES -A INPUT -p icmp --icmp-type echo-request -j ACCEPT)
# Bottom of the input chain -- log?
test "${LOGLEVEL}" == "Everything" && (IPTABLES -A INPUT -j LOG --log-level notice --log-prefix "iptables: ")
# start a TCP chain if necessary
iptables -N TCP
# start a UDP chain if necessary
iptables -N UDP
# SSH is open by default
if [ -z "$SSHD_PORT" ]; then SSHD_PORT="22";fi
if [ -z "$SSHRANGE" ]; then SSHRANGE="0/0"; fi
echo Allowing: SSH from $SSHRANGE
IPTABLES -A TCP -p tcp --dport $SSHD_PORT -s $SSHRANGE -j ACCEPT
# optionally open up gearman
test "${GEARMAN_ENABLED}" == "yes" && (echo "Allowing: Gearman on port 4730 from 127.0.0.1")
test "${GEARMAN_ENABLED}" == "yes" && (IPTABLES -A TCP -p tcp --dport 4730 -s 127.0.0.1 -j ACCEPT)
# optionally open up libdrizzle
test "${GEARMAN_ENABLED}" == "yes" && test "${DRIZZLE_ENABLED}" == "yes" && (echo "Allowing: Drizzle on port 4427 from 127.0.0.1")
test "${GEARMAN_ENABLED}" == "yes" && test "${DRIZZLE_ENABLED}" == "yes" && (IPTABLES -A TCP -p tcp --dport 4427 -s 127.0.0.1 -j ACCEPT)
# optionally open up memcached
test "${MEMCACHED_ENABLED}" == "yes" && (echo "Allowing: Memcached on port 11211 from 127.0.0.1")
test "${MEMCACHED_ENABLED}" == "yes" && (IPTABLES -A TCP -p tcp --dport 11211 -s 127.0.0.1 -j ACCEPT)
# optionally open up beanstalk
test "${BEANSTALK_ENABLED}" == "yes" && (echo "Allowing: Beanstalk on port 11300 from 127.0.0.1")
test "${BEANSTALK_ENABLED}" == "yes" && (IPTABLES -A TCP -p tcp --dport 11300 -s 127.0.0.1 -j ACCEPT)
# Allowed services
IFS=$','
for service in $ALLOW; do
echo Allowing: $service
interested=${service#*: }
IFS=$' '
set -- $interested
for i in TCP UDP; do
if [[ "$1" == *$i* ]]; then IPTABLES -A $i -p $i --dport $2 -j ACCEPT; fi
done
done
unset IFS
# Extras
for i in $EXTRAU; do
echo Allowing: UDP $i
IPTABLES -A UDP -p UDP --dport $i -j ACCEPT
done
for i in $EXTRAT; do
echo Allowing: TCP $i
IPTABLES -A TCP -p TCP --dport $i -j ACCEPT
done
# Lock 'n save
IPTABLES -P INPUT DROP
iptables-save > /etc/firewall.conf
echo "Completed firewall config..." >> /var/log/stackscript.log
}
################
# SSH SECURITY #
################
function lemp_setup_ssh {
echo "" >> /var/log/stackscript.log
echo "Beginning SSH security setup..." >> /var/log/stackscript.log
cp /etc/sudoers /etc/sudoers.tmp
chmod 0640 /etc/sudoers.tmp
test "${SUDO_PASSWORDLESS}" == "Do Not Require Password" && (echo "%`echo ${SUDO_USERGROUP} | tr '[:upper:]' '[:lower:]'` ALL = NOPASSWD: ALL" >> /etc/sudoers.tmp)
test "${SUDO_PASSWORDLESS}" == "Require Password" && (echo "%`echo ${SUDO_USERGROUP} | tr '[:upper:]' '[:lower:]'` ALL = (ALL) ALL" >> /etc/sudoers.tmp)
chmod 0440 /etc/sudoers.tmp
mv /etc/sudoers.tmp /etc/sudoers
# Configure SSHD
echo "Port ${SSHD_PORT}" > /etc/ssh/sshd_config.tmp
echo "Protocol ${SSHD_PROTOCOL}" >> /etc/ssh/sshd_config.tmp
sed -n 's/\(HostKey .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(UsePrivilegeSeparation .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(KeyRegenerationInterval .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(ServerKeyBits .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(SyslogFacility .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(LogLevel .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(LoginGraceTime .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
echo "PermitRootLogin `echo ${SSHD_PERMITROOT} | tr '[:upper:]' '[:lower:]'`" >> /etc/ssh/sshd_config.tmp
sed -n 's/\(StrictModes .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(RSAAuthentication .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(PubkeyAuthentication .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(IgnoreRhosts .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(RhostsRSAAuthentication .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(HostbasedAuthentication .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(PermitEmptyPasswords .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(ChallengeResponseAuthentication .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
echo "PasswordAuthentication `echo ${SSHD_PASSWORDAUTH} | tr '[:upper:]' '[:lower:]'`" >> /etc/ssh/sshd_config.tmp
sed -n 's/\(X11Forwarding .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(X11DisplayOffset .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(PrintMotd .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(PrintLastLog .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(TCPKeepAlive .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(MaxStartups .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(AcceptEnv .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(Subsystem .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
sed -n 's/\(UsePAM .*\)/\1/p' < /etc/ssh/sshd_config >> /etc/ssh/sshd_config.tmp
echo "AllowGroups `echo ${SSHD_GROUP} | tr '[:upper:]' '[:lower:]'`" >> /etc/ssh/sshd_config.tmp
chmod 0600 /etc/ssh/sshd_config.tmp
mv /etc/ssh/sshd_config.tmp /etc/ssh/sshd_config
touch /tmp/restart-ssh
# Create Groups
groupadd ${SSHD_GROUP}
groupadd ${SUDO_USERGROUP}
# Create User & Add SSH Key
USER_NAME_LOWER=`echo ${USER_NAME} | tr '[:upper:]' '[:lower:]'`
useradd -m -s /bin/bash -G ${SSHD_GROUP},${SUDO_USERGROUP} ${USER_NAME_LOWER}
echo "${USER_NAME_LOWER}:${USER_PASSWORD}" | chpasswd
USER_HOME=`sed -n "s/${USER_NAME_LOWER}:x:[0-9]*:[0-9]*:[^:]*:\(.*\):.*/\1/p" < /etc/passwd`
sudo -u ${USER_NAME_LOWER} mkdir ${USER_HOME}/.ssh
echo "${USER_SSHKEY}" >> $USER_HOME/.ssh/authorized_keys
chmod 0600 $USER_HOME/.ssh/authorized_keys
chown ${USER_NAME_LOWER}:${USER_NAME_LOWER} $USER_HOME/.ssh/authorized_keys
}
######################################################
# IMPORTANT - BELOW SECTION RUNS INSTALL IN SEQUENCE #
######################################################
# starting of stackscript
touch /var/log/stackscript.log
echo "Starting StackScript processing..." >> /var/log/stackscript.log
# update the system
lemp_system_update
# optimize a few things
lemp_system_optimize
# install basic packages
lemp_install_basics
# install postfix
postfix_install_loopback_only
# set up the firewall
lemp_setup_firewall
# set up ssh
lemp_setup_ssh
# install php and nginx
lemp_install_lemp
# setup and install mysql
mysql_install "$DB_PASSWORD" && mysql_tune 40
mysql_create_database "$DB_PASSWORD" "$DB_NAME"
mysql_create_user "$DB_PASSWORD" "$DB_USER" "$DB_USER_PASSWORD"
mysql_grant_user "$DB_PASSWORD" "$DB_USER" "$DB_NAME"
touch /tmp/restart-mysqld
# install gearmand
test "${GEARMAN_ENABLED}" == "yes" && lemp_install_gearman
# setup auto-start services
lemp_setup_chkconfig
# restart new services
restartServices
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment