Ubuntu 18.04 LTS

These instructions are for Ubuntu 18.04 on a hosted VPS provider

This class is the most critical as it will ultimately determine whether your server works or not. Make sure you have at least a 20-minute block of uninterrupted time before you get started. It should also be done in one fell swoop since we’ll be configuring our firewall to keep the bad guys out!

Virtualization Drivers

When given the option, we install Ubuntu using the Intel Pro/1000 virtual network card and the Virtio disk driver.


sr0           1024M
vda             20G
├─vda1 ext4     19G /
├─vda2           1K
└─vda5 swap   1022M [SWAP]

Ok, start your engines!

1. Change The Root Password, Then Add A Sudo User

Once your server has been spun-up, login as root via SSH and change the root password by typing:

$ passwd

Done? Good. With great power comes great responsibility. So, let’s tone things down abit and create our own personal account with a lower set of system privileges. We’ll login with this user from now on. Type:

$ adduser mycoolusername

Follow the prompts. Once you’r done, add your user account to the sudo group, by typing:

$ adduser mycoolusername sudo

Deleting Users

You may delete a user by typing deluser mycoolusername. Refer to the official Ubuntu documentation as well as the man pages for additional details.

This will add your user to the sudo group and allow it to use the sudo command. Now log off by typing

$ exit

Now log back in as the new user you just created.

2. Update the Network Interfaces File

There are 2 principal breaking changes during the transition from 14.04 LTS to 16.04 LTS. First eth0 is neither the default nor a valid interface name. Second, the default network configuration is now set to dhcp instead of a static IP address. Here’s the contents of our interface file after a fresh install:

$ sudo nano /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto ens3
iface ens3 inet dhcp

In the above, note the items in red: the ens3 interface name and the dhcp network config. You will need to change dhcp to static and add the following 4 new lines.:

 auto ens3
  iface ens3 inet static
   address nnn.nnn.nnn.nnn
   gateway nnn.nnn.nnn.1

IMPORTANT: Replace nnn with the corresponding portions (octets) of your actual IP address

3. Name Your Server (Hostname) and Add Its Fully Qualified Domain Name (FQDN)

Note that the hostname is not tied to your your server’s websites or any applications residing on it. The hostname is nothing more than a unique name for your server. We edit the hostname file and update (re-map) the directive to that file.

To name your server create a hostname entry like so:

$ echo "myReallyCoolServerName" > /etc/hostname
$ hostname -F /etc/hostname

The next step is very important and entails two alternatives. You may either have your hostname mapped to to the localhost address (i.e., or map your server’s IP address to your hostname. The major takeaway is that you should edit your /etc/hosts file so the server resolves the FQDN to your localhost.

$ sudo nano /etc/hosts

If Package-x is Not Available

Run the following to install “Package-x”:

$ apt-get install package-x

Uninstalling Programs and Packages

$ apt-get purge package-x

Option 1: FQDN Localhost Mapping       myReallyCoolServerName       ubuntu

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Option 2: FQDN IP Address Mapping

Below is an alternate set-up. Be sure to swap out with your server’s actual IP address:       localhost       ubuntu    myReallyCoolServerName

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Option 3: localhost + domain name to localhost, FQDN to localhost and Domain to IP Address Mapping      localhost myDomainName.com       myReallyCoolServerName    myDomainName.com

# The following lines are desirable for IPv6 capable hosts

We’ll now reboot our server to load these changes:

$ sudo reboot

4. Update and Upgrade Server Packages using apt-get

Now that you are logged in as your own user from a SSH terminal update Linux to ensure your packages and libraries are up to date. This is just good practice before you install anything on your system, make sure it is the latest release. To do this run these commands:

$ sudo apt-get update
$ sudo apt-get upgrade

5. Install The LAMP Stack

Ok! This is why you came to party! Actually, Linux is already installed, so we’ll just be adding additional packages, libraries as well as Apache, MySQL and PHP!

The easiest way install the LAMP stack is with tasksel. To install the LAMP with taskel type:

$ sudo tasksel install lamp-server

Follow the prompts that appear in your terminal. Enter a MySQL root password and don’t forget it :-). Next, you’ll need to secure our MySQL installation, so type:


Create Web Directory Structure5

Get to your top-level directory by typing:

$ cd /home/$USER

Now create the structure for your web directory:

$ mkdir -p public_html/domain1.com/{public,private,log,cgi-bin,backup}

Setup the group and permissions:

$ sudo usermod -a -G www-data $USER #adds $USER to www-data (the Apache user group)
$ groups  #this will output the groups $USER is a member of. logout then back in again to enable the change
$ sudo chgrp -R www-data /home/$USER/public_html
$ sudo chmod -R 2750 /home/$USER/public_html #assign the sticky bit so all files are mapped to $USER and group www-data

# Create a template that has the above folder structure and permissions.  
# Just recopy the folders with cp -a command:

$ cp -a /home/$USER/public_html/domain1.com /home/$USER/public_html/template_folders

6. Server Security Basics

It’s best to think of security as a series of layers. Additionally, security is something you want integrated into your app from the beginning. You want it baked-in, not just icing on top or added as an afterthought. We’ll only address a few of these concerns in today’s class, but here’s an overview:

  • Obscurity: Changing default connect ports (3306 and 22) for MySQL and SSH. Also limiting information that Apache tells the world about itself by editing /etc/apache2/conf.d/security

    Security through Obscurity is a Myth: Neither People Nor Computers Can Keep Secrets

    Obscurity does not make your server more secure. However, it may make you less of a target. From the Apache 2.4 core docs: “Security through obscurity” is a myth and leads to a false sense of safety.

  • Port Blocking: Using a Firewall to disable all non-essential traffic – ports and connections – including ping, ftp, and sftp
  • Pubic Key Encryption: Generating an SSH public/private key-pair for passwordless logins
  • Disabling Common Attack Vectors: Directory browsing and remote root login
  • IP Filtering: Using httpd.conf or the v-host file to restrict site access based on host IP Address
  • Restricting Folder Access by Traffic Type: Restricting public web traffic over http/s to only those folders those you specifically designate. This may also be done through the httpd.conf and the v-host files

a. Secure Your Server With A Firewall

For now, we’ll execute all the below as root. To allow established connections to remain open:

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

To allow SSH Traffic:

iptables -A INPUT -p tcp --dport 22 -j ACCEPT

To allow HTTP traffic:

iptables -A INPUT -p tcp --dport 80 -j ACCEPT

To allow HTTPS traffic:

iptables -A INPUT -p tcp --dport 443 -j ACCEPT

And, finally, drop all remaining traffic:

iptables -A INPUT -j DROP

Save your new rules to a file

$ iptables-save > /etc/iptables.rules

Next, instruct your server’s Network Interface Card (NIC) to load the IP table rules on each boot:

$ nano /etc/network/interfaces

Once the file is opened add the following line right below the line “iface eth0 inet static”. And, make sure it’s indented like the other lines:

pre-up iptables-restore < /etc/iptables.rules

b. Configure & Lockdown MySQL

$ nano /etc/mysql/mysql.conf.d/mysqld.cnf

Change ports in 1 2 locations and update bind address to server IP

c. Lockdown Apache

$  nano /etc/apache2/conf-enabled/httpd.conf
#ref: httpd.apache.org/docs/2.4/upgrading.html#access and httpd.apache.org/docs/2.4/howto/access.html
<Directory />
# Globally Disable .htaccess
   AllowOverride None
# Globally remove directory browsing
   Options -Indexes
# Globally Remove Website Viewing
#   Order Deny,Allow
#   Deny from all
   Require all denied

# Allow Viewing and .htaccess in A Web Directory of Your Choice
# You may choose any /optional/path/to/web/folder/public_html
<Directory /home/username/public_html/>
   AllowOverride All
#   Order Deny,Allow
#   Allow from all
   Require all granted

d. Partial SSH Lockdown

Further secure your server by modifying the sshd_config file. Change the SSH port number to something random between 1-65535. You may want to select a number over 30,000 (well after the commonly used ports). This will help to prevent brute force attacks where a bot attempts to connect over SSH on the default port 22:

$ sudo nano /etc/ssh/sshd_config  #change to a port above 

Reload ssh config with your new modifications:

$ sudo service ssh reload

IMPORTANT: Now update your IP table rules to allow the new SSH and MySQL ports. Port 22 and 3306 will now be blocked:

$ sudo nano /etc/iptables.rules

You're done (for now)! Pat your self on the back and grab a tasty snack for a job well done!