The Apache web server is a popular method for serving websites on the internet. As of 2019, it is estimated to serve 29% of all active websites and it offers robustness and flexibility for developers. Using Apache, an administrator can set up one server to host multiple domains or sites off of a single interface or IP by using a matching system.
Each domain or individual site — known as a “virtual host” — that is configured using Apache will direct the visitor to a specific directory holding that site’s information. This is done without indicating that the same server is also responsible for other sites. This scheme is expandable without any software limit as long as your server can handle the load. The basic unit that describes an individual site or domain is called a virtual host
.
In this guide, we will walk you through how to set up Apache virtual hosts on an Ubuntu 18.04 server. During this process, you’ll learn how to serve different content to different visitors depending on which domains they are requesting.
Before you begin this tutorial, you should create a non-root user.
You will also need to have Apache installed in order to work through these steps. If you haven’t already done so, you can get Apache installed on your server through the apt
package manner:
If you would like more detailed instructions as well as firewall setup, please refer to our guide How To Install the Apache Web Server on Ubuntu 18.04.
For the purposes of this guide, our configuration will make a virtual host for example.com
and another for test.com
. These will be referenced throughout the guide, but you should substitute your own domains or values while following along.
If you are using DigitalOcean, you can learn how to set up domains by following the product documentation, How to Add Domains. For other providers, refer to their relevant product documentation If you do not have domains available at this time, you can use test values.
We will show how to edit your local hosts file later on to test the configuration if you are using test values. This will allow you to validate your configuration from your home computer, even though your content won’t be available through the domain name to other visitors.
The first step that we are going to take is to make a directory structure that will hold the site data that we will be serving to visitors.
Our document root
(the top-level directory that Apache looks at to find content to serve) will be set to individual directories under the /var/www
directory. We will create a directory here for both of the virtual hosts we plan on making.
Within each of these directories, we will create a public_html
folder that will hold our actual files. This gives us some flexibility in our hosting.
For instance, for our sites, we’re going to make our directories as follows. If you are using actual domains or alternate values, swap out the highlighted text for these.
The portions in red represent the domain names that we want to serve from our VPS.
Now we have the directory structure for our files, but they are owned by our root user. If we want our regular user to be able to modify files in our web directories, we can change the ownership by doing this:
The $USER
variable will take the value of the user you are currently logged in as when you press ENTER
. By doing this, our regular user now owns the public_html
subdirectories where we will be storing our content.
We should also modify our permissions to ensure that read access is permitted to the general web directory and all of the files and folders it contains so that pages can be served correctly:
Your web server should now have the permissions it needs to serve content, and your user should be able to create content within the necessary folders.
We now have our directory structure in place. Let’s create some content to serve.
For demonstration purposes, we’ll make an index.html
page for each site.
Let’s begin with example.com
. We can open up an index.html
file in a text editor, in this case we’ll use nano:
Within this file, create an HTML document that indicates the site it is connected to, like the following:
<html>
<head>
<title>Welcome to Example.com!</title>
</head>
<body>
<h1>Success! The example.com virtual host is working!</h1>
</body>
</html>
Save and close the file (in nano, press CTRL
+ X
then Y
then ENTER
) when you are finished.
We can copy this file to use as the basis for our second site by typing:
We can then open the file and modify the relevant pieces of information:
<html>
<head>
<title>Welcome to Test.com!</title>
</head>
<body> <h1>Success! The test.com virtual host is working!</h1>
</body>
</html>
Save and close this file as well. You now have the pages necessary to test the virtual host configuration.
Virtual host files are the files that specify the actual configuration of our virtual hosts and dictate how the Apache web server will respond to various domain requests.
Apache comes with a default virtual host file called 000-default.conf
that we can use as a jumping off point. We are going to copy it over to create a virtual host file for each of our domains.
We will start with one domain, configure it, copy it for our second domain, and then make the few further adjustments needed. The default Ubuntu configuration requires that each virtual host file end in .conf
.
Start by copying the file for the first domain:
Open the new file in your editor with root privileges:
With comments removed, the file will look similar to this:
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Within this file, we will customize the items for our first domain and add some additional directives. This virtual host section matches any requests that are made on port 80, the default HTTP port.
First, we need to change the ServerAdmin
directive to an email that the site administrator can receive emails through.
ServerAdmin admin@example.com
After this, we need to add two directives. The first, called ServerName
, establishes the base domain that should match for this virtual host definition. This will most likely be your domain. The second, called ServerAlias
, defines further names that should match as if they were the base name. This is useful for matching hosts you defined, like www
:
ServerName example.com
ServerAlias www.example.com
The only other thing we need to change for our virtual host file is the location of the document root for this domain. We already created the directory we need, so we just need to alter the DocumentRoot
directive to reflect the directory we created:
DocumentRoot /var/www/example.com/public_html
When complete, our virtual host file should look like this:
<VirtualHost *:80>
ServerAdmin admin@example.com
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/public_html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
At this point, save and close the file.
Now that we have our first virtual host file established, we can create our second one by copying that file and adjusting it as needed.
Start by copying it:
Open the new file with root privileges in your editor:
You now need to modify all of the pieces of information to reference your second domain. When you are finished, it should look like this:
<VirtualHost *:80>
ServerAdmin admin@test.com
ServerName test.com
ServerAlias www.test.com
DocumentRoot /var/www/test.com/public_html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Save and close the file when you are finished.
Now that we have created our virtual host files, we must enable them. Apache includes some tools that allow us to do this.
We’ll be using the a2ensite
tool to enable each of our sites. If you would like to read more about this script, you can refer to the a2ensite
documentation.
Next, disable the default site defined in 000-default.conf
:
When you are finished, you need to restart Apache to make these changes take effect and use systemctl status
to verify the success of the restart.
Your server should now be set up to serve two websites.
If you haven’t been using actual domain names that you own to test this procedure and have been using some example domains instead, you can at least test the functionality of this process by temporarily modifying the hosts
file on your local computer.
This will intercept any requests for the domains that you configured and point them to your VPS server, just as the DNS system would do if you were using registered domains. This will only work from your local computer though, and only for testing purposes.
Make sure you are operating on your local computer for these steps and not your VPS server. You will need to know the computer’s administrative password or otherwise be a member of the administrative group.
If you are on a Mac or Linux computer, edit your local file with administrative privileges by typing:
If you are on a Windows machine, you can find instructions on altering your hosts file here.
The details that you need to add are the public IP address of your server followed by the domain you want to use to reach that server.
Using the domains used in this guide, and replacing your server IP for the your_server_IP
text, your file should look like this:
127.0.0.1 localhost
127.0.1.1 guest-desktop
your_server_IP example.com
your_server_IP test.com
Save and close the file.
This will direct any requests for example.com
and test.com
on our computer and send them to our server. This is what we want if we are not actually the owners of these domains in order to test our virtual hosts.
Now that you have your virtual hosts configured, you can test your setup by going to the domains that you configured in your web browser:
http://example.com
You should see a page that looks like this:
You can also visit your second page and see the file you created for your second site.
http://test.com
If both of these sites work as expected, you’ve successfully configured two virtual hosts on the same server.
If you adjusted your home computer’s hosts file, you may want to delete the lines you added now that you verified that your configuration works. This will prevent your hosts file from being filled with entries that are no longer necessary.
If you need to access this long term, consider adding a domain name for each site you need and setting it up to point to your server.
If you followed along, you should now have a single server handling two separate domain names. You can expand this process by following the steps we outlined above to make additional virtual hosts.
There is no software limit on the number of domain names Apache can handle, so feel free to make as many as your server is capable of handling.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Hi Lisa, this article is great, I completed allá steps and I know you said this is for testing, whether I don’t configure hosts file, how can I get my sites? Thanks again.
Once you’ve configured your Virtual Hosts you can point your domain names to the server IP address by adding an A record to your domain’s DNS zone to point to the Droplet’s IP address.
For more information on how to do that you can follow the documentation here:
This tutorial is very thorough and helpful!
But I wonder if I also have to change <Directory /var/www/html> to <Directory /var/www/example.com/public_html> in /etc/apache2/sites-available/example.com.conf and to <Directory /var/www/test.com/public_html> in /etc/apache2/sites-available/test.com.conf
(I’m using LAMP by DigitalOcean OS Ubuntu 18.04)
Yes, you should update the
<Directory>
directive in your Virtual Host configuration files to match the specificDocumentRoot
directories you have set for each site.In the
/etc/apache2/sites-available/example.com.conf
file, you would update the<Directory>
directive to:Similarly, in the
/etc/apache2/sites-available/test.com.conf
file, you would update the<Directory>
directive to:These changes ensure that Apache applies the correct configuration settings for each specific site’s directory.
Once you’ve made these updates, you can save the files and restart Apache for the changes to take effect:
Replace
example.com
andtest.com
with your actual domain names, and ensure that thepublic_html
directories exist in the specified paths.I’m glad to hear that the tutorial has been helpful for you. If you have any more questions, feel free to ask!
Is there any tutorial on how I have to configure my third-party Domains, which have DigitalOcean as their DNS server, to point to the website? I can look up the index.html in that directory using my IP-Adress, but the A-Record that points directly to the IP address can’T establish a connection…
DigitalOcean Product Docs should be able to help you out, here are the Domains and DNS how to guides.
Great article! I was easily able to migrate a site over from another hosting provider and now that the DNS has updated it’s LIVE! Yea!
One question, why do you have “public_html/” and put all files in that dir? Would there ever be files in the example.com/ directory? Just trying to understand if I need the public_html and/or would there ever be a private_files or somesuch?
Thanks!
Congratulations on successfully migrating your site and getting it live! That’s great to hear!
Regarding the
public_html
directory, it is a common convention used by many web hosting providers. The idea behind having a separatepublic_html
directory is to keep the publicly accessible files separate from other files that might exist in the root directory of the website.Typically, all the files that need to be accessed by the public, such as HTML, CSS, JavaScript, images, etc., are placed inside the
public_html
directory. This ensures that only the files in thepublic_html
directory are directly accessible by visitors to the website.On the other hand, files that are not intended to be accessed directly by visitors, such as server-side scripts, configuration files, or other sensitive files, can be placed outside of the
public_html
directory. This helps to enhance the security of the website by preventing direct access to sensitive files.The choice of directory structure ultimately depends on your specific requirements and preferences. If you don’t have any files outside of the
public_html
directory that need to be accessed by the web server or visitors, you can keep the structure simple and have all the website files directly inside theexample.com
directory.However, if you have files or directories that you want to keep private, you can create a separate directory, like
private_files
, outside of thepublic_html
directory and place those files there. You can then use appropriate permissions and access controls to restrict access to those files.Would these steps be the same to create a subdomain? In the example above you are using two completely different domain names. I’d like to use one called mywebsite.com & another called support.mywebsite.com
My droplet is already set up using the main domain name. How would you suggest to configure for a subdomain?
Very curious about this too. This works for me when having separate domain names, but won’t when using subdomain. I followed this tutorial to setup a subdomain: https://www.digitalocean.com/docs/networking/dns/how-to/add-subdomain/#create-a-new-hostname-with-an-a-record
but doesn’t seem to work pairing with Apache virtual hosts…
Did you try running
sudo certbot --apache
again? That was got my new subdomain to appear. I suppose it was related to the cert redirecting traffic only to domains with https.Hi there. I have been following this very carefully and made it through almost to the end. I have a question though – If I want to keep the root or Parent site live as is, should I keep the 000-default.conf file activated? Or should I duplicate it and create mysite.co.uk.conf pointing at the route.
I herd you shouldn’t be deactivating this file. So I am a little nervous doing this.
Hope you can help! Phil
The
000-default.conf
file is the default Virtual Host file that comes with Apache and is typically used to display a default page when someone accesses your server via its IP address, rather than a domain name.If you want to keep the root or parent site live, you have two main options:
Modify
000-default.conf
: You can directly edit this file to point to your website. However, note that any upgrades to Apache might overwrite your changes. Make sure to backup any changes you made.Create a new configuration file: You can create a new configuration file, for example
mysite.co.uk.conf
. This is often considered best practice because it allows you to manage each site independently and ensures your changes won’t be overwritten by future updates.In either case, you shouldn’t need to deactivate
000-default.conf
unless it’s causing conflicts. If you decide to create a new configuration file, you’d enable it witha2ensite mysite.co.uk
and then reload Apache.Just remember that the
ServerName
directive in your new site configuration should match your domain (mysite.co.uk
in this case), and theDocumentRoot
directive should point to your site’s directory.If your server is only going to be serving one site, and you’re not worried about Apache updates overwriting your changes, modifying
000-default.conf
is a bit simpler. But if you plan on hosting multiple sites, creating separate configuration files for each one is definitely the way to go.Thanks for the guide. I followed it to the letter to enable my two sites. And both work, just not when I do not add the full “https://www” in front of the second…
So the first site just works, whether I type site1.nl or www.example2.com, it loads and is redirected to https (through my .htaccess).
For the second site, however, which has precisely the same settings, same htaccess, same domain settings etc, this does not work. When I type example2.com, www.example2.com, http://example2.com or http://www.example2.com, it just refuses to load. Only when I type https://www.example2.com it will load.
I have tried all kinds of things, like different rules in .htaccess and adding NameVirtualHost * to the conf files. Nothing works. How can I resolve this problem?
Note that ServerName and ServerAlias are stated incorrectly in the guide.
Please correct it from INCORRECT values:
ServerName example.com ServerAlias www.example.com
to CORRECT values:
ServerName www.example.com ServerAlias example.com
I encountered the issue that the setup mentioned in the guide only worked for my first virtual host, but not for my second. Unless a full url was typed (https://www.example.com) the second site would not load. That issue was resolved by making this change.
Very clear description and very helpfull to understand. Thanks a lot
Thank you. It works just fine!