Serve Local Web Apps under a Custom Domain

When working on multiple web applications, it can be taxing to remember which applications are running on which ports. By default, Ruby on Rails serves on port 3000, MAMP serves on port 8888, many applications start up listening on port 8000, and you might even find yourself using a non-traditional port like 8012. Knowing where to find each application becomes increasingly difficult. It would be much more convenient to call up, say, http://launch/ in your browser, rather than http://localhost:3000/.

Fortunately, it only takes a few simple shell commands to accomplish such a feat.

I’m using a Mac, so these commands may not work quite the same way on other Unix-like systems. (In particular, Mac relies on ipfw to set port forwarding rules, while I understand Linux generally relies on iptables.)

If you’re on a Mac, these commands should work for you:

ifconfig lo0 alias $ip
ipfw add fwd $ip,$port tcp from any to $ip dst-port 80 > /dev/null
echo "$ip $domain" >> /etc/hosts

You’ll need three pieces of information to run these commands: an IP address, the port on which your application is running, and the domain under which you’d like to serve your application. You’ll also need superuser privileges for all three commonds.

The commands are surprisingly simple. The first aliases your machine’s loopback network connection under a new IP address, I usually choose one starting with 127.0.0.. The second command adds a port forwarding rule to connect the port on which your application is listening to port 80, the port on which your browser submits requests. The third command adds an alias for the IP address to your /etc/hosts file.

Here’s how it works. Suppose you use the IP address 127.0.0.2, serve your application on port 3000, and use the domain launch. When you load http://launch/ in your browser, the entry in your /etc/hosts file tells your machine to route the request to http://127.0.0.2/. When a URL doesn’t include a port, your browser assumes port 80, so you’re really hitting http://127.0.0.2:80/. Thanks to the new port forwarding rule, requests to 127.0.0.2:80 are routed to 127.0.0.2:3000. Because 127.0.0.2 is an alias for the loopback network interface, the request ultimately goes to http://localhost:3000/.

A more thorough script is on GitHub. It looks up what loopback IPs are already in your /etc/hosts file and generates a new one, as well as doing additional checks to avoid duplicate entries. Part of the reason for this checking is that I haven’t yet figured out how to persist new port forwarding rules through reboots, so if your machine restarts, you’ll need to re-run any ipfw commands.

I haven’t worked out the Linux solution to this problem. If you do, please leave a comment. I’m interested to see how it compares. Also, if you have any tips on persisting ipfw rules through reboots, please share!

 

Conversation
  • Bram says:

    Hi Eric,

    I don’t think the alias is needed because your loopback device will already respond to anything 127.0.0.0/8. Try leaving out the ifconfig alias to see if that works (I don’t own a mac).

    As for making the rules reboot persistent on Linux, you could add lines to /etc/rc.local but that’s considered bad practice. If you consider it part of the firewall setup, /etc/init.d/iptables might be there (look into iptables-save). Lastly, you can’t go wrong with just creating a new init script for your local init solution. These days you are writing either systemd, upstart or sysvinit scripts.

    Best of luck!

    • Eric Shull says:

      Hi Bram,

      Linux may behave differently than Mac in regard to 127.0.0._ addresses. On my Mac, the alias seems to be necessary in order to bind a server to that address. Without aliasing the loopback network interface, I get an address not available error.

      Thanks for asking!

  • Comments are closed.