Testing HTTPS Locally With Nanobox

12 July 2017

About two months ago, we published an article on using ngrok to share your app on the public Internet. This is still the simplest way to test HTTPS logic in your apps during development (though dry-run deployments do support HTTPS), and it's the best way to share your app before deploying it. But sometimes it's not the best option for everything.

In some cases, you can't use ngrok because you don't have access to the public Internet — being on a plane, for example, or otherwise too far from WiFi or other Internet sources. In others, you have access, but it's not reliable enough to use external services to test your apps — such as at conferences or in hotels where the WiFi is overloaded. In many other cases, your app isn't permitted to be publicly Internet-accessible during development at all, even with access controls and/or random domain naming in place to limit exposure. And so on.

Luckily, there is another option. Put simply, you just need to set up a local web server on your host to proxy requests to your app. While documentation already exists for how to do this, more or less, using whichever web server you prefer, I'm going to detail how to approach this specifically with Nanobox in mind, using Nginx as the proxy server. By the end of this article, you should be able to set up and take down an Nginx proxy in front of any app on your system.

Preparing Your System

Before we get started, a quick note to Windows users. You will need to install the Ubuntu app from the Windows Store, and run the following commands inside that app in order to make these instructions work. A future revision of this article may include instructions for other approaches (such as running these on older versions of Windows). Of course, you're more than welcome to adapt the process given here for use in Windows without waiting for us to get around to it. Hopefully, you'll share your results if you do!

Setting Up Nginx

Obviously, the first step is to install Nginx. Full instructions for that are well beyond the scope of this article, as they're extremely OS-dependent, but luckily the Nginx Wiki has an entry that covers the process for all supported systems. So we'll continue on from here assuming you already have Nginx installed.

You'll also need OpenSSL, so be sure to grab and install that, too. Most *NIX systems come with OpenSSL pre-installed, but Windows specifically does not. You can find ready-to-use versions at the OpenSSL Wiki.

The next step is to create a base Nginx configuration. In many cases, the configuration that ships with your Nginx installer will be a good place to start, and it may even be set up for hosting multiple sites already, though it will most likely be geared toward hosting local files and folders, rather than proxying requests to other servers. Either way, we're going to create our own space for holding Nanobox proxy configurations, partly to keep them separated clearly from other configurations, and partly for consistency across systems.

If your installation of Nginx has a folder for extra configuration files (usually conf.d or similar), separate from the one(s) for virtual hosts (usually either sites-available [with references from sites-enabled to turn them on and off], or vhosts), create a new file in there (that is, in conf.d or similar) called nanobox.conf and insert the following lines in there. If your installation doesn't have such a directory, add these lines to your main nginx.conf instead, inside the http {} block (go ahead and add one if it doesn't already exist, but it probably does):

Note: We want to use the conf.d approach — if possible — because it is the most resilient during software upgrades. Package managers aren't easily able to merge user changes with package changes to config files, so we want to use files that aren't included in the Nginx package itself.

Now, in the same directory as your nginx.conf, create a subdirectory called nanobox/ — this is where we'll place our configs to actually proxy requests to our apps. In that same directory, next to nanobox/, create a file called nanobox.app — we'll use this file to hold the template we'll be using to generate the app configs that will go in nanobox/. Go ahead and add the following lines to nanobox.app:

Note: In Windows, change /etc/ssl to the path where you want to store your certificates before saving. I'm going to use C:\ssl in this article, but you'll want to use the actual path on your system. Also note that the Nginx config requires you to use forward slashes (/) in paths instead of backslashes (\), even on Windows.

When you're done, you should have something like this directory structure:

nginx/
conf.d/
nanobox.conf
nanobox/
nanobox.app
nginx.conf

Creating A Base Certificate

Create /etc/ssl/nanobox/nanoapp.local.cnf (or C:\ssl\nanobox\nanoapp.local.cnf [for example] in Windows) with the following contents (adjust the *_default values to whatever's appropriate for you and your apps, but leave the {DOMAIN} reference somewhere in the commonName_Default line, because we'll need it later to avoid certificate collisions):

Finally, you'll probably want to import the base cert (nanoapp-base.crt) into your browser, so that it will automatically trust all the app certificates you'll create later. Full instructions on how to do that vary by both browser and OS, so are beyond the scope of this article, but thankfully, there are tutorials for this all over the Internet — just look for a recent one.

Adding An App

In a few moments we're going to create a script to handle this process for us, but I wanted to walk through doing it manually, first, so you can see what's going on, and even skip the script if you like. If you're not interested in how this all works, go ahead and skip to the finished script, below.

Internal DNS Alias

The first step when adding a new app to your Nginx proxy is to set up a DNS alias that Nginx can use to find your app internally. This is not a domain name you'll use to access your app – it's intended to be used exclusively by Nginx – so we'll set this to a name you're not likely to use directly:

nanobox dns add dry-run my-app.dry-run.nanoapp.local

Note that we put dry-run in the domain name. This is so you can proxy both your development and dry-run environments simultaneously. If you wanted to set up a proxy for your development environment instead, you'd use this command:

nanobox dns add local my-app.local.nanoapp.local

Notice that we've used .nanoapp.local here — this was chosen intentionally to mirror the .nanoapp.io CNAME domain given to every production app. You can use whatever you like, here, but don't omit it entirely – the name you use here must be different from the name you actually want to connect with, or none of this will actually work.

Note: These instructions include support for proxying your dry-run environments, but this is no longer really required to get HTTPS working with dry-run, as it's now built into the dry-run environment itself. You are, of course, free to proxy these environments anyway.

Proxy Configuration

OK, so now that you have set up the internal alias, it's time to copy our template into place and fill it out correctly.

And of course, use the actual location of your Nginx configuration files instead of the paths given above, and the actual domain you want to point to your app instead of example.local.

The last thing to do, now, is to set up the domain to point to your Nginx server. Open /etc/hosts (or %WinDir%\System32\drivers\etc\hosts on Windows) and add the following line to it. It can go anywhere in the file, but we recommend near the bottom to make it easy to find later.

127.0.0.1 example.local *.example.local

Note: You'll need admin rights to save changes to your hosts file.

As a quick reminder, the name you're adding here is the one you're planning to use to connect to your app with, and must be different from the internal name you added earlier with nanobox dns add.

Certificates For SSL

In order for the HTTPS portion of all this to work, the certificates have to actually exist. We created a base certificate, above, to handle one part of it. Now to handle the rest.

This certificate is only valid for one year. You can adjust the number of days, if you like, or just repeat this part of the process in a year or so when/before the certificate expires.

Testing The Result

The last step is to reload the Nginx configuration and test that everything works. First, we can ask Nginx to look the config over for any obvious problems:

sudo nginx -t

If everything is OK, we can restart the server:

sudo nginx -s reload

Go ahead and open http://example.local in your browser and make sure you can see your app. Don't worry if your app automatically redirects to https://example.local — you'll want to test that one next anyway. If both are working, then you've got everything set up correctly, and can move forward with your development and/or testing. If not, something went wrong, above, and you'll have to try it again. If you're still stumped, feel free to comment below.

Removing An App

This part is really easy. All we have to do is remove the files we created above, and reload the server configuration again.

The Complete Script

The script we're about to build takes all the steps above and combines them into a single file. Because it's designed to work for any and all of your apps, there are some options we need to be able to pass to it to set things up properly, and it has to be run from the root directory of your project (just like the nanobox commands). Be sure to adjust it for any differences between it and your own system!