How to Host Multiple Websites on the Same Ubuntu Server with Nginx and Virtual Hosts
Learn how to structure a Linux server to handle multiple different domains using server blocks, traffic routing, and secure isolation.
Summary
- Using Nginx server blocks solves the problem of directing requests from different domains to separate folders on disk.
- Configuring A and CNAME DNS records correctly ensures internet traffic reaches the correct public IP of the server.
- File permission isolation prevents security flaws in one application from compromising other hosted websites.
- Issuing free SSL certificates via Let's Encrypt protects the traffic of all domains independently.
- Monitoring system resource usage prevents a high-traffic site from harming the performance of neighbors on the same server.
The Challenge of Centralizing Multiple Applications on a Single Machine
When starting new projects on the internet, the most common path is to rent a cheap cloud virtual machine for every single website we launch. In practice, this means wasting money and processing power, since a simple institutional site consumes only a tiny fraction of a modern processor's capacity. The solution to this waste is using a single server running multiple domains simultaneously, splitting infrastructure costs and simplifying maintenance. However, an engineering problem arises: how do we make the server understand that a request coming from siteA.com should open completely different files than a request for siteB.com?
To solve this puzzle, we use software called a reverse proxy web server, with Nginx being one of the most popular and efficient choices on the current market. In practice, Nginx acts like an intelligent doorman at the entrance of your Ubuntu Server, looking at the address typed by the user in the browser and forwarding the request to the correct floor. This mechanism is technically known as Virtual Hosting or server blocks. Without it, the server would get lost, always displaying the same home page for any address hitting its door.
Preparing the Ground and Installing the Web Server
Before configuring domains, we must ensure the operating system is clean, up-to-date, and has the web handling tool properly installed. Ubuntu Server offers a package manager called APT, which functions like an official command-line app store for the system. The first practical step is updating the local package list by typing sudo apt update && sudo apt upgrade -y in the terminal. Next, we install Nginx with the command sudo apt install nginx -y. This step downloads essential files and starts the service in the background, ensuring the server is already responding to basic requests on the standard web port.
After installation, it is worth checking if the system firewall, known as UFW, is configured to allow internet traffic. In practice, the firewall acts like a bouncer at the club door, deciding who gets in and who stays out. We open the network rules by typing sudo ufw allow 'Nginx Full', which ensures both regular and secure connections can pass through. If you open your server's numerical IP address in the browser now, you will see the standard Nginx welcome page, indicating the main engine is already roaring and ready for more advanced instructions.
Organizing Folder Structures for Each Domain
A common mistake for beginners is throwing the files of all websites into the default folder Nginx creates automatically, mixing codes and creating security gaps. The engineering behind a robust environment requires strict isolation, creating a dedicated directory structure for each project inside Linux's standard web page directory. For our first site, we create the folder /var/www/siteone.com/html, and for the second site, the folder /var/www/sitetwo.com/html. We use the command sudo mkdir -p to ensure all intermediate folders are created at once without complaints from the operating system.
Besides creating folders, we must ensure the system user running Nginx has permission to read these files, without letting malicious users break into the system. In practice, we adjust folder ownership using the command sudo chown -R $USER:$USER /var/www/siteone.com/html, giving control to your current user during development. We also adjust read permissions with sudo chmod -R 755 /var/www, ensuring the outside world can read the site content, but only the administrator can alter them. To test if everything works, we create a simple test file named index.html inside each folder with a message identifying which site it is.
Configuring Nginx Server Blocks
The soul of multi-hosting lies within Nginx configuration files, located in the /etc/nginx/sites-available/ folder. Each domain must have its own isolated configuration file, describing exactly how the server should behave when receiving a request for that specific address. We create a file named siteone.com for the first project and fill it with clear guidelines informing Nginx where the files are on disk and what the corresponding domain name is. This separation prevents a cascading effect, where a typo in one site brings down the entire server.
Inside this configuration file, we define code blocks called server. A practical example of the essential structure is the following basic block:
server {
listen 80;
server_name siteone.com www.siteone.com;
root /var/www/siteone.com/html;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}In practice, this instruction tells Nginx to listen on port 80 (unencrypted traffic) when someone types siteone.com, look for files inside the folder we created, and deliver the requested home page. We repeat the process for the second site, creating a separate file for it. To activate these configurations, we create symbolic links—acting like smart shortcuts—pointing to the /etc/nginx/sites-enabled/ folder. Before restarting the server, we run the test command sudo nginx -t to validate that there are no syntax errors, preventing unwanted downtime in production.
## Pointing DNS and Securing with Security Certificates
With the server configured and running, the next step is ensuring domains purchased from external registrars know where to find your Ubuntu Server. In practice, you access your domain registrar panel and create A records pointing your site name to the public IP address of your cloud machine. When a user types the address in the browser, the global domain name system translates this to your IP, making traffic arrive exactly at the Nginx we configured in previous steps. This propagation process can take a few minutes to spread globally.
The final mandatory step for any modern website is installing SSL certificates, which transform the HTTP protocol into HTTPS, displaying the famous green security padlock in the browser. Without this, modern browsers block access and show scary warnings to visitors. We use an automated tool called Certbot, installed via package manager, which talks directly to the Let's Encrypt certificate authority. By running the command sudo certbot --nginx, the system automatically detects all server blocks configured in Nginx, generates free certificates, and even sets up automatic renewal in the background, ensuring your multiple sites remain secure and functional indefinitely.
Final Considerations and Continuous Maintenance
Hosting multiple websites on the same Ubuntu Server is an excellent resource optimization strategy, but it requires discipline in organization and daily monitoring. By isolating folders, structuring clean server blocks, and automating SSL certificate renewal, you build a professional environment comparable to large hosting agencies. Maintenance becomes a routine of observing Nginx error logs and ensuring operating system security updates do not interfere with network settings. With this solid foundation, scaling to five, ten, or twenty sites on the same machine ceases to be a technical risk and becomes a controlled, highly efficient operation.