LowEndBox - Cheap VPS, Hosting and Dedicated Server Deals

How To Set Up Apache Virtual Hosts on Debian 8, 9, and 10

In this tutorial, we will start with an empty VPS with a freshly installed Debian 9 and will end up with three different sites sharing the same IP address, hosted on the same machine.

Apache web server analyzes HTTP request headers and appropriately connects it to the directory structure inside the VPS. The technical term for “sites” inside VPS boxes is “virtual host” – the server is the “host” to many domains 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
  • Installing and setting up UFW
  • 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 TLS certificates

Read more to continue…


We use Debian 9 but this article has been tested against Debian 8 and 10 as well. The differences are noted in the text:

  • 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 using A records at your DNS service provider.
  • We use nano as our editor of choice, and you can install it with this command:
sudo apt install nano -y
  • On Debian 8 you need to install sudo as well:
apt-get install sudo

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 carry out the rest of the commands in this tutorial. We’ll call the new user simpleuser. To create it, run:

adduser simpleuser

Debian 9.7 will ask you for a UNIX password, while Debian 10 will ask only for a password, however, the procedure is the same. Enter the password twice and press Enter five times to create a new user.

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

usermod -aG sudo simpleuser

On Debian 9.7, you may get a harmless but annoying message like this:

Turns out that your version of Debian 9.7 may come with a package called unscd preinstalled. It is supposed to speed up requests to name servers like LDAP… unfortunately, it contains a bug that forces the lines such as

sent invalidate(passwd) request, exiting
sent invalidate(group) request, exiting

to appear after usermod command.

Feel free to remove unscd with this command:

apt remove unscd

After that, the usermod command won’t report strange lines.

You don’t get this problem on Debian 10.

Anyways, now you will be able to use the simpleuser as a root using the command sudo.

Step 2: Installing Apache

To install Apache web server on all three versions of Debian, type the following commands:

sudo apt update
sudo apt install apache2 apache2-doc

That will install the Apache manual as well.

The following command will show the status of Apache service in a terminal window:

sudo systemctl status apache2    

The real test of successful installation is whether you can access files from the server through your local browser. Navigate to this address:


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

Step 3: Change Firewall Rules to Enable Nginx

On Debian, the iptables firewall is installed by default, but we prefer ufw, the uncomplicated firewall. First install it:

sudo apt install ufw -y

List all the port profiles ufw already knows about:

sudo ufw app list

It will show quite a list, but we are interested only in those entries that have prefix *WWW in them:

Let’s take a closer look at the WWW Full:

sudo ufw app info "WWW Full"

The result is:

It is exactly what we need, two ports 80 and 443, one for the HTTP traffic and the other for HTTPS traffic. Enable it:

sudo ufw allow 'WWW Full'

Here is a list of ports and feel free to add any other that your host requires for the normal functioning of the system:

sudo ufw allow ssh
sudo ufw allow ftp
sudo ufw allow http
sudo ufw allow https
sudo ufw allow 20/tcp
sudo ufw allow 3000
sudo ufw allow 8080
sudo ufw allow 'WWW Full'
sudo ufw enable

The above commands illustrate various ways of defining ports within ufw. For instance, ports 3000 and 8080 are here used only as an example – they are not needed for installing virtual hosts on Apache, but may well be needed for some other type of application running on your VPS. Learn from your VPS provider which ports might be mandatory for normal functioning of the system and then add them to ufw.


Always enable ssh, http, https and other critical ports in ufw, otherwise you will NOT be able to log back into your VPS server!

To see the changes, run:

sudo ufw status

To test, navigate to your domain in your browser. It should load correctly, and if you again see the welcome to Apache on Debian page, you have set up ufw correctly.

Step 4: File Locations For the Default Apache Page

We’ll now learn how did Apache know to serve that welcome page. In Debian, root document page is in directory /var/www/html and it is called index.html. You can see its contents by running this command:

ls -la /var/www/html

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

Execute this command

sudo nano /var/www/html/index.html

to see the contents of index.html:

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

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

ls -la /etc/apache2

Directories sites-available and sites-enabled hold information on sites that exist and on sites that are permitted to be served to the Internet, respectively.

File /etc/apache2/sites-enabled/000-default.conf is a symbolic link to the file of the same name in folder sites-available. That 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 different domains. 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 5: Creating File Structure For Our Demo Virtual Hosts

We will create two virtual hosts called debian1.com and debian2.com. They will correspond to DNS entries debian1.duskosavic.com and debian2.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.) If we now navigated to http://debian1.duskosavic.com/_ in a browser, the default index.html page with basic Apache information would be served, again.

Let’s now create a directory to hold our debian1.com site. Apache on Ubuntu stores its HTML files under /var/www/html so we could also use it to create our demo sites there. One possibility is to make that folder the top one and to put the demo sites into it. With commands such as

cd /var/www/html
sudo mkdir debian1.com
sudo mkdir debian2.com
ls -la

we would have the following directory structure:

Here we decide upon the other possibility, and that is to go one level up the directory tree and create the demo sites in /var/www. Inside folders debian1.com and debian2.com we can create whatever directory structure we need, for example:

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

Step 6: Granting Permissions

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

sudo chown -vR simpleuser:simpleuser /var/www/debian1.com/public_html
sudo chown -vR simpleuser:simpleuser /var/www/debian2.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 7: Create index.html Pages For Our Demo Sites

Our public files will be in /var/www/debian1.com/publichtml_ and /var/www/debian2.com/publichtml. We’ll now create an _index.html in each of these two folders so that we have something to see while browsing. Using nano, we will create index.html for debian1.com:

sudo nano /var/www/debian1.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, then save and close the file:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
<title>debian1.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 debian1.com 

Create index.html for debian2.com

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

and paste this in:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
<title>debian2.com Title</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css">
.style1 {color: #3333FF}

<h1 class="style1">This is debian2.com</h1>

Step 8: Create Virtual Hosts Files

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

Step 8A: Create the First Virtual Hosts File

Copy the original file and rename it debian1.com.conf:

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

Use nano to see what is in it:

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

For clarity, we’ll remove comments and this is what you should return back into nano:

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

Here is a detailed explanation:

  • 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: It is the email address to which Apache will send messages for administrator in case of an error in the system. May be omitted.
  • 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 8B: 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/debian2.com.conf

Again use nano to see what is in it:

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

This is what you should return back into nano:

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

Save and close the file.

Step 9: 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 commands are:

sudo a2ensite debian1.com.conf
sudo a2ensite debian2.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 index.html 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

In other words, run it as 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 10: 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 debian1.duskosavic.com you will see this:

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

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

We can use free certificates to turn our HTTP traffic into HTTPS traffic, which will make connecting to your site secure.

Certbot for Debian comes from the Backports repo, so let’s create a sources list for our case:

sudo nano /etc/apt/sources.list.d/apache.list

and enter the following line into that file:

deb http://deb.debian.org/debian stretch-backports main


sudo apt update

and install backports:

sudo apt-get install certbot python-certbot-apache -t stretch-backports

Finally, run Certbot:

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 set up for:

  • debian1.duskosavic.com
  • debian2.duskosavic.com

The last question will be whether do you want HTTPS access or not. You do, of course, so choose 2.

Restart Apache:

sudo service apache2 restart

In your browser, go to address


We have entered the HTTP address and Apache automatically redirects to HTTPS, as it should:

You’ll notice that the actual site address starts with HTTPS and that there is green padlock in the address bar.

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, running Debian 9 or 10.

Dusko Savic is a technical writer and programmer.



  1. Om123:

    This title might confuse some people:

    Step 3: Change Firewall Rules to Enable *Nginx*

    April 13, 2020 @ 1:18 pm | Reply
  2. Great, for users don’t like command line, or your manage many different system with different OS or for beginner, a simple solution for you; Virtualmin.

    When you start a new VPS, is a good begin for, you can easily setup server for your services and can make a backup for restoring later. Is a good alternative to CPanel or DirectAdmin when you start your business and not have client (and not have money for CPanel license).

    Yesy, is a little less user freindly of CPanel or Direct Admin, but offer more options.

    April 13, 2020 @ 2:45 pm | Reply
  3. April 13, 2020 @ 2:52 pm | 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 *