Get your web application accessible under a subdomain

(Using nginx)

Suppose you have a domain such as domain.com and you would like to provide access to a number of sites under your domain.

There are at least two ways you can achieve it. Either by appending a name i.e. domain.com/appName or by specifying a sub-domain such as appname.domain.com.

I had to configure both. However I found that having a name after the domain is a lot trickier when using a proxy server. Why? In such setup your application needs to know the exact root url, so that it generates proper links on its pages. What that usually means is that you need to configure it properly every time you change the name after the domain. Additionally your nginx configuration is more involved as you need to apply rewrite and sometimes use multiple location entries.

The alternative solution where you use sub-domains does not require so much hassle. All you need to do is proxy each request to the underlying web application running on localhost.

Example of contents of a file /etc/nginx/domain.com (linked from /etc/nginx/sites-enabled/domain.com)

server {
  listen 80;
  listen [::]:80;

  server_name subdomain.domain.com www.subdomain.domain.com;

  # => dot net core - theapp on Kestrel
  location / {
    proxy_pass http://localhost:5001;
    proxy_http_version 1.1;
    proxy_set_header Connection keep-alive;
    proxy_set_header Host $host;
  }
  # <= dot net core on Kestrel
}

The above file could have multiple virtual server definitions. For our purpose we need only one. The clause server { (…) } defines a virtual server that will listen on port 80. Nginx will pick this virtual server as long as it matches the host name of the request (it has to be the best match out of all the possibilities).

The next thing for Nginx to do is picking the location. Requesting subdomain.domain.net is equivalent to subdomain.domain.net/ and the location / will be used as it is the only one that happens to match. Here we tell Nginx:
1. to proxy the request to localhost:5001.
2. to reuse the existing tcp connection (keep-alive) rather than recreating a new connection on each subsequent request (e.g. for resources of the page)
3. to set the host header to the original from the request.

That is all that is required for a simple case where we do not require securing the data sent between the client and the server.

If our app sends any sensitive data to and from the server then we would have to force https connections. For such connections we will need a certificate. We can obtain one for free from e.g. Let’s Encrypt. This is a subject for another post.

Leave a Reply

Your email address will not be published.