LEMP,Kernel,Security,Tools,Monitoring - Functions
by obs
60 deployments · 6 still active · last rev. 6 years ago
Does nothing on its own, contains functions to install Nginx, Apache, MySQL PHP (running as fastcgi), postfix, munin, monit, configure ssh for pubkey only access, enabling a unprivileged user, basic iptables, set up root mail alias, and install the ubuntu ec2 stock kernel.
#!/bin/bash #IMPORTANT #This is an experimental script bits of it may not work I use it for my own linodes and it works for me, if you have problems email admin@rwky.net #Some functions in the script rely on other functions being used first (i.e. munin expects mysql to be installed) ###### ###### #LICENCE# ###### #Released under the BSD license http://www.opensource.org/licenses/bsd-license #Copyright (c) 2011, Rowan Wookey <admin@rwky.net> #All rights reserved. # #Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: # #1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. #3. Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ###### #Instructions ###### #Make sure you copy the UDFs to any script that uses these functions #Make sure you source stackscript id 1 #source <ssinclude StackScriptID="1"> #<udf name="INSTALL_MYSQL" label="Instal MySQL?" oneOf="Yes,No"> #<udf name="MYSQL_PASSWORD" label="MySQL root password"> #<udf name="NGINX_VERSION" label="Install nginx from PPA" oneOf="Yes,No" example="See https://launchpad.net/~nginx/+archive/stable"> #<udf name="SSH_PORT" label="SSH port" default="22"> #<udf name="USER" label="Unprivileged User Account" /> #<udf name="USER_PASSWORD" label="Unprivileged User Password" /> #<udf name="USER_SSHKEY" label="Public Key for User" default="" /> #<udf name="ROOT_EMAIL" label="Email alias for root" /> #<udf name="HOSTNAME" label="Hostname" default="" /> #<udf name="WEBSERVER" label="Which webserver to use?" oneOf="Nginx,Apache Prefork,Apache Worker,None" /> ###### #Support ###### #For support please email admin@rwky.net ####### #TODO #run sed on /etc/php5/conf.d/mcrypt.ini to remove # comment #add monit for mysql/postfix/ssh/munin #enabled mod rewrite/expires/deflate/status by default #set apache monit to use mod status #add option to set up an initial domain in /srv/www/domain.com ####### function prep_system { #update system #setup hostname if [ -z "$HOSTNAME" ] then export HOSTNAME=`get_rdns_primary_ip` fi HOST=`echo $HOSTNAME | sed 's/\(\[a-z0-9\]\)*\..*/\1/'` echo "$HOST" > /etc/hostname echo "`system_primary_ip` $HOSTNAME $HOST" >> /etc/hosts start hostname echo "/usr/sbin/nologin" >> /etc/shells #set timezone to UTC ln -s -f /usr/share/zoneinfo/UTC /etc/localtime system_update } function install_nginx { #add nginx ppa if [ $NGINX_VERSION == "Yes" ] then aptitude -y install python-software-properties add-apt-repository ppa:nginx/stable aptitude update fi #Install nginx aptitude -y install nginx cat <<EOT > /etc/nginx/fastcgi_config fastcgi_intercept_errors on; fastcgi_ignore_client_abort on; fastcgi_connect_timeout 60; fastcgi_send_timeout 180; fastcgi_read_timeout 180; fastcgi_buffer_size 128k; fastcgi_buffers 4 256k; fastcgi_busy_buffers_size 256k; fastcgi_temp_file_write_size 256k; fastcgi_max_temp_file_size 0; fastcgi_index index.php; EOT service nginx start mkdir -p /etc/monit/conf.d cat <<EOT >/etc/monit/conf.d/nginx check process nginx with pidfile /var/run/nginx.pid group www-data start program = "/etc/init.d/nginx start" stop program = "/etc/init.d/nginx stop" if failed port 80 protocol HTTP request / within 5 cycles then restart if 5 restarts within 5 cycles then timeout EOT sed -i 's/# gzip_types/gzip_types/' /etc/nginx/nginx.conf sed -i 's/# gzip_vary/gzip_vary/' /etc/nginx/nginx.conf } function notification_email { #mail root to confirm installation mail -s "Linode "`cat /etc/hostname`" setup complete" root <<EOT Your linode setup is complete, if you encounter problems or would like commercial support email admin@rwky.net. Your linode will reboot shortly after this email is sent. You will need to shutdown your linode and change the kernel to pv-grub-x86_32 in the linode manager if you installed the ubuntu stock kernel EOT $(shutdown -r +1) & } function install_php_apache { aptitude -y install libapache2-mod-php5 php5-cli php5-curl php5-gd php5-mcrypt php5-mysql php5-sqlite php-apc sed -i 's/short_open_tag = On/short_open_tag = Off/' /etc/php5/apache2/php.ini sed -i 's/disable_functions =/disable_functions = dl/' /etc/php5/apache2/php.ini sed -i 's/expose_php = On/expose_php = Off/' /etc/php5/apache2/php.ini sed -i 's/memory_limit = 128M/memory_limit = 32M/' /etc/php5/apache2/php.ini sed -i 's/;arg_separator.output/arg_separator.output/' /etc/php5/apache2/php.ini sed -i 's/;date.timezone =/date.timezone = UTC/' /etc/php5/apache2/php.ini sed -i 's/session.name = PHPSESSID/session.name = SESSID/' /etc/php5/apache2/php.ini sed -i 's@;error_log = syslog@error_log = /var/log/php/error.log@' /etc/php5/apache2/php.ini mkdir -p /var/log/php/ chown www-data /var/log/php/ sed -i 's/#/;/' /etc/php5/conf.d/mcrypt.ini mkdir -p /etc/monit/conf.d cat <<EOT >/etc/monit/conf.d/apache2 check process apache with pidfile /var/run/apache2.pid group www-data start program = "/etc/init.d/apache2 start" stop program = "/etc/init.d/apache2 stop" if failed port 80 protocol HTTP request / within 5 cycles then restart if 5 restarts within 5 cycles then timeout EOT } function install_php_apache_worker { aptitude -y install apache2-mpm-worker libapache2-mod-fcgid php5-cgi php5-cli php5-curl php5-gd php5-mcrypt php5-mysql php5-sqlite php-apc sed -i 's/short_open_tag = On/short_open_tag = Off/' /etc/php5/cgi/php.ini sed -i 's/disable_functions =/disable_functions = dl/' /etc/php5/cgi/php.ini sed -i 's/expose_php = On/expose_php = Off/' /etc/php5/cgi/php.ini sed -i 's/memory_limit = 128M/memory_limit = 32M/' /etc/php5/cgi/php.ini sed -i 's/;arg_separator.output/arg_separator.output/' /etc/php5/cgi/php.ini sed -i 's/;date.timezone =/date.timezone = UTC/' /etc/php5/cgi/php.ini sed -i 's/session.name = PHPSESSID/session.name = SESSID/' /etc/php5/cgi/php.ini sed -i 's@;error_log = syslog@error_log = /var/log/php/error.log@' /etc/php5/cgi/php.ini mkdir -p /var/log/php/ chown www-data /var/log/php/ sed -i 's/#/;/' /etc/php5/conf.d/mcrypt.ini cat <<EOT >/etc/apache2/conf.d/fcgi.conf FcgidMaxProcesses 4 FcgidMaxRequestsPerProcess 5000 AddHandler fcgid-script .php FcgidWrapper /usr/local/bin/php5-fcgi-wrapper .php EOT cat <<EOT > /usr/local/bin/php5-fcgi-wrapper #!/bin/sh PHP_FCGI_MAX_REQUESTS=0 export PHP_FCGI_MAX_REQUESTS PHP_FCGI_CHILDREN=0 export PHP_FCGI_CHILDREN exec /usr/bin/php-cgi EOT chmod +x /usr/local/bin/php5-fcgi-wrapper mkdir -p /etc/monit/conf.d cat <<EOT >/etc/monit/conf.d/apache2 check process apache with pidfile /var/run/apache2.pid group www-data start program = "/etc/init.d/apache2 start" stop program = "/etc/init.d/apache2 stop" if failed port 80 protocol HTTP request / within 5 cycles then restart if 5 restarts within 5 cycles then timeout EOT a2dissite default # disable the interfering default virtualhost # clean up, or add the NameVirtualHost line to ports.conf sed -i -e 's/^NameVirtualHost \*$/NameVirtualHost *:80/' /etc/apache2/ports.conf if ! grep -q NameVirtualHost /etc/apache2/ports.conf; then echo 'NameVirtualHost *:80' > /etc/apache2/ports.conf.tmp cat /etc/apache2/ports.conf >> /etc/apache2/ports.conf.tmp mv -f /etc/apache2/ports.conf.tmp /etc/apache2/ports.conf fi } function install_php_fcgi { #Install PHP and common extensions aptitude -y install php5-cgi php5-cli php5-curl php5-gd php5-mcrypt php5-mysql php5-sqlite php-apc #configure php to run as fcgi under user www-data on port 8000 edit init script to change this sed -i 's/short_open_tag = On/short_open_tag = Off/' /etc/php5/cgi/php.ini sed -i 's/disable_functions =/disable_functions = dl/' /etc/php5/cgi/php.ini sed -i 's/expose_php = On/expose_php = Off/' /etc/php5/cgi/php.ini sed -i 's/memory_limit = 128M/memory_limit = 32M/' /etc/php5/cgi/php.ini sed -i 's/;arg_separator.output/arg_separator.output/' /etc/php5/cgi/php.ini sed -i 's/;date.timezone =/date.timezone = UTC/' /etc/php5/cgi/php.ini sed -i 's/session.name = PHPSESSID/session.name = SESSID/' /etc/php5/cgi/php.ini sed -i 's@;error_log = syslog@error_log = /var/log/php/error.log@' /etc/php5/cgi/php.ini mkdir -p /var/log/php/ chown www-data /var/log/php/ sed -i 's/#/;/' /etc/php5/conf.d/mcrypt.ini cat <<EOT >/etc/init/php5-fcgi.conf # php5-fcgi # # Spawns php5 in fastcgi mode start on (local-filesystems and net-device-up IFACE=eth0) stop on runlevel [!12345] respawn respawn limit 5 300 script . /etc/php5/upstart/\$UPSTART_JOB su -p -s /bin/bash -c "\$PHP_ENVS /usr/bin/php-cgi -b \$PHP_LISTEN -c \$PHP_INI" \$PHP_USER end script #create pidfile post-start script sleep 1 status \$UPSTART_JOB | egrep -o '([0-9]+)\$' | head -n1 > /var/run/\$UPSTART_JOB.pid end script #delete pid file post-stop exec rm /var/run/\$UPSTART_JOB.pid EOT mkdir -p /etc/php5/upstart/ cat <<EOT >/etc/php5/upstart/php5-fcgi export PHP_USER=www-data export PHP_LISTEN=127.0.0.1:8000 export PHP_ENVS="PHP_FCGI_CHILDREN=4 PHP_FCGI_MAX_REQUESTS=5000" export PHP_INI="/etc/php5/php.ini.sites/www-data.ini" EOT mkdir -p /etc/php5/php.ini.sites/ cp /etc/php5/cgi/php.ini /etc/php5/php.ini.sites/www-data.ini start php5-fcgi mkdir -p /etc/monit/conf.d cat <<EOT >/etc/monit/conf.d/php5-fcgi check process php5-fcgi with pidfile /var/run/php5-fcgi.pid start program "/sbin/start php5-fcgi" stop program "/sbin/stop php5-fcgi" if failed port 8000 type tcp then restart if 5 restarts within 5 cycles then timeout EOT } function install_mysql { #Install mysql mysql_install "$MYSQL_PASSWORD" mysql_tune 30 sed -i -e 's/^skip-innodb/#skip-innodb/' /etc/mysql/my.cnf # re-enable innodb, it may take more memory but it's becoming standard #enable slow query logging to table compatible with mysql workbench cat <<EOT > /etc/mysql/conf.d/logging.cnf [mysqld] slow_query_log = 1 slow_query_log_file = /var/log/mysql/mysql-slow.log long_query_time = 1 log-queries-not-using-indexes log-output=TABLE EOT #make pid file static name across installations cat <<EOT > /etc/mysql/conf.d/pid.cnf [mysqld] pid-file = /var/lib/mysql/mysqld.pid EOT cat <<EOT > /root/.my.cnf [client] user=root password=$MYSQL_PASSWORD EOT chmod 0400 /root/.my.cnf mkdir -p /etc/monit/conf.d/ cat <<EOT > /etc/monit/conf.d/mysql check process mysqld with pidfile /var/lib/mysql/mysqld.pid group mysql start program = "/sbin/start mysql" stop program = "/sbin/stop mysql" if failed unixsocket /var/run/mysqld/mysqld.sock protocol mysql then restart if 5 restarts within 5 cycles then timeout EOT } function install_postfix { #Install postfix postfix_install_loopback_only #install mail sending utilities aptitude -y install mailutils #configure root alias echo "root: $ROOT_EMAIL" >> /etc/aliases echo "$USER: root" >> /etc/aliases cat /etc/hostname > /etc/mailname /usr/bin/newaliases sed -i "s/mydestination = localhost, localhost.localdomain, , localhost/mydestination = localhost, localhost.localdomain, $HOSTNAME/" /etc/postfix/main.cf service postfix restart } function configure_ssh { #setup ssh #add ssh key sudo -u $USER mkdir /home/$USER/.ssh sudo -u $USER echo "${USER_SSHKEY}" >> /home/$USER/.ssh/authorized_keys chmod 0600 /home/$USER/.ssh/authorized_keys chown $USER:$USER /home/$USER/.ssh/authorized_keys sed -i "s/Port 22/Port $SSH_PORT/" /etc/ssh/sshd_config #set ssh port sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config #disable root ligin if [ "$USER_SSHKEY" != "" ] then sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config #disable ssh password auth if $USER_SSHKEY is not empty fi sed -i 's/X11Forwarding yes/X11Forwarding no/' /etc/ssh/sshd_config #disable xforwarding echo "UseDNS no" >> /etc/ssh/sshd_config #disable dns lookups echo "AllowUsers $USER" >> /etc/ssh/sshd_config #only allow access from $USER } function configure_user { #configure ssh/sudo useradd -m -s /bin/bash $USER #add user account echo "$USER:$USER_PASSWORD" | chpasswd #setpassword #add user to sudoers echo "$USER ALL=(ALL) ALL" >> /etc/sudoers #lock out root passwd -l root } function install_shorewall { #sets up shorewall firewall aptitude -y install shorewall shorewall6 cp /usr/share/doc/shorewall/examples/one-interface/* /etc/shorewall/ sed -i 's/BLACKLISTNEWONLY=Yes/BLACKLISTNEWONLY=No/' /etc/shorewall/shorewall.conf sed -i 's/REJECT/DROP/' /etc/shorewall/policy if [ "$WEBSERVER" != "None" ] then echo "#accept http/s" >> /etc/shorewall/rules echo "ACCEPT net \$FW:`system_primary_ip` tcp 80" >> /etc/shorewall/rules echo "ACCEPT net \$FW:`system_primary_ip` tcp 443" >> /etc/shorewall/rules fi echo '#accept ssh and ratelimit to 5 connections per miniute per ip' >> /etc/shorewall/rules echo "ACCEPT net \$FW:`system_primary_ip` tcp $SSH_PORT - - s:ssh:5/min:1" >> /etc/shorewall/rules sed -i 's/STARTUP_ENABLED=No/STARTUP_ENABLED=Yes/' /etc/shorewall/shorewall.conf sed -i 's/startup=0/startup=1/' /etc/default/shorewall #disable ipv6 by default cp /usr/share/doc/shorewall6/examples/one-interface/* /etc/shorewall6/ sed -i 's/BLACKLISTNEWONLY=Yes/BLACKLISTNEWONLY=No/' /etc/shorewall6/shorewall6.conf sed -i 's/REJECT/DROP/' /etc/shorewall6/policy sed -i 's/STARTUP_ENABLED=No/STARTUP_ENABLED=Yes/' /etc/shorewall6/shorewall6.conf sed -i 's/startup=0/startup=1/' /etc/default/shorewall6 } function install_monit { #install and enable monit aptitude -y install monit sed -i 's/startup=0/startup=1/' /etc/default/monit mkdir -p /etc/monit/conf.d/ echo "include /etc/monit/conf.d/*" >> /etc/monit/monitrc sed -i "s/# set daemon 120/set daemon 120/" /etc/monit/monitrc sed -i "s/# with start delay 240/with start delay 240/" /etc/monit/monitrc sed -i "s/# set logfile syslog facility log_daemon/set logfile \/var\/log\/monit.log/" /etc/monit/monitrc sed -i "s/# set mailserver mail.bar.baz,/set mailserver localhost/" /etc/monit/monitrc sed -i "s/# set eventqueue/set eventqueue/" /etc/monit/monitrc sed -i "s/# basedir \/var\/monit/basedir \/var\/monit/" /etc/monit/monitrc sed -i "s/# slots 100 /slots 100/" /etc/monit/monitrc sed -i "s/# set alert sysadm@foo.bar/set alert root@localhost reminder 180/" /etc/monit/monitrc sed -i "s/# set httpd port 2812 and/ set httpd port 2812 and/" /etc/monit/monitrc sed -i "s/# use address localhost/use address localhost/" /etc/monit/monitrc sed -i "s/# allow localhost/allow localhost/" /etc/monit/monitrc sed -i "s/# set mail-format { from: monit@foo.bar }/set mail-format { from: monit@`hostname -f` }/" /etc/monit/monitrc cat << EOT > /etc/monit/conf.d/system check system `hostname -f` if loadavg (1min) > 4 then alert if loadavg (5min) > 4 then alert if memory usage > 90% then alert if cpu usage (user) > 70% then alert if cpu usage (system) > 30% then alert if cpu usage (wait) > 20% then alert check filesystem rootfs with path / if space > 80% then alert EOT } function install_munin { #install munin aptitude -y install munin munin-node libcache-cache-perl libdbd-mysql-perl sed -i 's/host \*/host 127.0.0.1/' /etc/munin/munin-node.conf sed -i "s/localhost.localdomain/`hostname -f`/" /etc/munin/munin.conf echo "munin: root" >> /etc/aliases sed -i "s#\[mysql\*\]#[mysql*]\nenv.mysqladmin /usr/bin/mysqladmin#" /etc/munin/plugin-conf.d/munin-node if [ -x /usr/bin/newaliases ] then /usr/bin/newaliases fi } function install_security { #install chrootkit rkhunter logwatch aptitude -y install chkrootkit rkhunter logwatch libsys-cpu-perl build-essential echo "yes" | perl -MCPAN -e 'install Sys::MemInfo' sed -i 's/#ALLOWHIDDENDIR=\/dev\/.initramfs/ALLOWHIDDENDIR=\/dev\/.initramfs/' /etc/rkhunter.conf sed -i 's/#ALLOWHIDDENDIR=\/dev\/.udev/ALLOWHIDDENDIR=\/dev\/.udev/' /etc/rkhunter.conf sed -i 's/DISABLE_TESTS="suspscan hidden_procs deleted_files packet_cap_apps apps"/DISABLE_TESTS="suspscan hidden_procs deleted_files packet_cap_apps apps os_specific"/' /etc/rkhunter.conf rkhunter --propupd sed -i 's/--output mail/--output mail --detail 10 --service All/' /etc/cron.daily/00logwatch } function install_tools { #install full vim, nano, less, htop (nice version of top), iotop (top for disk io), logrotate (rotates logs..), lynx (text webbrowser), mytop (top for mysql), ntop (top for networks), screen (terminal emulator), sqlite3 (command line interface for sqlite databases) aptitude -y install vim nano less htop iotop logrotate lynx mytop nmap ntop screen sqlite3 cron-apt ntp curl sed -i 's/# EXITON="error"/EXITON=""/' /etc/cron-apt/config sed -i 's/# SYSLOGON="upgrade"/SYSLOGON=""/' /etc/cron-apt/config sed -i 's/# MAILON="error"/MAILON=""/' /etc/cron-apt/config } function install_ubuntu_stock_kernel { #installs ubuntu ec2 kernel which works best on linode #configures grub to load kernel after 3 seconds #sets console to hvc0 so you can access via listh #enables delayacct so iotop works aptitude -y install grub update-grub -y sed -i 's#kopt=root=.* ro#kopt=root=/dev/xvda ro#' /boot/grub/menu.lst sed -i 's#groot=.*#groot=(hd0)#' /boot/grub/menu.lst sed -i 's/defoptions=quiet splash/defoptions=quiet delayacct console=hvc0/' /boot/grub/menu.lst sed -i 's/# indomU=detect/# indomU=true/' /boot/grub/menu.lst aptitude -y install linux-ec2 chmod 0600 /boot/grub/menu.lst } function set_root_profile { #Black 0;30 Dark Gray 1;30 #Blue 0;34 Light Blue 1;34 #Green 0;32 Light Green 1;32 #Cyan 0;36 Light Cyan 1;36 #Red 0;31 Light Red 1;31 #Purple 0;35 Light Purple 1;35 #Brown 0;33 Yellow 1;33 #Light Gray 0;37 White 1;37 cat <<EOT >> /root/.profile PS1='\[\033[0;33m\]root@' #add hostname PS1=\$PS1\$(hostname -f)'\n' #add ipv4 addresses PS1=\$PS1\$(ifconfig | grep -v '127.0.0.1' | awk -F: '/inet addr:/ {print \$2}' | awk '{ print \$1 }') #add ipv6 addresses PS1=\$PS1'\n'\$(ifconfig | grep 'Global' | awk -F / '/inet6 addr: / {print \$1}' | awk '{ print \$3 }') #add current working dir and close colours PS1=\$PS1'\n\$PWD:\$\033[00m\]\n' export PS1 EOT } function cleanup { #disable services not required if [ -f /etc/init/atd.conf ] then stop atd mv /etc/init/atd.conf /etc/init/atd.conf.noexec fi update-locale } #deletes users from /etc/passwd that you don't need function deleteusers { deluser irc #delete irc user deluser games #delete games user deluser news #delete nntp daemon user deluser uucp #delete uucp user deluser proxy #delete proxy user deluser list #delete mailing list user deluser gnats #delete gnats bug reporting user }