How do I route a subdomain to an application running on my homeserver on a specific port?

Do I need to be running a DNS server [to do this]?

No. You need to be running a reverse proxy. Apache or nginx are both web servers that can be used for this purpose.

In short, you would create either a virtual host (Apache) or server block (nginx) for app.example.com, which would then be set up to forward requests for app.example.com to e.g. http://192.168.0.13:9177.

Regarding DNS, app.example.com would point to your public IP (typically your router, which would then direct web requests to your reverse proxy).


The other answers are all true, but I'll elaborate a bit to set some more minor details straight.

The first thing to realize is - when you type http://app.example.com/path/to/resource.jpeg in your browser, the first thing your browser does is to use the DNS system to translate from app.example.com to your external IP address (you need to set this up yourself, obviously). And then it tries to connect to that IP address.

Since no port was specified in the original URL, it will look at the protocol (http in this case) an choose the default port number for that protocol (80 for http). So then it connects to that IP and that port.

Note that you have no way to specify a different port in the DNS system. If a custom port wasn't in the URL to begin with, then the default will be used, period.

Now, since your actual web server was running behind your router on an internal IP address, and the external IP address belongs to your router, you'll need to set up port forwarding on the router. So that when someone connects to the externalIP:80 the router will then create another connection to 192.168.0.13:9177 and forward all the data back and forth between the two connections (nitpicking: it's actually a bit different, but you can think of it like that).

This is all nice and fine as long as you have only one web application. But if you want to have TWO web applications, and distinguish them by the domain - you can't do it this way. The precise domain you have requested is only transmitted once the connection is already opened, but the router needs to make the port-forwarding decision BEFORE the connection is opened. It doesn't know which domain the incoming request is for until it's already too late.

In this case you need the reverse-proxy. The reverse proxy is like another web application, but what it does is simply accept HTTP requests, check out what domain was requested, open another connection depending on that and then forward all the data between them. It's a bit more involved than just blindly forwarding binary data (what the router does for its port forwarding), since the reverse proxy needs to understand (and likely modify) the contents of the HTTP request.

The reverse proxy might be installed on your router, or on your home server next to the web applications, or on a separate machine. That's up to you.

Oh, and if your web-applications all use the same webserver anyway (like Apache Httpd or Nginx), then they support "virtual hosts" by themselves, and you don't need an additional reverse proxy at all.

P.S. Slightly out of scope, but consider also setting up HTTPS. With free (as in beer) certificates available from Let's Encrypt, it's really a good idea. Your reverse proxy can also handle this part, meaning no changes need to be made to the web application.