LowEndBox - Cheap VPS, Hosting and Dedicated Server Deals

How To Set Up Apache Virtual Hosts on Ubuntu 16.04

In this tutorial, we shall start with an empty VPS screen of a freshly installed Ubuntu 16.04 and will finish up with three different sites sharing the same IP address.

Apache web server analyzes input from the browser and connects it to the directory structure inside VPS. The technical term for “sites” inside VPS boxes is “virtual host” — the server is the “host” many DNS addresses at the same time, hence, they are not real but only “virtual”.

Let’s see how it’s done.

What We Are Going To Cover

  • Creating a Non Root User
  • Installing Apache
  • Defining File Locations For the Default Apache Page
  • Creating File Structure For Our Demo Virtual Hosts
  • Granting Permissions
  • Creating index.html Pages For Our Demo Sites
  • Creating Virtual Hosts Files
  • Turning On the New Virtual Host Files
  • Testing the Virtual Hosts
  • Securing Your Domains With Let’s Encrypt SSL


We use Ubuntu 16.04:

  • Starting with a clean VPS with
  • At least 512Mb of RAM and
  • 15Gb of free disk space.
  • You will need root user access via SSH
  • Two domain names pointed to your server’s IP address (it can also be a subdomain) using A records at your DNS service provider.

Step 1: Creating a Non Root User

Once you are logged in as root, you can create a new user account that you’ll use to access the app once it is installed. We’ll call the new user simpleuser. To create it, run:

adduser simpleuser

Enter the password twice and press Enter five times to create a new user.

Then, add it to the sudo group, so that you can run commands as sudo:

usermod -aG sudo simpleuser

Now you will be able to use the simpleuser as a root using the command sudo.

Step 2: Install Apache

First, update your package manager’s cache:

sudo apt update -y

Install the Apache web server:

sudo apt install apache2 -y

Enable its service to make it run on every system boot:

sudo systemctl enable apache2

Finally, start it:

sudo systemctl start apache2

To verify that Apache was installed successfully, access it from your local browser by navigating to http://YOUR_DOMAIN/. If that does not work, try adding :80 in the end, like this:


You should see a welcome page for Apache, which means that you now have Apache running.

Apache is running

Step 3: File Locations For the Default Apache Page

What did just happen? How did Apache know to serve the page that you see above? Turns out that under Ubuntu, root document page is in directory /var/www/html and it is called index.html. You can see it after these commands:

cd /var/www/html
ls -la

Note that the directories and the index.html files belong to root user.

Execute this command

sudo nano index.html

to see the contents of the index.html:

It is a very long page so we can scroll through it, change it and so on.

Under Ubuntu, all Apache files are in folder /etc/apache2:

cd /etc/apache2
ls -la

Directory sites-available holds information on sites that exist, while sites-enabled holds information which of the available sites can be exposed to the Internet. File 000-default.conf in the image above is light blue in color, which tells us that it is a symbolic link to the file of same name in folder sites-available. The existence of one such link enables Apache to read the contents of file


and serve it to the browser. By adding more config files into /etc/apache2/sites-available and creating the corresponding symbolic links in /etc/apache2/sites-enabled, we can serve different pages to the different site domains and that is how we can host multiple independent sites off of one and the same IP address.

Each site in Apache parlance is called “virtual host” and will have to reside in its own subdirectory. The plan for adding new virtual hosts boils down to

  • creating file structure for each site,
  • populating HTML and other files in the site,
  • creating a new .conf file in /etc/apache2/sites-available, and
  • creating a new symbolic link in /etc/apache2/sites-enabled.

Apache will then do the rest, automatically.

Step 4: Creating File Structure For Our Demo Virtual Hosts

We shall create two virtual hosts, let us call them demo1.com and demo2.com and they will correspond to DNS entries demo1.duskosavic.com and demo2.duskosavic.com that we have previously made using A records at our DNS service provider. (Instead of these, you should enter your own site domains and subdomains.) If we now entered http://demo1.duskosavic.com/ in the browser, the default index.html page with basic Apache information would be served, again.

Let us now create a directory within VPS to hold our demo1.com site. Ubuntu will hold its HTML files under /var/www/html folder but we are free to install our files elsewhere. We can, for example, install it into the root folder, like this:

cd ~
sudo mkdir /demo1.com

and put all our data into it. The address of the directory would be /root/demo1.com. As long as we entered that folder address into the rest of the configuration files, everything would be OK.

However, we could also use /var/www/html/ folder to create our demo sites there. With commands such as

cd /var/www/html
sudo mkdir demo1.com
sudo mkdir demo2.com
ls -la

we would have the following directory structure:

Or, we can go one level up the directory tree and create the demo sites in /var/www. Inside folders demo1.com and demo2.com we can install whatever directory structure we need, for example:

sudo mkdir -p /var/www/demo1.com/{public_html,private,log,cgi-bin,backup}
sudo mkdir -p /var/www/demo2.com/{public_html,private,log,cgi-bin,backup}
ls demo1.com -la

Step 5: Granting Permissions

From the image above we see that root user is still the owner of public_html folder from which our public files will be served to the Internet. Let us now change the ownership so that our simpleuser can access the public_html files. The commands are:

sudo chown -vR simpleuser:simpleuser /var/www/demo1.com/public_html
sudo chown -vR simpleuser:simpleuser /var/www/demo2.com/public_html

Also make sure that files in /var/www and its subfolders can be read correctly:

sudo chmod -R 755 /var/www

Step 6: Create index.html Pages For Our Demo Sites

Our public files will be in /var/www/demo1.com/publichtml_ and /var/www/demo2.com/publichtml. Let us create an _index.html in each of these two folders so that we have something to see while browsing. Use nano or editor of your choice to create index.html for demo1.com:

sudo nano /var/www/demo1.com/public_html/index.html

We need only one line of text, preferably in H1 format for better readability. Insert the following text into nano, save and close the file:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
<title>demo1.com Title</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css">
body,td,th {
    color: #FF3333;

<h1>This is demo1.com 

Create index.html for demo2.com

sudo nano /var/www/demo2.com/public_html/index.html

and paste this in:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
<title>demo2.com Title</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css">
body,td,th {
    color: #FF3333;
.style1 {color: #3333FF}
<h1 class="style1">This is demo2.com</h1>

Step 7: Create Virtual Hosts Files

Let us now inform Apache that there are two new sites to be served. We shall copy the default virtual host file, 000-default.conf twice and then alter these new files to reflect the positions of demo1.com and demo2.com sites on disk.

Step 7A: Create the First Virtual Hosts File

Copy the original and rename it demo1.com.conf:

sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/demo1.com.conf

Through nano see what is in it:

sudo nano /etc/apache2/sites-available/demo1.com.conf

For clarity, let us remove comments and this is what you should return back into nano:

<VirtualHost *:80>
    ServerAdmin admin@demo1.com
    ServerName demo1.com
    ServerAlias demo1.duskosavic.com
    ServerAlias www.demo1.com
    DocumentRoot /var/www/demo1.com/public_html
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

Let us explain in detail:

  • 80 This virtual host will listen on port 80. You can change port number through file ports.conf with this command:
sudo nano /etc/apache2/ports.conf

The contents of the ports.conf file are here in case you want to actually change them:

# If you just change the port or add more ports here, you will likely also
# have to change the VirtualHost statement in
# /etc/apache2/sites-enabled/000-default.conf

Listen 80

<IfModule ssl_module>
        Listen 443

<IfModule mod_gnutls.c>
        Listen 443

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
  • ServerAdmin is the email address to which Apache will send messages for administrator in case of an error in the system.
  • ServerName Server name, obviously, it should coincide with the domain name.
  • ServerAlias Another name for the same server as above. You can have as many of these aliases as you like.
  • DocumentRoot Points to the absolute address of the site on disk.
  • ErrorLog The address of the error log.
  • CustomLog The same for access logs — for example, have there been too many unauthorized accesses from the same IP address?

Step 7B: Create the Second Virtual Hosts File

Do the same for the other site / domain. Here are the commands:

sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/demo2.com.conf

Again use nano see what is in it:

sudo nano /etc/apache2/sites-available/demo2.com.conf

This is what you should return back into nano:

<VirtualHost *:80>
    ServerAdmin admin@demo2.com
    ServerName demo2.duskosavic.com
    ServerAlias www.demo2.com
    DocumentRoot /var/www/demo2.com/public_html
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

Save and close both files.

Step 8: Turn On the New Virtual Host Files

Command a2ensite will create symbolic links from sites-enabled directory to sites-available and so Apache will routinely start serving the virtual hosts. The command are:

sudo a2ensite demo1.com.conf
sudo a2ensite demo2.com.conf

If you want to disable the default site, the command would be:

sudo a2dissite 000-default.conf

You may want to leave it as it is in case that someone enters the IP address directly into the browser — then the default html code will be activated and the visitor would see what you have prepared for that case.

Once you use the a2ensite and a2dissite commands, you may see something like this in the terminal window:

If you try to activate a link that is already activated, you will be notified as already enabled. And then you will see two lines that say:

To activate new configuration, you need to run:
  service apache2 reload

That is, however, an incorrect advice to follow. The proper command is:

sudo service apache2 reload

that is, run it as a sudo.

Also be sure to clear cache in your browser or it may start fooling you with old values instead of the properly refreshed ones.

Step 9: Testing the Virtual Hosts

If you have left the default IP address activated, it will currently show the welcome to Apache screen. If you enter address demo1.duskosavic.com you will see this:

And entering demo2.duskosavic.com into the browser changes the image to:

Step 10: Securing Your Domains With Let’s Encrypt SSL

We can use free certificates to turn our HTTP traffic into HTTPS traffic, which will make access to the site more secure. Use this link to obtain free Let’s Encrypt TLS certificates, from the official Cerbot site.

Execute the following set of commands:

sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update

Now let us install Certbot:

sudo apt-get install certbot python-certbot-apache 

Run this command to get a certificate and have Certbot edit your Apache configuration automatically to serve it, turning on HTTPS access in a single step.

sudo certbot --apache

It will ask for your email address in case of emergency, then another two questions that you may answer however you like and then the most important question — which names would you like to activate HTTPS for?

I chose 4 and 5 as these are the only real domains and subdomains that I have DNS addresses for:

  • demo1.duskosavic.com
  • demo2.duskosavic.com

The last question will be whether do you want HTTPS access or not. You, of course, do so choose 2. This finishes the installation of CertBot so let us now try it out:

We have entered the HTTP address and the site automatically turns it into a HTTPS address:

What Can You Do Next

We have shown how to share one IP address to one, two, three or dozens or hundreds of independent sites. You can now use this knowledge to host all your sites on one low cost VPS box.

Dusko Savic is a technical writer and programmer.


1 Comment

  1. Harry:

    Thank you, very useful article.

    July 12, 2019 @ 5:27 am | Reply

Leave a Reply

Some notes on commenting on LowEndBox:

  • Do not use LowEndBox for support issues. Go to your hosting provider and issue a ticket there. Coming here saying "my VPS is down, what do I do?!" will only have your comments removed.
  • Akismet is used for spam detection. Some comments may be held temporarily for manual approval.
  • Use <pre>...</pre> to quote the output from your terminal/console, or consider using a pastebin service.

Your email address will not be published. Required fields are marked *