You can host multiple websites on a single IP address and port 80 by configuring name-based virtual hosting or reverse proxies. This technique, known as Server Name Indication (SNI) in modern contexts or Host header routing in HTTP/1.1, allows web servers to distinguish between domains based on the requested hostname rather than just the destination IP.
Understanding the Core Mechanism
When you access a website, your browser sends an HTTP request that includes a
Host header. This header contains the domain name you typed into the address bar. The web server listening on port 80 receives this request and checks the
Host value against its configuration rules. If the server is configured with multiple "virtual hosts" or "server blocks," it matches the incoming hostname to the correct document root directory. This allows Apache, Nginx, IIS, and other web servers to serve different content for
example.com and
test.org even though they share the same IP address and port.
For this to work reliably, your DNS records must point all relevant domains to the same IP address. Once the traffic arrives at your server, the software layer handles the separation. While Linux distributions like Ubuntu or CentOS are the most common environments for this setup due to the prevalence of open-source web servers, Windows and macOS can also achieve similar results using specific tools.
Configuring Apache on Linux
Apache uses the concept of Virtual Hosts. On a standard Linux installation, configuration files are typically located in
/etc/apache2/sites-available/ (Debian/Ubuntu) or
/etc/httpd/conf.d/ (CentOS/RHEL). To set up a new site, you create a configuration file that specifies the
ServerName and
DocumentRoot.
Create a new file, for example,
example.conf, with the following structure:
<VirtualHost *:80>
ServerName www.example.com
ServerAlias example.com
DocumentRoot /var/www/html/example
<Directory /var/www/html/example>
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/example_error.log
CustomLog ${APACHE_LOG_DIR}/example_access.log combined
</VirtualHost>
After saving the file, enable the site. On Ubuntu, run
a2ensite example.conf. Then, reload the Apache service using
systemctl reload apache2. Repeat this process for each additional domain, ensuring each has a unique
ServerName and points to a distinct directory. You can verify the syntax before reloading by running
apache2ctl configtest.
Setting Up Nginx on Linux
Nginx uses server blocks instead of virtual hosts. The configuration files are usually stored in
/etc/nginx/sites-available/ and linked via symlinks to
/etc/nginx/sites-enabled/. A basic server block looks like this:
server {
listen 80;
server_name www.test.org test.org;
root /var/www/test;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Place this code in
/etc/nginx/sites-available/test.org, create a symlink to
sites-enabled, and restart Nginx with
systemctl restart nginx. Nginx processes requests very efficiently, making it ideal for high-traffic multi-site setups. If you need to route traffic to backend applications (like Node.js or Python apps), you would use
proxy_pass directives within these blocks.
Hosting Multiple Sites on Windows
Windows users often rely on Internet Information Services (IIS) or third-party servers like XAMPP which bundles Apache/Nginx. If using IIS, the process is GUI-driven but requires careful binding configuration. Open the IIS Manager and select the server node. Navigate to "Sites" and click "Add Website."
In the dialog box, provide a Site Name and specify the physical path to your website's folder. Crucially, under "Binding," ensure the Type is
http, the Port is
80, and the Host Name field contains your domain (e.g.,
www.example.com). You can add multiple bindings to the same site if needed, but for separate sites, you create separate entries in IIS Manager. Each site entry acts as an isolated container. If you encounter permission errors, ensure the IIS_IUSRS group has read access to the physical directory. For those using WSL (Windows Subsystem for Linux) or Docker on Windows, the Linux configurations above apply directly within the container or subsystem environment.
macOS Configuration
macOS does not include a pre-installed web server by default, but developers often install Apache or Nginx via Homebrew. If you install Apache via Homebrew (
brew install httpd), the configuration files are located in
/opt/homebrew/etc/httpd/ (Apple Silicon) or
/usr/local/etc/httpd/ (Intel). The main configuration file is
httpd.conf, but it is best practice to include separate files for each site in
extra/httpd-vhosts.conf.
Uncomment the line
Include /path/to/extra/httpd-vhosts.conf in the main config. Then, edit
httpd-vhosts.conf to define your virtual hosts similarly to the Linux Apache examples. Start the service using
brew services start httpd. Note that on macOS, ports below 1024 (like 80) require sudo privileges to bind. You may need to configure passwordless sudo for the brew user or use port forwarding rules in
/etc/pf.conf to redirect external traffic from port 80 to a higher privileged port if you face permission denied errors during local testing.
Reverse Proxy and Load Balancing
If you are running complex applications behind these sites, you might use a reverse proxy. Nginx is excellent for this. You can direct all traffic on port 80 to a local application server. For example:
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
This setup hides the internal port number from the outside world. It also facilitates load balancing if you have multiple backend instances. Distribute traffic across several servers by defining an upstream block in Nginx or using Apache's
mod_proxy_balancer. This ensures high availability and scalability for your hosted domains.
Frequently Asked Questions
Can I host HTTPS sites on the same IP without SNI?
No, traditional SSL/TLS encryption requires a dedicated IP address for each certificate because the handshake happens before the browser sends the
Host header. However, Server Name Indication (SNI) allows multiple SSL certificates to be served over a single IP by sending the hostname during the initial handshake. Most modern browsers support SNI, making it the standard solution for secure multi-site hosting.
What happens if two sites have the same IP but no Host header is sent?
If a client connects without sending a
Host header, the server will serve the first virtual host defined in its configuration file. This is why it is critical to always define a "default" server block that catches all unmatched requests. This default block should ideally return a 403 Forbidden error or a simple landing page to prevent accidental exposure of your primary site's content.
How do I troubleshoot DNS issues when hosting multiple sites?
Ensure that every domain name resolves to the exact same public IP address using tools like
nslookup or
dig. If one domain points to a different IP, the traffic will not reach your server's virtual host configuration. Additionally, check for DNS propagation delays after updating records, as cached entries might still direct users to an old or incorrect server.
Is it safe to expose multiple sites on port 80?
Port 80 itself is not inherently unsafe, but serving unencrypted HTTP traffic exposes data to interception. It is strongly recommended to migrate all sites to HTTPS (port 443) using free certificates from Let's Encrypt. Using a reverse proxy like Nginx or Apache allows you to enforce HTTPS redirection automatically, ensuring that even if users type
http://, they are securely redirected to
https://.
Can I use this method for subdomains?
Yes, this technique works identically for subdomains like
blog.example.com or
app.example.com. You simply add a new virtual host or server block with the specific
ServerName including the subdomain prefix. Ensure your DNS records include CNAME or A records for each subdomain pointing to your server's IP address.