This post was created to assist some colleagues in Afghanistan, who are creating a server for running Laravel. My experience is with WordPress, but the principles should be the same.
These instructions apply to Ubuntu server. The version is Ubuntu 19.04, there may be slight variations between Ubuntu versions, but the principles apply. Note that if you are doing this for practice purposes, it may be a good idea to create a practice subdomain in your DNS manager, for example, practice.example.com, and then every time you delete your practice server and create a new one, you can just change the IP address in your DNS manager (e.g. Namecheap, GoDaddy, DogitalOcean, etc).
STEP 1: Make sure everything is up to date.
sudo apt update sudo apt upgrade -y
STEP 2: Install Apache web server and configure service
sudo apt install -y apache2 apache2-utils sudo chown www-data:www-data /var/www/html/ -R sudo systemctl stop apache2.service sudo systemctl start apache2.service sudo systemctl enable apache2.service
STEP 3: Create a temporary index until done with WordPress install
sudo cd /var/www/html sudo rm index.html sudo echo "<h1>Working here. Nothing here yet.</h1>" > index.html
STEP 4: Install a digital certificate software and generate a certificate for enabling HTTPS
The technology we will use is from the Electronic Frontier Foundation, and it is called “Let’s Encrypt”. The software that is used to install and manage certificates is called “certbot”. I recommend that you visit the Let’s Encrypt website and learn about certificates, the certbot technology, and how to manage HTTPS on your website.
sudo apt install software-properties-common -y sudo add-apt-repository universe -y sudo add-apt-repository ppa:certbot/certbot -y sudo apt install certbot python-certbot-apache -y sudo certbot --apache -d example.com -d www.example.com sudo certbot renew --dry-run
STEP 5: More secure with a UFW firewall
sudo apt install -y ufw sudo ufw allow ssh sudo ufw allow http sudo ufw allow https sudo ufw enable sudo ufw status verbose
STEP 6: Install PHP
sudo apt install -y php libapache2-mod-php php-common php-mysql php-gmp php-ldap php-curl php-intl php-mbstring php-xmlrpc php-gd php-bcmath php-xml php-cli php-zip php-soap sudo nano /etc/php/7.2/apache2/php.ini
Change
post_max_size = 100M
upload_max_filesize = 100M
memory_limit=256M
STEP 7: Install MariaDb
Note that I am using MaridDb, the same commands work for MySQL.
sudo apt install -y mariadb-server mariadb-client sudo systemctl stop mariadb.service sudo systemctl start mariadb.service sudo systemctl enable mariadb.service sudo mysql_secure_installation
Make sure you choose a good password for the root database user when prompted.
STEP 8: Set time and timezone
The time and timezone settings should always be set correctly, and an NNTP daemon should be running. On Ubuntu, this is usually the case after an install, but it is still worth checking. Incorrect time settings can provide an attack surface for attackers. Set the timezone that corresponds to either your server location, or the main time zone where it will be used, depending on your needs.
sudo timedatectl set-timezone Africa/Johannesburg
You should check the date as well just to be sure.
date
You should get something like
Sat Feb 23 17:59:06 SAST 2019
Make sure that timesyncd is running so that the server time is always updated from an Internet time server.
timedatectl
You should see something like
Local time: Sat 2019-02-23 17:59:45 SA Universal time: Sat 2019-02-23 15:59:45 UTC RTC time: Sat 2019-02-23 15:59:46 Time zone: Africa/Johannesburg (SAST, +0200) System clock synchronized: yes systemd-timesyncd.service active: yes
If timesyncd isn’t active, turn it on with timedatectl (in the example, it is already running).
sudo timedatectl set-ntp on
STEP 9: Install WordPress
You are probably not going to use WordPress, but this would probably be the point at which you install Laravel. Since I prefer WordPress for content sites, and Laravel for doing development of totally new stuff, I will stick with WordPress here. Also, I do not know Laravel, I leave that to colleagues for now. Just consider this the point at which you install whatever PHP application you are using.
sudo cd /var/www sudo mkdir downloads cd downloads sudo wget https://wordpress.org/latest.tar.gz sudo tar -xzvf latest.tar.gz -C /var/www/html/ cd ../html/wordpress sudo mv * .. cd .. sudo rm wordpress -R
Now you need to create the database for WordPress. Note that you can use ‘mysql -u root’ or ‘mysql -u root -p’ depending on your password settings and whether you are logged in as root user.
mysql -u root -p
Once the database is running, you can enter the commands below. Change users and passwords according to what you require.
CREATE DATABASE mywpdatabasename; GRANT ALL PRIVILEGES ON mywpdatabasename.* TO "whateverusernameyouwant"@"localhost" IDENTIFIED BY "top-secret-password"; FLUSH PRIVILEGES; EXIT;
Next you need to set up your WordPress config file and edit some setting in it. Also, you can remove the index.html file that you created earlier so the WordPress PHP index is then the default index file for the server.
sudo mv wp-config-sample.php wp-config.php sudo nano wp-config.php sudo mv index.html index.tmp
Next you need to configure WordPress database settings. To do this you need to edit wp-config.php and make some changes therein.
sudo nano wp-config.php
Insert the database settings that you set for your MySQL settings earlier. Note that you can also define your preferred character set here.
/** The name of the database for WordPress */ define( 'DB_NAME', 'mywpdatabasename' ); /** MySQL database username */ define( 'DB_USER', 'whateverusernameyouwant' ); /** MySQL database password */ define( 'DB_PASSWORD', 'top-secret-password' ); /** MySQL hostname */ define( 'DB_HOST', 'localhost' ); /** Database Charset to use in creating database tables. */ define( 'DB_CHARSET', 'utf8mb4' ); /** The Database Collate type. Don't change this if in doubt. */ define( 'DB_COLLATE', 'utf8mb4_unicode_ci' );
You also want to set up WordPress so that it can be updated and plugins installed without having to go through FTP or manual uploads. To do this you need to edit wp-config.php again.
sudo nano wp-config.php
Add this to the end of the file:
/** Set up direct method for updating plugins */ define('FS_METHOD','direct');
Once you have done the above steps, you can open WordPress in your browser, for example https://practice.example.com.
STEP 10: A little more secure hardening
We can hide the Apache Version and Operating System
sudo cp /etc/apache2/apache2.conf /etc/apache2/apache2.conf.bak sudo cp /etc/apache2/conf-enabled/security.conf /etc/apache2/conf-enabled/security.conf.bak sudo nano /etc/apache2/conf-enabled/security.conf
Set the following:
ServerSignature Off ServerTokens Prod
Then reload Apache to pick up the settings.
systemctl reload apache2
Another useful thing to do is install mod_evasive for denial of service (DOS) attack protection.
apt install libapache2-mod-evasive -y nano /etc/apache2/mods-enabled/evasive.conf mkdir /var/log/mod_evasive chown -R www-data:www-data /var/log/mod_evasive systemctl restart apache2
Something else that is a good idea to install is intrusion prevention, such as Fail2Ban. Fail2Ban is an intrusion prevention software framework that protects computer servers from brute-force attacks. Fail2Ban is a Python application that operates by monitoring log files (e.g. /var/log/auth.log, /var/log/apache/access.log, etc.) for selected entries and running scripts based on them. Most commonly this is used to block selected IP addresses that may belong to hosts that are trying to breach the system’s security. Install it as follows:
sudo apt install -y fail2ban sudo systemctl start fail2ban sudo systemctl enable fail2ban sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local sudo nano /etc/fail2ban/jail.local
In that file, enter the following if it is not already there.
Insert [sshd] enabled = true port = 22 filter = sshd logpath = /var/log/auth.log maxretry = 3
Then restart fail2ban service.
sudo systemctl restart fail2ban
If you ever need to unban an IP address, you can use:
sudo fail2ban-client set sshd unbanip IP_ADDRESS
There are other things that can be done to harden and secure your server further, but this will probably be enough for now. I will try to keep this document updated. Please ask on the Slack channel if you have any questions.
If you want to read more on server hardening, Geekflare has a good article at: https://geekflare.com/apache-web-server-hardening-security/
STEP 11: Making sure file permissions are correct
Run these commands inside the folder of the website
/var/www/html/ or /var/www/example.com/
cd /var/www/html find . -type f -exec chmod 664 {} + find . -type d -exec chmod 775 {} + chmod 660 wp-config.php
What this does is find all files and change them to 664 permissions (), and find all folders (directories) and change them to 775 permissions (). Then the config file, wp-config.php, is given a 660 permission. More on Linux file and directory permissions at https://www.linux.com/learn/getting-know-linux-file-permissions