Last active
December 16, 2020 17:45
-
-
Save aaronymousX/99b366c4c4cbf59073b66505a702457a to your computer and use it in GitHub Desktop.
ServerSetup.sh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
clear | |
# Checks for ROOT privileges | |
echo "============================================" | |
echo "Checking for ROOT" | |
echo "============================================" | |
if [ "$USER" = "root" ] | |
then | |
echo "Success! You are ROOT" | |
else | |
echo >&2 "ERROR: You must be a root user to execute this script." | |
exit | |
fi | |
# Update and install required packages from apt | |
echo "============================================" | |
echo "Upgrading and installing pre-requisits..." | |
echo "============================================" | |
apt update | |
apt upgrade -y | |
apt dist-upgrade -y | |
apt install perl -y | |
apt install ufw -y | |
apt install apache2 -y | |
apt install mysql-server -y | |
apt install php libapache2-mod-php php-mcrypt php-mysql php-cli php-mbstring php-gettext -y | |
echo "DONE: Upgrades complete, pre-requisits installed." | |
#Add sudo user | |
echo "============================================" | |
echo "Do you require a sudo user? (y/n)" | |
echo "============================================" | |
read -e setupsudo | |
if [ "$setupsudo" == y ] ; then | |
echo "Username (Enter for default 'sudouser'): " | |
read -e sudouser=${sudouser:-sudouser} | |
echo "Password: " | |
read -s sudopass | |
echo "Public SSH Key (ED25519 recommended): " | |
read -e sshkey | |
egrep "^$sudouser" /etc/passwd >/dev/null | |
if [ $? -eq 0 ]; then | |
echo "$sudouser already exists!" | |
exit 1 | |
else | |
saltpass=$(perl -e 'print crypt($ARGV[0], "password")' $sudopass) | |
useradd -m -p $saltpass $sudouser | |
usermod -aG sudo $sudouser | |
mkdir /home/$sudouser/.ssh | |
chmod 700 /home/$sudouser/.ssh | |
touch /home/$sudouser/.ssh/authorized_keys | |
echo $sshkey >> /home/$sudouser/.ssh/authorized_keys | |
chmod 600 /home/$sudouser/.ssh/authorized_keys | |
chown -R $sudouser /home/$sudouser/.ssh | |
[ $? -eq 0 ] && echo "DONE: User has been added to system!" || echo "Failed to add a user!" | |
fi | |
else | |
echo "Sudo user not required." | |
exit 2 | |
fi | |
# Enable and configure UFW | |
echo "============================================" | |
echo "Enabling UFW for Apache and OpenSSH..." | |
echo "============================================" | |
ufw allow OpenSSH | |
ufw allow in "Apache Full" | |
ufw enable | |
echo "DONE: UFW enabled for Apache and OpenSSH." | |
# Configure PHP | |
echo "============================================" | |
echo "Configuring PHP..." | |
echo "Manually remove /var/www/html/info.php after testing" | |
echo "============================================" | |
# Upgrade PHP index file | |
rm /etc/apache2/mods-enabled/dir.conf | |
touch /etc/apache2/mods-enabled/dir.conf | |
cat > /etc/apache2/mods-enabled/dir.conf <<'EOL' | |
<IfModule mod_dir.c> | |
DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm | |
</IfModule> | |
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet | |
EOL | |
# Crete PHP info to easliy check PHP configuration | |
touch /var/www/html/info.php | |
cat > /var/www/html/info.php <<'EOL' | |
<?php | |
phpinfo(); | |
?> | |
EOL | |
echo "DONE: PHP configured." | |
# Required service restarts to accept changes | |
echo "============================================" | |
echo "Restarting Services..." | |
echo "============================================" | |
systemctl restart apache2 | |
echo "DONE: Services restarted." | |
#Install and configure Wordpress | |
echo "============================================" | |
echo "WordPress Install Script" | |
echo "============================================" | |
echo "Do you need to setup a MySQL database? (y/n)" | |
read -e setupmysql | |
if [ "$setupmysql" == y ] ; then | |
echo "MySQL Admin User (Enter for default 'root'): " | |
read -e mysqluser | |
mysqluser=${mysqluser:-root} | |
echo "MySQL Admin Password (Use a secure password): " | |
read -s mysqlpass | |
echo "MySQL Host (Enter for default 'localhost'): " | |
read -e mysqlhost | |
mysqlhost=${mysqlhost:-localhost} | |
fi | |
echo "WP Database Name: " | |
read -e dbname | |
echo "WP Database User: " | |
read -e dbuser | |
echo "WP Database Password: " | |
read -s dbpass | |
echo "WP Database Table Prefix [numbers, letters, and underscores only] (Enter for default 'wp_'): " | |
read -e dbtable | |
dbtable=${dbtable:-wp_} | |
echo "Do basic security hardening of wp-config and htaccess? (y/n)" | |
read -e harden | |
if [ "$harden" == y ] ; then | |
echo "Key for updating: " | |
read -e hardenkey | |
fi | |
echo "Last chance - sure you want to run the install? (y/n)" | |
read -e run | |
if [ "$run" == y ] ; then | |
if [ "$setupmysql" == y ] ; then | |
echo "============================================" | |
echo "Setting up the database." | |
echo "============================================" | |
mysql_secure_installation --use-default | |
#login to MySQL, add database, add user and grant permissions | |
dbsetup="create database $dbname;GRANT ALL PRIVILEGES ON $dbname.* TO $dbuser@$mysqlhost IDENTIFIED BY '$dbpass';FLUSH PRIVILEGES;" | |
mysql -u $mysqluser -p$mysqlpass -e "$dbsetup" | |
if [ $? != "0" ]; then | |
echo "============================================" | |
echo "[Error]: Database creation failed. Aborting." | |
echo "============================================" | |
exit 1 | |
fi | |
fi | |
echo "============================================" | |
echo "Installing WordPress for you." | |
echo "============================================" | |
#download wordpress | |
echo "Downloading..." | |
cd /tmp | |
curl -O https://wordpress.org/latest.tar.gz | |
#unzip wordpress | |
echo "Unpacking..." | |
tar -zxf latest.tar.gz | |
#move /wordpress/* files to this dir | |
echo "Moving..." | |
mv wordpress/* /var/www/html/ | |
echo "Configuring..." | |
#create wp config | |
cd /var/www/html/ | |
mv wp-config-sample.php wp-config.php | |
#set database details with perl find and replace | |
perl -pi -e "s'database_name_here'"$dbname"'g" wp-config.php | |
perl -pi -e "s'username_here'"$dbuser"'g" wp-config.php | |
perl -pi -e "s'password_here'"$dbpass"'g" wp-config.php | |
perl -pi -e "s/\'wp_\'/\'$dbtable\'/g" wp-config.php | |
#set WP salts | |
perl -i -pe' | |
BEGIN { | |
@chars = ("a" .. "z", "A" .. "Z", 0 .. 9); | |
push @chars, split //, "!@#$%^&*()-_ []{}<>~\`+=,.;:/?|"; | |
sub salt { join "", map $chars[ rand @chars ], 1 .. 64 } | |
} | |
s/put your unique phrase here/salt()/ge | |
' wp-config.php | |
#create uploads folder and set permissions | |
mkdir wp-content/uploads | |
chmod 775 wp-content/uploads | |
if [ "$harden" == y ] ; then | |
echo "============================================" | |
echo "Hardening." | |
echo "============================================" | |
#remove readme.html | |
rm readme.html | |
#debug extras | |
perl -pi -e "s/define\('WP_DEBUG', false\);/define('WP_DEBUG', false);\n\/** Useful extras *\/ \nif (WP_DEBUG) { \n\tdefine('WP_DEBUG_LOG', true); \n\tdefine('WP_DEBUG_DISPLAY', false); \n\t\@ini_set('display_errors',0);\n}/" wp-config.php | |
# key access to mods | |
find="/* That's all, stop editing! Happy blogging. */" | |
replace="/** Disallow theme and plugin editor in admin. Updates only with query var */\ndefine( 'DISALLOW_FILE_EDIT', true );\nif ( \\$\_REQUEST['key'] == '$hardenkey' ) {\n\tsetcookie( 'updatebypass', 1 );\n} elseif ( ! \\$\_COOKIE['updatebypass'] ) {\n\tdefine( 'DISALLOW_FILE_MODS', true );\n}\n\n/* That's all, stop editing! Happy blogging. */" | |
perl -pi -e "s{\Q$find\E}{$replace}" wp-config.php | |
#create root .htaccess with some useful starters | |
cat > .htaccess <<'EOL' | |
# Protect this file | |
<Files ~ "^\.ht"> | |
Order allow,deny | |
Deny from all | |
</Files> | |
# Prevent directory listing | |
Options -Indexes | |
## BEGIN 6G FIREWALL/BLACKLIST | |
## @ https://perishablepress.com/6g/ | |
# 6G:[QUERY STRINGS] | |
<IfModule mod_rewrite.c> | |
RewriteEngine On | |
RewriteCond %{QUERY_STRING} (eval\() [NC,OR] | |
RewriteCond %{QUERY_STRING} (127\.0\.0\.1) [NC,OR] | |
RewriteCond %{QUERY_STRING} ([a-z0-9]{2000,}) [NC,OR] | |
RewriteCond %{QUERY_STRING} (javascript:)(.*)(;) [NC,OR] | |
RewriteCond %{QUERY_STRING} (base64_encode)(.*)(\() [NC,OR] | |
RewriteCond %{QUERY_STRING} (GLOBALS|REQUEST)(=|\[|%) [NC,OR] | |
RewriteCond %{QUERY_STRING} (<|%3C)(.*)script(.*)(>|%3) [NC,OR] | |
RewriteCond %{QUERY_STRING} (\\|\.\.\.|\.\./|~|`|<|>|\|) [NC,OR] | |
RewriteCond %{QUERY_STRING} (boot\.ini|etc/passwd|self/environ) [NC,OR] | |
RewriteCond %{QUERY_STRING} (thumbs?(_editor|open)?|tim(thumb)?)\.php [NC,OR] | |
RewriteCond %{QUERY_STRING} (\'|\")(.*)(drop|insert|md5|select|union) [NC] | |
RewriteRule .* - [F] | |
</IfModule> | |
# 6G:[REQUEST METHOD] | |
<IfModule mod_rewrite.c> | |
RewriteCond %{REQUEST_METHOD} ^(connect|debug|move|put|trace|track) [NC] | |
RewriteRule .* - [F] | |
</IfModule> | |
# 6G:[REFERRERS] | |
<IfModule mod_rewrite.c> | |
RewriteCond %{HTTP_REFERER} ([a-z0-9]{2000,}) [NC,OR] | |
RewriteCond %{HTTP_REFERER} (semalt.com|todaperfeita) [NC] | |
RewriteRule .* - [F] | |
</IfModule> | |
# 6G:[REQUEST STRINGS] | |
<IfModule mod_alias.c> | |
RedirectMatch 403 (?i)([a-z0-9]{2000,}) | |
RedirectMatch 403 (?i)(https?|ftp|php):/ | |
RedirectMatch 403 (?i)(base64_encode)(.*)(\() | |
RedirectMatch 403 (?i)(=\\\'|=\\%27|/\\\'/?)\. | |
RedirectMatch 403 (?i)/(\$(\&)?|\*|\"|\.|,|&|&?)/?$ | |
RedirectMatch 403 (?i)(\{0\}|\(/\(|\.\.\.|\+\+\+|\\\"\\\") | |
RedirectMatch 403 (?i)(~|`|<|>|:|;|,|%|\\|\s|\{|\}|\[|\]|\|) | |
RedirectMatch 403 (?i)/(=|\$&|_mm|cgi-|etc/passwd|muieblack) | |
RedirectMatch 403 (?i)(&pws=0|_vti_|\(null\)|\{\$itemURL\}|echo(.*)kae|etc/passwd|eval\(|self/environ) | |
RedirectMatch 403 (?i)\.(aspx?|bash|bak?|cfg|cgi|dll|exe|git|hg|ini|jsp|log|mdb|out|sql|svn|swp|tar|rar|rdf)$ | |
RedirectMatch 403 (?i)/(^$|(wp-)?config|mobiquo|phpinfo|shell|sqlpatch|thumb|thumb_editor|thumbopen|timthumb|webshell)\.php | |
</IfModule> | |
# 6G:[USER AGENTS] | |
<IfModule mod_setenvif.c> | |
SetEnvIfNoCase User-Agent ([a-z0-9]{2000,}) bad_bot | |
SetEnvIfNoCase User-Agent (archive.org|binlar|casper|checkpriv|choppy|clshttp|cmsworld|diavol|dotbot|extract|feedfinder|flicky|g00g1e|harvest|heritrix|httrack|kmccrew|loader|miner|nikto|nutch|planetwork|postrank|purebot|pycurl|python|seekerspider|siclab|skygrid|sqlmap|sucker|turnit|vikspider|winhttp|xxxyy|youda|zmeu|zune) bad_bot | |
# Apache < 2.3 | |
<IfModule !mod_authz_core.c> | |
Order Allow,Deny | |
Allow from all | |
Deny from env=bad_bot | |
</IfModule> | |
# Apache >= 2.3 | |
<IfModule mod_authz_core.c> | |
<RequireAll> | |
Require all Granted | |
Require not env bad_bot | |
</RequireAll> | |
</IfModule> | |
</IfModule> | |
# 6G:[BAD IPS] | |
<Limit GET HEAD OPTIONS POST PUT> | |
Order Allow,Deny | |
Allow from All | |
# uncomment/edit/repeat next line to block IPs | |
# Deny from 123.456.789 | |
</Limit> | |
## END 6G FIREWALL/BLACKLIST | |
## BEGIN htauth basic authentication | |
# STAGING | |
Require all denied | |
AuthType Basic | |
AuthUserFile /etc/apache2/wp-login | |
AuthName "Please Authenticate" | |
Require valid-user | |
# LIVE - prevent wp-login brute force attacks from causing load | |
#<FilesMatch "^(wp-login|xmlrpc)\.php$"> | |
# AuthType Basic | |
# AuthUserFile /etc/apache2/wp-login | |
# AuthName "Please Authenticate" | |
# Require valid-user | |
#</FilesMatch> | |
# Exclude the file upload and WP CRON scripts from authentication | |
#<FilesMatch "(async-upload\.php|wp-cron\.php)$"> | |
# Satisfy Any | |
# Order allow,deny | |
# Allow from all | |
# Deny from none | |
#</FilesMatch> | |
## END htauth | |
## BEGIN WP file protection | |
<Files wp-config.php> | |
order allow,deny | |
deny from all | |
</Files> | |
# WP includes directories | |
<IfModule mod_rewrite.c> | |
RewriteEngine On | |
RewriteBase / | |
RewriteRule ^wp-admin/includes/ - [F,L] | |
RewriteRule !^wp-includes/ - [S=3] | |
# note - comment out next line on multisite | |
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L] | |
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L] | |
RewriteRule ^wp-includes/theme-compat/ - [F,L] | |
</IfModule> | |
## END WP file protection | |
# Prevent author enumeration | |
RewriteCond %{REQUEST_URI} !^/wp-admin [NC] | |
RewriteCond %{QUERY_STRING} author=\d | |
RewriteRule ^ /? [L,R=301] | |
EOL | |
#create .htaccess to protect uploads directory | |
cat > wp-content/uploads/.htaccess <<'EOL' | |
# Protect this file | |
<Files .htaccess> | |
Order Deny,Allow | |
Deny from All | |
</Files> | |
# whitelist file extensions to prevent executables being | |
# accessed if they get uploaded | |
order deny,allow | |
deny from all | |
<Files ~ ".(docx?|xlsx?|pptx?|txt|pdf|xml|css|jpe?g|png|gif)$"> | |
allow from all | |
</Files> | |
EOL | |
fi | |
# Install and configure PhpMyAdmin | |
echo "============================================" | |
echo "Installing and configuring PhpMyAdmin" | |
echo "============================================" | |
apt install phpmyadmin -y | |
phpenmod mcrypt | |
phpenmod mbstring | |
echo "============================================" | |
echo "Cleaning up..." | |
echo "============================================" | |
#remove wordpress/ dir | |
rmdir /tmp/wordpress | |
#remove zip file | |
rm /tmp/wordpress/latest.tar.gz | |
#remove bash script if it exists in this dir | |
[[ -f "wp.sh" ]] && rm "wp.sh" | |
echo "=========================" | |
echo "[Success]: Setup is complete." | |
echo "=========================" | |
# Setting up persistent swap file | |
echo "============================================" | |
echo "Creating swap..." | |
echo "============================================" | |
swapoff -a | |
fallocate -l 4G /swapfile | |
chmod 600 /swapfile | |
mkswap /swapfile | |
swapon /swapfile | |
cp /etc/fstab /etc/fstab.bak | |
echo '/swapfile none swap sw 0 0' | tee -a /etc/fstab | |
sysctl vm.swappiness=10 | |
echo 'vm.swappiness=10' | tee -a /etc/sysctl.conf | |
sysctl vm.vfs_cache_pressure=50 | |
echo 'vm.vfs_cache_pressure=50' | tee -a /etc/sysctl.conf | |
echo "============================================" | |
echo "Congrats! Setup complete" | |
echo "============================================" | |
exit |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment