Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Webserver recipe for Ubuntu 14.04

Webserver setup recipe for Ubuntu 14.04 LTS

A few notes:

  • All commands should be run as root unless specified otherwise.
  • Commands that sould be run locally have a local$ prefix.

Initial setup


hostname SHINYNODE


apt-get update

# Review what will be upgraded
apt-get -u upgrade

apt-get upgrade -y

apt-get autoremove

Install some base packages

apt-get install git tree httpie python-pip python-software-properties software-properties-common

Timezone & time sync

# Configure timezones
dpkg-reconfigure tzdata

# Configure NTP sync
apt-get install ntp

Add SSH key

# Add your SSH key
local$ ssh-copy-id root@SERVER_IP

# Or manually:
mkdir ~/.ssh
chmod 700 ~/.ssh

echo "YOUR_SSH_KEY" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

Add a new user if necessary

adduser sepehr

# Add new user to the `sudo` group to be a sudoer
gpasswd -a sepehr sudo

local$ ssh-copy-id sepehr@SERVER_IP

# If logged-in with root, you can switch to the new user without logging out:
su - sepehr

Enable swap for mini nodes

# Allocate an empty 1G file
fallocate -l 1G /swapfile

# Format as swap
mkswap /swapfile

# Enable swap
swapon /swapfile

NOTE: The system will only use this space until the next reboot, but the only time that the server is likely to exceed its available memory is during the build processes, so this shouldn't be a problem.


Disallow remote root logins, if necessary

# Simply change `PermitRootLogin yes` to `PermitRootLogin no`
nano /etc/ssh/sshd_config

service ssh restart

# Exit and login using the new user
# NOTE: Make sure there's at least a sudoer user available

Protect SSH against bruteforce

A service called fail2ban can mitigate this problem by creating rules that can automatically alter your iptables firewall configuration based on a predefined number of unsuccessful login attempts. This will allow the server to respond to illegitimate access attempts without intervention from you.

apt-get install fail2ban

# Since this file can be modified by package upgrades, we should not edit this file in-place, but rather copy it so that
# we can make our changes safely.
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

# Configure:
# bantime: 600
# findtime: 600
# maxretry: 3
# Other entries to pay attention to:
#     destemail, sendername, mta, filter, logpath
# SSH is enabled by default, all other services are disabled. Read more:
nano /etc/fail2ban/jail.local

Configure the firewall

ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp

ufw show added

ufw enable

Install LAMP stack

Install Apache 2.4

apt-get install apache2

# Resolve this error for 2.4:
# "apache2: Could not reliably determine the server's fully qualified domain name, using for ServerName"
echo "ServerName localhost" | sudo tee /etc/apache2/conf-available/fqdn.conf
a2enconf fqdn

Install Apache 2.2

# Add `precise` repos so the 2.2 version will be available to us:
# deb precise main restricted universe
# deb precise-updates main restricted universe
# deb precise-security main restricted universe multiverse
nano /etc/apt/sources.list.d/precise.list

apt-get update

apt-get install apache2-mpm-prefork=2.2.22-1ubuntu1.10 \
  apache2-prefork-dev=2.2.22-1ubuntu1.10 \
  apache2.2-bin=2.2.22-1ubuntu1.10 \

# Resolve this error for 2.2:
# "apache2: Could not reliably determine the server's fully qualified domain name, using for ServerName"
echo "ServerName localhost" > nano /etc/apache2/conf.d/fqdn

service apache2 restart

NOTE: Due to dependency conflicts the default php5 package cannot be installed alongside this apache 2.2. You need to install a compatible php5 package. Instructions to do so is not included in this guide... yet.

Enable rewrite module

a2enmod rewrite

# Allow .htaccess files under the document root
# Within "<Directory /var/www/>" change "AllowOverride None" to "AllowOverride All"
nano /etc/apache2/apache2.conf

service apache2 restart

Disable directory listing

# Within "<Directory /var/www/>" remove "Indexes" from "Options Indexes"
nano /etc/apache2/apache2.conf

Setup Apache virtualhosts

# 1. Create directory structure
mkdir -p /var/www/html/
mkdir -p /var/www/html/

# 2. Setup virtualhost for
# NOTE: Default Ubuntu configuration requires that each virtual host file end in `.conf`
cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/

# <VirtualHost *:80>
#    ServerAdmin
#    ServerName
#    ServerAlias
#    DocumentRoot /var/www/html/
#    ErrorLog     ${APACHE_LOG_DIR}/error.log
#    CustomLog    ${APACHE_LOG_DIR}/access.log combined
# </VirtualHost>
# Copy and customize this file for domain
nano /etc/apache2/sites-available/
nano /etc/apache2/sites-available/

# 3. Enable new virtual host files

# Disable the default virtual host
a2dissite 000-default.conf

service apache2 restart

Install PHP 5.5.x

apt-get install php5

php -v

Install PHP 5.6.x

add-apt-repository ppa:ondrej/php5-5.6

apt-get update

apt-get install php5

php -v

Install composer globally

curl -sS | php
mv composer.phar /usr/local/bin/composer

Install PHP extensions

apt-get install php5-mysql php5-gd php5-mongo php5-mcrypt

service apache2 restart

Install MariaDB 10.1

# Add the official repo:
apt-key adv --recv-keys --keyserver hkp:// 0xcbcb082a1bb943db

# Add these to a new mariadb.list file:
# deb [arch=amd64,i386] trusty main
# deb-src trusty main
nano /etc/apt/sources.list.d/mariadb.list

apt-get update

apt-get install mariadb-server

service mysql start

# Post-installation setup

# In case you need to reconfigure the package
dpkg-reconfigure mariadb-server-10.1

Enabling SSL on Apache

Enable SSL module

# With apache2 already installed, enable the SSL module
a2enmod ssl

service apache2 restart

Disable SSLv3

# Disable SSLv3 against POODLE attacks
# The "SSLProtocol" directive should be explicitly set to "SSLProtocol all -SSLv3". SSLv2 is no longer supported.
nano /etc/apache2/mods-available/ssl.conf

service apache2 restart

Securing Apache with letsencrypt

# 1. Download the Let's Encrypt client
cd /opt
git clone

# 2. Setup SSL certificates
# Execute the interactive installation and obtain a certificate that covers only a single domain.
# When the installation is finished, you should be able to find the generated certificate files at
# /etc/letsencrypt/live directory.
# Verify the status of your SSL certificate with the following link:
# During installation letsencryot will ask to whether disable HTTP or not. Make sure to choose the 
# second option to redirect HTTP traffic to HTTPS.
./letsencrypt-auto --apache -d -d -d

# 3. Setup auto-renewal
# Let’s Encrypt certificates are valid for 90 days. Manually renew a Let’s Encrypt certificate for Apache with no
# interaction using this command. Pass the same list of domains again for the renewal command:
# ./letsencrypt-auto certonly --apache --renew-by-default -d -d -d
# 3.1. Download the renewal script
curl -L -o /usr/local/sbin/le-renew
chmod +x /usr/local/sbin/le-renew

# 3.2. Now we can manually renew using just the base domain
# You can check which domain was used by Let’s Encrypt as the base domain name by looking at the contents inside
# /etc/letsencrypt/live

# 3.3. Setup a CRON task to automatically check for renewals every week
# 30 2 * * 1 /usr/local/sbin/le-renew >> /var/log/le-renew.log
crontab -e

Securing Apache with self-signed SSL certificates

# 1. Create a directory to store server keys
mkdir /etc/apache2/ssl

# 2. Create a Self Signed SSL Certificate
# This command will prompt terminal to display a lists of fields that need to be filled in. The most important line is
# "Common Name". Enter your official domain name here or, if you don't have one yet, your site's IP address.
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.crt

# 3. Setup virtualhosts
# Default virtualhost with SSL enabled:
# /etc/apache2/sites-available/default-ssl.conf
# Create new virtualhosts for each site based on the default. Here's a sample:
<IfModule mod_ssl.c>
    <VirtualHost _default_:443>
            DocumentRoot  /var/www/html/
            ErrorLog      ${APACHE_LOG_DIR}/error.log
            CustomLog     ${APACHE_LOG_DIR}/access.log combined

            SSLEngine on
            SSLCertificateFile    /etc/apache2/ssl/apache.crt
            SSLCertificateKeyFile /etc/apache2/ssl/apache.key

            <FilesMatch "\.(cgi|shtml|phtml|php)$">
                    SSLOptions +StdEnvVars

            <Directory /usr/lib/cgi-bin>
                    SSLOptions +StdEnvVars

            BrowserMatch "MSIE [2-6]" \
                nokeepalive ssl-unclean-shutdown \
                downgrade-1.0 force-response-1.0

            # MSIE 7 and newer should be able to use keepalive
            BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown

# 4. Enable SSL virtualhosts
# You might want to disable the corresponding non-SSL virtualhost

service apache2 restart


Initial Server Setup with Ubuntu 14.04

Additional Recommended Steps for New Ubuntu 14.04 Servers

How To Protect SSH with Fail2Ban on Ubuntu 14.04

How To Set Up Apache Virtual Hosts on Ubuntu 14.04 LTS

How To Create a SSL Certificate on Apache for Ubuntu 12.04

How To Secure Apache with Let's Encrypt on Ubuntu 14.04

How To Protect your Server Against the POODLE SSLv3 Vulnerability

How to setup / install PHP 5.6 on Ubuntu 14.04 LTS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment