You are here

Installation script (Deprecated)

Submitted by Alan Mels on Sat, 08/26/2017 - 02:56

Auto-installation script for the newly deployed systems

This page generates a script for an automatic installation of operating system for AltaGrade dedicated and virtual private servers. The script incorporates all the steps on this page and referenced steps of other nodes in this book hierarchy. Introduction fields will be ignored. Make sure to properly reference steps on other nodes to get them included. To reference another node place only its nid in the source code field of any paragraph.

Newly created Virtualizor systems can pull the script by the following commands placed in the `Extra` parameter:

  1. yum -y update && yum -y install wget dos2unix && cd /usr/src && wget http://in.altagrade.org:8080/etc-ag.tgz && wget http://in.altagrade.org:8080/altaos-install.txt && dos2unix altaos-install.txt && mv altaos-install.txt altaos-install.sh && chmod 755 altaos-install.sh && sh ./altaos-install.sh | tee /root/altaos-install-log.txt

Additional notes:

- To install AltaOS on EU-based server, don't forget to include EU IP addresses to `Allow from` rule for in.altagrade.org in the Apache configuration file (/etc/httpd/conf/httpd.conf).


0) Check if the system is freshly installed before doing anything else, because we don't want to run the installation script twice

if [ -d /etc/ag ]; then
  echo "It seems this script has already been executed on this server."
  echo "This script should be run only once as otherwise it will duplicate entries in number of configuration files!"
  exit 0
fi
SECONDS=0

1) Setting cron job definitions before other scripts start puting their own lines

cd /var/spool/cron/
rm -f root
cat > root << 'EOF'
# Example of cron job definition on AltaGrade servers:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
#
# 1. Entry: Minute when the process will be started [0-60]
# 2. Entry: Hour when the process will be started [0-23]
# 3. Entry: Day of the month when the process will be started [1-28/29/30/31]
# 4. Entry: Month of the year when the process will be started [1-12]
# 5. Entry: Weekday when the process will be started [0-6] [0 is Sunday]
#
# every x min = */x
# So according to this your 5 8 * * 6 would run 8:05 every Saturday.
# Ex: 39 * * * * wget -O - -q -t 1 http://YourDrupalSite.com/cron.php?key=YourDrupalSiteCronKeyHere
EOF

2) Upgrading the system, installing nano and creating AltaGrade working directories

yum -y makecache fast && yum -y install yum-plugin-fastestmirror
yum -y update && yum -y install nano
mkdir /etc/ag && cd /etc/ag && mkdir scripts cp
mkdir /sandbox /home/backup /home/backup/ag
ln -s /home/backup /backup

3) Installing additional repositories

yum -y install epel-release && yum -y update
cat > /etc/yum.repos.d/AltaGrade.repo << 'EOF'
[altagrade]
name=AltaGrade Repository
baseurl=http://repo.altagrade.org:8080
enabled=1
gpgcheck=0
EOF

4) Installing useful OS packages

yum -y install perl nano rsync make vim screen wget mlocate gcc pcre-devel nmap openssh-clients ImageMagick gcc-c++ bzip2 net-tools iptables-services ntpdate yum-cron perl-LWP-Protocol-https deltarpm patch  lsof git psacct yum-utils bash-completion at e2fsprogs sudo libxml2-devel htop pam-devel perl-Authen-PAM

5) Defining some variable values to use later in the installation script

if grep -q "QEMU" /proc/bus/input/devices; then
    PORT=19759
else
    PORT=19753
fi
export PORT
IP="$( ip route get 8.8.8.8 | awk 'NR==1 {print $NF}' )"
IFACE=$(ip addr | grep $IP | awk '{print $NF}')
OWNER=""

6) Creating a Welcome banner and MOTD

cat <<EOT >> /etc/banner
 ▄▄▄       ▓▓▓  ▓▓▓█████▓ ▄▄▄        ▄████  ▓▓▀███   ▄▄▄      ▓█████▄ ▓█████
▒▓▓██▄    ▓██▒  ▓  ▓▓▒ ▓▒▒████▄     ▓▓▒ ▀█▒▓██ ▒ ▓█▒▒▓▓██▄    ▒▓▓▀ ██▌▓▓   ▀
▒▓▓  ▀█▄  ▒▓▓░  ▒ ▓██░ ▒░▒▓▓  ▀█▄  ▒▓▓░▄▄▄░▓▓▓ ░▄█ ▒▒▓▓  ▀█▄  ░██   █▌▒▓▓██
░██▄▄▄▄██ ▒▓▓░  ░ ▓██▓ ░ ░██▄▄▄▄██ ░▓█  ██▓▒▓▓▀▀█▄  ░██▄▄▄▄██ ░▓█▄   ▌▒▓█  ▄
 ▓█   ▓██▒░██████▒▒██▒ ░  ▓█   ▓██▒░▒▓███▀▒░██▓ ▒▓▓▒ ▓█   ▓██▒░▒████▓ ░▒████▒
 ▒▒   ▓▒█░░ ▒░▓  ░▒ ░░    ▒▒   ▓▒█░ ░▒   ▒ ░ ▒▓ ░▒▓░ ▒▒   ▓▒█░ ▒▒▓  ▒ ░░ ▒░ ░
  ▒   ▒▒ ░░ ░ ▒  ░  ░      ▒   ▒▒ ░  ░   ░   ░▒ ░ ▒░  ▒   ▒▒ ░ ░ ▒  ▒  ░ ░  ░
  ░   ▒     ░ ░   ░        ░   ▒   ░ ░   ░   ░░   ░   ░   ▒    ░ ░  ░    ░
      ░  ░    ░  ░             ░  ░      ░    ░           ░  ░   ░       ░  ░
 
EOT
cat <<EOT >> /etc/motd
*****************************************************************************
*             Welcome to AltaGrade Optimized Operating System!              *
*                                                                           *
* If you encounter any issues with the server, then please browse our Help  *
* section on https://www.altagrade.com/help first. And if you couldn't find *
* any solution, then submit a support request at https://my.altagrade.com.  *
*                                                                           *
*****************************************************************************
EOT

7) Setting %wheel group members passwordless sudoers

sed -ie 's/%wheel/#%wheel/' /etc/sudoers && sed -ie 's/# #%wheel/%wheel/' /etc/sudoers

8) Installing getinfo script and making it executable...

cd /etc/ag/scripts
wget https://raw.githubusercontent.com/elrepo/packages/master/getinfo/el6/getinfo.sh
chmod 755 getinfo.sh

9) Define aliases for root user

cat >> /root/.bashrc << 'EOF' 
 
alias webminpass='/usr/libexec/webmin/changepass.pl /etc/webmin root'
alias ps10='ps -auxf | sort -nr -k 4 | head -10'
alias cpu10='ps -eo pcpu,pid,user,args | sort -k 1 -r | head -10'
alias qchwr='drush pml --no-core --type=module --status=enabled --pipe | xargs drush -y dis'
alias repo='sed -n -e "/^\[/h; /priority *=/{ G; s/\n/ /; s/ity=/ity = /; p }" /etc/yum.repos.d/*.repo | sort -k3n'
alias psx="ps -eo pcpu,pid -o comm= | sort -k1 -n -r | head -12"
alias psg="ps fuxa |grep $1"
alias psm="ps -eo pmem,pcpu,rss,vsize,args | sort -k 1 -r | less"
alias eba='nano /etc/profile.d/globaliases.sh'
alias lba='source /etc/profile.d/globaliases.sh'
 
alias net1='rm -rf /etc/udev/rules.d/70-persistent-net.rules'
alias net2='nano /etc/resolv.conf'
alias net3='nano /etc/sysconfig/network-scripts/ifcfg*'
 
snd () {
rsync --rsh -av -e 'ssh -p 19759' --progress --partial ${1} root@IP:/
}
 
 
# sync two directories
# rsync -azP -e 'ssh -p 19759' local_dir root@IP:/remote_dir

EOF

10) Creating global aliases for user SSH sessions...

24

11) Colorify the Nano editor

sed -ie 's|# include "/usr/share/nano/sh.nanorc"|include "/usr/share/nano/sh.nanorc"|' /etc/nanorc
sed -ie 's|# include "/usr/share/nano/java.nanorc"|include "/usr/share/nano/java.nanorc"|' /etc/nanorc
sed -ie 's|# include "/usr/share/nano/python.nanorc"|include "/usr/share/nano/python.nanorc"|' /etc/nanorc
sed -ie 's|# include "/usr/share/nano/patch.nanorc"|include "/usr/share/nano/patch.nanorc"|' /etc/nanorc
sed -ie 's|# include "/usr/share/nano/php.nanorc"|include "/usr/share/nano/php.nanorc"|' /etc/nanorc
sed -ie 's|# include "/usr/share/nano/c.nanorc"|include "/usr/share/nano/c.nanorc"|' /etc/nanorc
sed -ie 's|# include "/usr/share/nano/css.nanorc"|include "/usr/share/nano/css.nanorc"|' /etc/nanorc
sed -ie 's|# include "/usr/share/nano/html.nanorc"|include "/usr/share/nano/html.nanorc"|' /etc/nanorc
sed -ie 's|# include "/usr/share/nano/man.nanorc"|include "/usr/share/nano/man.nanorc"|' /etc/nanorc
sed -ie 's|# include "/usr/share/nano/perl.nanorc"|include "/usr/share/nano/perl.nanorc"|' /etc/nanorc
sed -ie 's|# include "/usr/share/nano/ruby.nanorc"|include "/usr/share/nano/ruby.nanorc"|' /etc/nanorc
sed -ie 's|# include "/usr/share/nano/xml.nanorc"|include "/usr/share/nano/xml.nanorc"|' /etc/nanorc
sed -ie 's|# include "/usr/share/nano/nanorc.nanorc"|include "/usr/share/nano/nanorc.nanorc"|' /etc/nanorc

12) Enabling Audit Trail

systemctl enable psacct && systemctl start psacct

13) Enabling automatic OS updates

sed -ie 's/update_messages = no/update_messages = yes/' /etc/yum/yum-cron.conf
sed -ie 's/download_updates = no/download_updates = yes/' /etc/yum/yum-cron.conf
sed -ie 's/apply_updates = no/apply_updates = yes/' /etc/yum/yum-cron.conf
#chattr +i /etc/yum/yum-cron.conf
sed -ie 's/update_messages = no/update_messages = yes/' /etc/yum/yum-cron-hourly.conf
sed -ie 's/download_updates = no/download_updates = yes/' /etc/yum/yum-cron-hourly.conf
sed -ie 's/apply_updates = no/apply_updates = yes/' /etc/yum/yum-cron-hourly.conf
#chattr +i /etc/yum/yum-cron-hourly.conf

14) Setting amount of installed kernels to 2

sed -ie 's/installonly_limit=5/installonly_limit=2/' /etc/yum.conf
systemctl enable yum-cron.service && systemctl start yum-cron.service

15) Installing Webmin and Virtualmin

cd /usr/src
wget http://software.virtualmin.com/gpl/scripts/install.sh
chmod 755 install.sh
# Per https://www.virtualmin.com/node/53190
DISABLE_SCL=1
export DISABLE_SCL
./install.sh -y
#yum -y install wbm-virtualmin-password-recovery

16) Installing style.css file for Virtualmin

29

17) Configuring Webmin and Virtualmin

rm -rf /etc/webmin/status/services
sed -ie 's/php_suexec=3/php_suexec=2/' /etc/webmin/virtual-server/config
sed -ie 's/nopwd=0/nopwd=1' /etc/webmin/mysql/config
echo "Declaring global variables for PORT and DEFAULT_IP..."
echo "PORT ${PORT}" > /etc/webmin/virtual-server/globals
echo "DEFAULT_IP 1" >> /etc/webmin/virtual-server/globals
chkconfig usermin off
echo "webmin_from=root" >> /etc/webmin/mailboxes/config

18) Creating an 'altagrade' admin user

useradd -G wheel altagrade
echo "yik78Fv,ag" | passwd altagrade --stdin 
sed -ie 's/root: /altagrade: /' /etc/webmin/webmin.acl
sed -ie 's/root:/altagrade:/' /etc/webmin/miniserv.users
mkdir /home/altagrade/.ssh 
echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC753VZbicoElj5moS0XZ70ERwse483Cuqc6Jf3YXJvn4+ZGzdjUsUI4+0GHK0aufeFh4YNZQ9QoQnM/3HUKZIGm3/2lYvzY1Z2YtyWz57LSX6o+oskq01Pe+3g+sxbt1yOW/KhClVhTSNzFPtMV5h4//JLxdO1Z6pctXSgq2COZ9fnEAm/AzmYFpuNvg0JmNdWuFkvnSKZrkt9hmw72TTjTE+p9DviTmoq4GCr6l2Pg4y6oTlyQ595yi6wDZe0JK7cdkKMsA4U6kAyHqci7zXOu7HjLdYcKZCohCp/iddHZbERmlZuS1eGbiARYtBZb9FNdUmnUB3nggb4DU3FPeDl' >> /home/altagrade/.ssh/authorized_keys
echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4K7QPiD9EbzJDXN9xcfloD6NL6T4hUDmfe3/5lqVgBkiFUr1Npq5R+KE6DyCxu6HC3Yiowf4Ju32e6W66Ke4smcPQSsAPKUjtzm59IB8Ngt8z/iDlsPj66Wonq9TqIVjuKsol2R8J8LvwybmaheuAr6Hccsw2pdUwkh1KZiJOmPwiP5Rm2ekCJ8kUTED45zQrXEuv3q4Mszec6Kt5r0Y8qHfGzNDE4xgCRofNmK55l6WclC36ZZdYRrNt+1btFM10VqwtWUX3OJtumfPYKmzhWGGpBlBk9rbxCjXdSIiGSjJEO+9nzlsWZo0TfThs6T/DqmMSkCMsVu3jb9cms2qT [email protected]' >> /home/altagrade/.ssh/authorized_keys
restorecon -R -v /home/altagrade/.ssh
sed -i "s/#Port 22/Port ${PORT}/g" /etc/ssh/sshd_config
sed -i "s/#PermitRootLogin yes/PermitRootLogin no/g" /etc/ssh/sshd_config
sed -i "s/PasswordAuthentication yes/PasswordAuthentication no/g" /etc/ssh/sshd_config
echo 'Banner /etc/banner' >> /etc/ssh/sshd_config
 
yum -y install policycoreutils-python
semanage port -a -t ssh_port_t -p tcp ${PORT}
yum -y remove policycoreutils-python setools-libs python-IPy checkpolicy libsemanage-python audit-libs-python 
 
systemctl restart sshd
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config

19) Renaming Webmin modules

cat > /etc/webmin/webmin.descs<< 'EOF'
bandwidth=Traffic Monitoring
webmin=Host Manager Configuration
servers=Host Manager Servers
webminlog=Host Manager Log
acl=Host Manager Users
virtualmin-registrar=Site Manager Domain Registration
virtualmin-dav=Site Manager DAV
virtualmin-init=Site Manager Bootup Actions
virtualmin-git=Site Manager Git
virtualmin-htpasswd=Site Manager Protected Directories
virtualmin-sqlite=Site Manager SQLite
virtual-server=Site Manager Domains
usermin=User Manager Configuration
EOF
# Per https://www.virtualmin.com/node/43097
rm -rf /var/webmin/module.infos.cache

20) Installing /etc/webmin/webmin.acl

33

21) Temporary step until https://www.virtualmin.com/node/56959 is resolved

sed -ie "s/nopwd=0/nopwd=1/" /etc/webmin/mysql/config

22) Installing custom menu for SSL certificate selection

mkdir /etc/ag/custom-menus
cd /etc/ag/custom-menus
cat > ssl.menu << 'EOF'
ssl_self Self-signed SSL Certificate
ssl_le Let's Encrypt SSL Certificate
ssl_commercial Commercial SSL Certificate
EOF
cat > app.menu << 'EOF'
drupal8 Drupal 8
drupal7 Drupal 7
backdrop Backdrop
wordpress Wordpress
other Other
EOF

23) Installing Composer globally

cd /usr/src
curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer

24) Installing additional PHP packages, memcached, configuring uploadprogress

yum -y install php-soap php-devel php-pear php-gd php-mbstring php-mcrypt
pecl channel-update pecl.php.net
pecl install uploadprogress
echo extension=uploadprogress.so >> /etc/php.d/uploadprogress.ini
yum -y install memcached
yum -y install php-pecl-memcache
rm -f /etc/sysconfig/memcached
cat <<'EOT' >> /etc/sysconfig/memcached 
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="1024"
OPTIONS="-l 127.0.0.1"
EOT
systemctl enable memcached
systemctl start  memcached
 
sed -ie 's/upload_max_filesize = 2M/upload_max_filesize = 20M/' /etc/php.ini
sed -ie 's/post_max_size = 8M/post_max_size = 16M/' /etc/php.ini
sed -ie 's/max_execution_time = 30/max_execution_time = 600/' /etc/php.ini
sed -ie 's/max_input_time = 60/max_input_time = 600/' /etc/php.ini
sed -ie 's/memory_limit = 128M/memory_limit = 1280M/' /etc/php.ini 

25) Configuring the correct SSLProtocol entries in Apache configuration file

sed -ie '/SSLProtocol/c\SSLProtocol All -SSLv2 -SSLv3' /etc/httpd/conf/httpd.conf
sed -ie '/SSLCipherSuite/c\SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4"' /etc/httpd/conf/httpd.conf
sed -ie '/SSLCipherSuite/i\SSLHonorCipherOrder on' /etc/httpd/conf/httpd.conf

26) Configuring automatic core updates for Drupal websites

25
yum -y install certbot
 
# Install script to auto-replace the ssl_le.pem files for domains
mkdir /etc/letsencrypt/renewal-hooks
mkdir /etc/letsencrypt/renewal-hooks/deploy
cat > /etc/letsencrypt/renewal-hooks/deploy/replace_pems.sh << 'EOF'
#!/bin/sh

# Re-create the ssl_le.pem files for Pound 
for domain in $RENEWED_DOMAINS; do
  cat $RENEWED_LINEAGE/privkey.pem $RENEWED_LINEAGE/fullchain.pem > $RENEWED_LINEAGE/ssl_le.pem
done
 
systemctl restart httpd
systemctl restart varnish
systemctl restart pound
 
exit
EOF
chmod 755 /etc/letsencrypt/renewal-hooks/deploy/replace_pems.sh
 
# Install script to auto-renew all certificates

cat > /etc/ag/scripts/renew-certs << 'EOF'
#!/bin/bash

# Create a temporary file for STDERR
ERROR_LOG=$(mktemp)
 
# Renew, ignoring STDOUT and piping STDERR to the temp file
/usr/bin/certbot renew --quiet > /dev/null 2> "$ERROR_LOG"
 
if [[ -s "$ERROR_LOG" ]]; then
    mail -s "certbot Renewal Issue" root < "$ERROR_LOG"
fi
 
rm -rf "$ERROR_LOG"
exit
EOF
chmod 755 /etc/ag/scripts/renew-certs
 
# Install cron-tab to trigger auto-renew
(crontab -l && echo "0 0,12 * * 7 python -c 'import random; import time; time.sleep(random.random() * 3600)' && /etc/ag/scripts/renew-certs" | sort | uniq) | crontab -

28) Configuring hourly and daily AltaGrade cron-tasks

cat > /etc/cron.hourly/altagrade << 'EOF'
#!/bin/bash
sh /etc/ag/scripts/update-drupal 1 > /dev/null
exit
EOF
chmod 755 /etc/cron.hourly/altagrade
 
cat > /etc/cron.daily/altagrade << 'EOF'
#!/bin/bash
sed -ie 's/CentOS/AltaOS/' /etc/webmin/config >/dev/null 2>&1
sed -ie 's/slider_enabled=true/slider_enabled=false/' /etc/webmin/authentic-theme/settings.js >/dev/null 2>&1
exit
EOF
chmod 755 /etc/cron.daily/altagrade
/etc/cron.daily/altagrade

29) Creating script to check if logged user is authorized or not

cat > /etc/ag/scripts/login-notify.sh << 'EOF'
#!/bin/sh
if [ "$PAM_TYPE" != "close_session" ]; then
  if [ -f /etc/apf/allow_hosts.rules ]; then
    IP=`who | cut -d"(" -f2 | cut -d")" -f1`
    if ! grep -q "$IP" /etc/apf/allow_hosts.rules; then
      HOST="`hostname`"
      SUBJECT="Security Alert: $PAM_USER logged into $host from unauthorized $PAM_RHOST"
      # message="`env`"
      MESSAGE="A user $PAM_USER has opened $PAM_TTY session on $HOST from an unauthorized IP address $PAM_RHOST. If the IP address does not belong to your team, then investigate this incident as soon as possible, otherwise please get it whitelisted to avoid receiving this notifications in the future."
      echo "$MESSAGE" | mailx -r root -s "$SUBJECT" "[email protected]"
    fi
  fi
fi
EOF
chmod 755 /etc/ag/scripts/login-notify.sh
echo 'session optional pam_exec.so seteuid /etc/ag/scripts/login-notify.sh' >> /etc/pam.d/sshd

30) Suppressing all cron e-mail notifications. Excluded now, because we added:

sh /usr/local/bin/update-drupal 1 > /dev/null

to hourly drupal updates.

echo 'CRONDARGS=-s -m off' >> /etc/sysconfig/crond
systemctl restart crond.service

31) Configuring MariaDB settings

rm -f  /etc/my.cnf
cat > /etc/my.cnf << 'EOF'
[client]
default-character-set = utf8mb4
 
[mysql]
default-character-set = utf8mb4
 
[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
 
#skip-networking
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
slow_query_log = 1
slow_query_log_file = /var/log/mariadb/slow.log
 
query_cache_size = 128M
query_cache_limit = 16M
 
thread_cache_size = 8
myisam_sort_buffer_size = 64M
read_rnd_buffer_size = 8M
read_buffer_size = 2M
sort_buffer_size = 2M
table_cache = 512
max_allowed_packet=1024M
key_buffer = 384M
wait_timeout=600
max_connections = 600
tmp_table_size = 256M
max_heap_table_size = 256M
 
innodb_large_prefix=true
innodb_file_format=barracuda
innodb_file_per_table = true
 
innodb_additional_mem_pool_size = 16M
innodb_flush_log_at_trx_commit = 0
innodb_log_buffer_size  = 8M
innodb_buffer_pool_size = 1G
innodb_thread_concurrency =     16
innodb_lock_wait_timeout =     120
innodb_data_file_path   = ibdata1:10M:autoextend
innodb_file_io_threads  = 4
innodb_max_dirty_pages_pct =    90
 
[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid
 
!includedir /etc/my.cnf.d
EOF
 
echo '*               soft    nofile            65535' >> /etc/security/limits.conf
echo '*               hard    nofile            65535' >> /etc/security/limits.conf

32) Setting the database root password

yum install -y expect
 
MYSQL_ROOT_PASSWORD=`date +%s | sha256sum | base64 | head -c 16 ; echo`
 
SECURE_MYSQL=$(expect -c "
 
set timeout 3
spawn mysql_secure_installation
 
expect \"Enter current password for root (enter for none):\"
send \"$CURRENT_MYSQL_PASSWORD\r\"
 
expect \"Set root password?\"
send \"y\r\"
 
expect \"New password:\"
send \"$MYSQL_ROOT_PASSWORD\r\"
 
expect \"Re-enter new password:\"
send \"$MYSQL_ROOT_PASSWORD\r\"
 
expect \"Remove anonymous users?\"
send \"y\r\"
 
expect \"Disallow root login remotely?\"
send \"y\r\"
 
expect \"Remove test database and access to it?\"
send \"y\r\"
 
expect \"Reload privilege tables now?\"
send \"y\r\"
expect eof
")
 
echo "$SECURE_MYSQL"
 
yum remove -y expect
 
if grep -q pass= /etc/webmin/mysql/config; then
  sed -i "/pass=/c\pass=$MYSQL_ROOT_PASSWORD" /etc/webmin/mysql/config
else
  echo pass=$MYSQL_ROOT_PASSWORD >> /etc/webmin/mysql/config
fi

33) Configuring Apache

sed -ie 's/Listen 80/Listen 8080/' /etc/httpd/conf/httpd.conf
echo 'RemoteIPHeader X-Forwarded-For' >> /etc/httpd/conf/httpd.conf
echo "RemoteIPInternalProxy $IP" >> /etc/httpd/conf/httpd.conf
sed -ie 's/%h/%a/' /etc/httpd/conf/httpd.conf
# per https://support.plesk.com/hc/en-us/articles/213399589-Websites-are-slow-and-a-warning-appears-in-logs-mod-fcgid-ap-pass-brigade-failed
echo 'FcgidMaxRequestsPerProcess 500' >> /etc/httpd/conf.d/fcgid.conf
echo 'FcgidOutputBufferSize 0' >> /etc/httpd/conf.d/fcgid.conf
sed -ie 's|LoadModule|#LoadModule|' /etc/httpd/conf.modules.d/00-dav.conf
sed -ie 's|LoadModule|#LoadModule|' /etc/httpd/conf.modules.d/10-php.conf
 
# Maybe we can turn the below ones off.
sed -ie 's/LoadModule proxy/#LoadModule proxy/' /etc/httpd/conf.modules.d/00-proxy.conf
sed -ie 's@#LoadModule proxy_module@LoadModule proxy_module@g' /etc/httpd/conf.modules.d/00-proxy.conf
sed -ie 's@#LoadModule proxy_fcgi_module@LoadModule proxy_fcgi_module@g' /etc/httpd/conf.modules.d/00-proxy.conf
sed -ie 's@LoadModule lbmethod_heartbeat@#LoadModule lbmethod_heartbeat@g' /etc/httpd/conf.modules.d/00-proxy.conf
 
systemctl restart httpd

34) Installing PHP7

yum -y install scl-utils
rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm -Uvhl http://rpms.remirepo.net/enterprise/remi-release-7.rpm
 
yum -y install php72 php72-php-mysqlnd php72-php-curl php72-php-simplexml php72-php-devel php72-php-gd php72-php-json php72-php-mcrypt php72-php-mbstring php72-php-opcache php72-php-pear php72-php-pecl-apcu php72-php-pecl-geoip php72-php-pecl-imagick php72-php-pecl-json-post php72-php-pecl-memcache php72-php-pecl-zip php72-php-pspell php72-php-soap php72-php-xml php72-php-xmlrpc php72-php-pecl-uploadprogress php72-php-imap php72-php-pecl-xmldiff php72-php-bcmath
 
source /opt/remi/php72/enable
yum -y install php72-php-tidy
pear channel-update pear.php.net
pear install Cache_Lite
 
sed -ie 's/upload_max_filesize = 2M/upload_max_filesize = 20M/' /etc/opt/remi/php72/php.ini
sed -ie 's/post_max_size = 8M/post_max_size = 16M/' /etc/opt/remi/php72/php.ini
sed -ie 's/max_execution_time = 30/max_execution_time = 600/' /etc/opt/remi/php72/php.ini
sed -ie 's/max_input_time = 60/max_input_time = 600/' /etc/opt/remi/php72/php.ini
sed -ie 's/memory_limit = 128M/memory_limit = 1280M/' /etc/opt/remi/php72/php.ini 
 
yum -y install php73 php73-php-mysqlnd php73-php-curl php73-php-simplexml php73-php-devel php73-php-gd php73-php-json php73-php-mcrypt php73-php-mbstring php73-php-opcache php73-php-pear php73-php-pecl-apcu php73-php-pecl-geoip php73-php-pecl-imagick php73-php-pecl-json-post php73-php-pecl-memcache php73-php-pecl-zip php73-php-pspell php73-php-soap php73-php-xml php73-php-xmlrpc php73-php-pecl-uploadprogress php73-php-imap php73-php-pecl-xmldiff php73-php-bcmath
 
source /opt/remi/php73/enable
 
yum -y install php73-php-tidy
pear channel-update pear.php.net
pear install Cache_Lite
 
sed -ie 's/upload_max_filesize = 2M/upload_max_filesize = 20M/' /etc/opt/remi/php73/php.ini
sed -ie 's/post_max_size = 8M/post_max_size = 16M/' /etc/opt/remi/php73/php.ini
sed -ie 's/max_execution_time = 30/max_execution_time = 600/' /etc/opt/remi/php73/php.ini
sed -ie 's/max_input_time = 60/max_input_time = 600/' /etc/opt/remi/php73/php.ini
sed -ie 's/memory_limit = 128M/memory_limit = 1280M/' /etc/opt/remi/php73/php.ini
sed -ie 's/disable_functions =/disable_functions = pcntl_exec/' /etc/opt/remi/php73/php.ini

35) Installing drush and wp-cli

# Installing drush
wget https://github.com/drush-ops/drush/releases/download/8.1.16/drush.phar
php drush.phar core-status
chmod +x drush.phar
mv drush.phar /usr/local/bin/drush
drush -y init
 
# Fixing https://github.com/drush-ops/drush/issues/2065
sed -i '/disable_functions/c\disable_functions = pcntl_exec' /etc/php.ini
sed -i '/disable_functions/c\disable_functions = pcntl_exec' /etc/opt/remi/php70/php.ini
 
# Installing wp-cli
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
mv wp-cli.phar /usr/local/bin/wp
if [ ! -d /etc/ag ]; then
  mkdir /etc/ag
fi
#mkdir /etc/ag/wp
#cd /etc/ag/wp
#wget https://raw.githubusercontent.com/wp-cli/wp-cli/v1.5.1/utils/wp-completion.bash
#chmod 755 wp-completion.bash
#echo "source /etc/ag/wp/wp-completion.bash" >> /etc/profile.d/globaliases.sh

36) Setting the time zone to UTC and synchronizing the time

rm -f /etc/localtime
ln -s /usr/share/zoneinfo/UTC /etc/localtime
 
echo "timeserver=pool.ntp.org" >> /etc/webmin/time/config
cd /etc/webmin/webmincron/crons/
cat >150338373415549.cron<< 'EOF'
disabled=0
hours=11,14
days=*
mins=0,52
boot=1
id=150338373415549
weekdays=*
func=sync_time_cron
months=*
module=time
EOF

37) Customizing the control panel

35

38) Disabling slider for Authentic Theme

rm -rf /etc/webmin/authentic-theme
mkdir /etc/webmin/authentic-theme
cd /etc/webmin/authentic-theme
cat > settings.js << 'EOF'
settings_side_slider_enabled=false;
settings_right_default_tab_usermin='mail';
settings_right_default_tab_webmin='virtualmin';
settings_sysinfo_theme_updates=true;
settings_sysinfo_theme_patched_updates=false;
EOF

39) Adapting Virtualmin and Webmin jargon for cPanel users

sh /etc/ag/cp/new-lang.sh 
 
sed -i 's/bandwidth /traffic /g' /etc/webmin/virtual-server/bw-template
sed -i 's/bandwidth /traffic /g' /etc/webmin/virtual-server/warnbw-template
sed -i 's/Bandwidth /Traffic /g' /etc/webmin/virtual-server/bw-template
sed -i 's/Bandwidth /Traffic /g' /etc/webmin/virtual-server/warnbw-template

40) Setting up skeleton directory

mkdir /etc/ag/skel
cd /etc/ag/skel
if [ -d "public_html" ]; then
  rm -rf public_html
fi
mkdir patches sandbox public_html
ln -s public_html www
cd /etc/ag/skel/public_html
cat > index.php << 'EOF'
<html>
<body>
 
<?php
 
$domain=$_SERVER['SERVER_NAME'];
$protocol="http://$domain";
$ssl="https://$domain";
 
function random_color_part() {
    return str_pad( dechex( mt_rand( 0, 255 ) ), 2, '0', STR_PAD_LEFT);
}
 
function random_color() {
    return random_color_part() . random_color_part() . random_color_part();
}
 
$bgcolor=random_color();
 
$date=date('m/d/Y H:i:s', time());
$port=$_SERVER['SERVER_PORT'];
 
function brightness($hex) {
  $r = hexdec(substr($hex,0,2));
  $g = hexdec(substr($hex,2,2));
  $b = hexdec(substr($hex,4,2));
 
  if($r + $g + $b > 301) {
    $txtcolor="#000000";
  } else {
    $txtcolor="#ffffff";
  }
  return $txtcolor;
}
  $txtcolor=brightness($bgcolor);
 
  $text = "<pre style=\"padding: 10px; border:1px solid $txtcolor\"><strong>Time:</strong> $date <br>";
  $text .= "<strong>Background color:</strong> #$bgcolor </pre>";
  $suffix = "<p>Compare different versions of the same page:<br>
<pre style=\"padding: 10px; border:1px solid $txtcolor\">
<strong>AltaCache</strong> at <a style=\"color:$txtcolor;\" href=\"$protocol\">$protocol</a>
<strong>AltaCache through SSL</strong> termination at <a style=\"color:$txtcolor;\" href=\"$ssl\">$ssl</a>
<strong>Apache</strong> version at <a style=\"color:$txtcolor;\" href=\"$protocol:8080\">$protocol:8080</a></pre></p>";
 
if ($port == "8080") {
  $prefix = "<p><strong>Uncached</strong> page with the background color and current time changing <br>on page refresh.</p>";
} else {
$prefix = "<p><strong>Cached</strong> page, so the background color and time captured won't change <br>on page refresh.<br>Expires in 24 hours unless AltaCache is restarted sooner.</p>";
}
?>
 
<body style="font-family: 'Avenir Next',sans-serif; color:<?php print $txtcolor;?>; background-color:#<?php print $bgcolor;?>;">
<div style="position: relative;float: left;top: 300px;left: 50%;transform: translate(-50%, -50%);">
<h1>AltaGrade Demo</h1>
<?php
print $prefix;
print $text;
print $suffix;
 
?>
</div>
 
</body>
</html>
EOF
 
cd /etc/ag/skel/patches
cat > PATCHES.TXT << 'EOF' 
You can place any information about patches of your website below. 
EOF
 
cd /etc/ag/skel
cat > BEST-PRACTICES.TXT << 'EOF'
Your AltaGrade server is configured to take regular backups of all websites'
home directories. Therefore placing large archive or database dump files within
the home directories make backup process very slow and often times cause errors.
It also negatively effects the overall performance of your server and hosted
the websites. That is why it is in your own best interest to keep the home
directories and document roots of your websites clean and tidy.
 
Ideally a typical home directory on a AltaGrade server should contain only this
text file and the following directories:
 
***
cgi-bin
domains
etc
fcgi-bin
logs
Maildir
patches
public_html
sandbox
ssl
tmp
usermails
www -> public_html
***
 
We recommend to place all non-standard or temporary files in the 'sandbox'
directory, which is excluded from automatic backups.
 
If you have further questions on how to organize your files, please open a
ticket on https://my.altagrade.com. 
EOF

41) Giving sudo user an admin privilege for Webmin

yum -y install "perl(IO::Pty)"
echo "sudo=1" >> /etc/webmin/miniserv.conf
passwd -d root

42) Installing and configuring Pound

sed -i '/Listen/c\#Listen' /etc/httpd/conf.d/ssl.conf
yum -y install Pound && systemctl enable pound && systemctl start pound
mv /etc/pound.cfg /etc/pound.cfg.orig
cat > /etc/pound.cfg << EOF
ListenHTTP
  Address ${IP}
  Port 80
  Service
    URL "/.well-known/acme-challenge/.*"
    BackEnd
      Address ${IP}
      Port 8888
    End
  End
End
 
Service
    BackEnd
	Address ${IP}
        Port    8888
    End
End
 
EOF

43) Installing and configuring Varnish

15

44) Generating pre.sh file

cat > /etc/ag/scripts/pre.sh << 'EOF'
#!/bin/sh

exit 0
EOF
chmod 755 /etc/ag/scripts/pre.sh

45) Generating post.sh file

28

46) Disabling the port mapping service and installing Advanced Policy Firewall

# per https://superuser.com/questions/1083882/block-port-111-on-centos-7

systemctl stop rpcbind.socket && systemctl disable rpcbind.socket
systemctl mask fail2ban && systemctl stop fail2ban
systemctl mask firewalld && systemctl stop firewalld
systemctl enable iptables && systemctl start iptables
 
cd /usr/src
wget http://www.rfxn.com/downloads/apf-current.tar.gz
tar xzf apf-current.tar.gz
rm -f apf-current.tar.gz
cd apf*
./install.sh 
chkconfig apf on
sed -ie "s/eth0/$IFACE/" /etc/apf/conf.apf
sed -ie 's/DEVEL_MODE="1"/DEVEL_MODE="0"/' /etc/apf/conf.apf
sed -ie 's/SET_MONOKERN="0"/SET_MONOKERN="1"/' /etc/apf/conf.apf
sed -ie 's/ICMP_LIM="30\/s"/ICMP_LIM="100\/s"/' /etc/apf/conf.apf
sed -ie 's/DLIST_PHP="0"/DLIST_PHP="1"/' /etc/apf/conf.apf
sed -ie 's/DLIST_SPAMHAUS="0"/DLIST_SPAMHAUS="1"/' /etc/apf/conf.apf
sed -ie 's/DLIST_DSHIELD="0"/DLIST_DSHIELD="1"/' /etc/apf/conf.apf
sed -ie 's/IG_TCP_CPORTS=/#IG_TCP_CPORTS=/' /etc/apf/conf.apf
sed -ie 's/IG_UDP_CPORTS=/#IG_UDP_CPORTS=/' /etc/apf/conf.apf
sed -i '2s/^/IG_UDP_CPORTS="53,123,465,587,953,2525,6277,1043,6081,6082,8983"\n/' /etc/apf/conf.apf
sed -i "2s/^/IG_TCP_CPORTS="\"25,53,80,110,143,443,465,587,953,993,995,1043,2525,5900_5910,8079,8080,8888,8983,10000_10010,20000,${PORT}\""\n/" /etc/apf/conf.apf
apf -r
/usr/local/sbin/apf -a 65.49.80.104 "Do not remove this IP address. It belongs to AltaGrade."

47) Installing and configuring Brute Force Detection

cd /usr/src
wget http://www.rfxn.com/downloads/bfd-current.tar.gz
tar xzf bfd-current.tar.gz
rm -f bfd-current.tar.gz*
cd bfd-1.5*
./install.sh
sed -ie 's/TRIG="15"/TRIG="5"/' /usr/local/bfd/conf.bfd
sed -ie 's/EMAIL_ALERTS="0"/EMAIL_ALERTS="1"/' /usr/local/bfd/conf.bfd
sed -ie 's/EMAIL_ADDRESS="root"/EMAIL_ADDRESS="security"/' /usr/local/bfd/conf.bfd
rm -f /usr/local/bfd/alert.bfd
echo 'EB=0' >> /usr/local/bfd/alert.bfd
echo 'if [ "$EMAIL_LOGLINES" == "" ]; then' >> /usr/local/bfd/alert.bfd
echo '        EMAIL_LOGLINES=50' >> /usr/local/bfd/alert.bfd
echo 'fi' >> /usr/local/bfd/alert.bfd
echo 'EV=`nice -n 19 tail -n 5000 $LP | grep $ATTACK_HOST | tail -n $EMAIL_LOGLINES`' >> /usr/local/bfd/alert.bfd
echo 'cat <<EOF' >> /usr/local/bfd/alert.bfd
echo '' >> /usr/local/bfd/alert.bfd
echo '$ATTACK_HOST has been blocked and blacklisted by AltaGrade for exceeded login failures on $HOSTNAME.' >> /usr/local/bfd/alert.bfd
echo "If the IP address belongs to your team, then please clear it from the firewall's block-list and add it allowed hosts." >> /usr/local/bfd/alert.bfd
echo 'Alternatively file a support request on https://my.altagrade.com and we will gladly do it for you.' >> /usr/local/bfd/alert.bfd
echo '' >> /usr/local/bfd/alert.bfd
echo 'SOURCE ADDRESS: $ATTACK_HOST' >> /usr/local/bfd/alert.bfd
echo 'TARGET SERVICE: $MOD' >> /usr/local/bfd/alert.bfd
echo 'FAILED LOGINS: $ATTACK_COUNT' >> /usr/local/bfd/alert.bfd
echo 'EXECUTED COMMAND: $BAN_COMMAND' >> /usr/local/bfd/alert.bfd
echo '' >> /usr/local/bfd/alert.bfd
echo "SOURCE LOGS FROM SERVICE '\$MOD' (GMT \$TIME_ZONE):" >> /usr/local/bfd/alert.bfd
echo '' >> /usr/local/bfd/alert.bfd
echo '$EV' >> /usr/local/bfd/alert.bfd
echo '' >> /usr/local/bfd/alert.bfd
echo '-----------------------------------------------' >> /usr/local/bfd/alert.bfd
echo 'AltaGrade Brute Force Detection System' >> /usr/local/bfd/alert.bfd
echo '' >> /usr/local/bfd/alert.bfd
echo 'EOF' >> /usr/local/bfd/alert.bfd
 
sed -ie 's/#root:/root:/' /etc/aliases
sed -ie 's/marc/[email protected]/' /etc/aliases
echo "#owner: ${OWNER}" >> /etc/aliases
newaliases

48) Installing Linux Malware Detect

wget http://www.rfxn.com/downloads/maldetect-current.tar.gz
tar xzf maldetect-current.tar.gz
rm -rf maldetect-current.tar.gz
cd maldetect*
./install.sh
# Installing inotify-tools per https://www.rfxn.com/appdocs/README.maldetect
yum -y install inotify-tools
# Configuring malware detection settings
sed -ie 's/email_alert="0"/email_alert="1"/' /usr/local/maldetect/conf.maldet
sed -ie 's/email_addr="[email protected]"/email_addr="security"/' /usr/local/maldetect/conf.maldet
sed -ie 's/email_ignore_clean="1"/email_ignore_clean="0"/' /usr/local/maldetect/conf.maldet
sed -ie 's/quarantine_hits="0"/quarantine_hits="1"/' /usr/local/maldetect/conf.maldet
sed -ie 's/quarantine_clean="0"/quarantine_clean="1"/' /usr/local/maldetect/conf.maldet
sed -ie 's/quarantine_suspend_user="0"/quarantine_suspend_user="1"/' /usr/local/maldetect/conf.maldet
echo "/home/.*/public_html/stats" >> /usr/local/maldetect/ignore_paths
echo "/home/.*/domains/.*/public_html/stats" >> /usr/local/maldetect/ignore_paths

49) Calculating execution time

duration=$SECONDS
executed="$(($duration / 60)) minutes and $(($duration % 60)) seconds"
echo "The installation took $executed"

50) Removing unnecessary services and installing altagrade package.

systemctl stop chronyd && yum -y remove chrony
systemctl stop fail2ban && yum -y remove fail2ban*
rm -rf /var/log/fail2ban.log
systemctl stop wpa_supplicant && yum -y remove wpa_supplicant
#yum -y install altagrade
chown -R root:bin /etc/webmin
systemctl restart webmin

51) Sending the final e-mail notification

cd /
mv /usr/src/etc-ag.tgz .
tar -xjf etc-ag.tgz
 
yum -y install mailx
echo "Installation of AltaOS on ${HOSTNAME} completed in $executed. The system is rebooting..." | mail -s "AltaOS has been installed on ${HOSTNAME}" 6504506428@tmomail.net
 
rm -f /root/recipe1.sh
rm -f /usr/src/altaos-install.sh
 
updatedb
echo "Rebooting the system..."
reboot