Serving Multiple Domains

27th Jun. 2022 - 10m read

Ever felt your server was an overkill for the single static site it was serving and wanted to host multiple websites with different domains pointing to the same IP?

Well, that was me a week ago when I desperately dug at the internet for an hour only to realize I had the solution staring at me the whole time. Enter Nginx, the godsend. A miracle reverse proxy, that can do wonders when setup correctly.

In my case, the approach was to have it route incoming requests to different backends based on the (sub) domain used to connect. To test this out, I had a setup like so:

Sub Domain Handlers

Let’s say you want http://t0.dom.com to point to the website on port 8080. We could start with a simple configuration:

# /etc/nginx/sites-enabled/t0.dom.com
server {
    listen          80;
    server_name     t0.dom.com;
    location / {
        proxy_pass  http://localhost:8080;
    }
}

And write a similar config for http://t1.dom.com, but this time pass a different service running on port 8081:

# /etc/nginx/sites-enabled/t1.dom.com
server {
    listen          80;
    server_name     t1.dom.com
    location / {
        proxy_pass  http://localhost:8081;
    }
}

Notice how both server directives are listening to the same port, but their server_name’s are different? So any incoming request to port 80 will be routed based on the sub-domain that was used to connect. Now restart the server with new configuration:

systemctl restart nginx

SSL Support

I had certbot generate SSL certs for me:

certbot certonly --nginx

After that, just add a new server directive listening on port 443, a simple config would resemble:

# /etc/nginx/sites-enabled/t0.dom.com
server {
    listen          80;
    server_name     t0.dom.com;
    return          301 https://t0.dom.com$request_uri;
}

server {
    listen          443;
    server_name     t0.dom.com;

    ssl_certificate     /etc/letsencrypt/live/t0.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/t0.com/privkey.pem;
    ssl on;

    location / {
        proxy_pass  http://localhost:8000;
    }
}

The directive for port 80 is modified so it redirects all http requests to port 443. Update the /etc/nginx/sites-enabled/t1.dom.com similarly and hey, you have two https sites running on the same server.

Cheers!