Put Localhost on HTTPS with Nginx
How to put a local app server on https.
Why
Why would you want https on a local app server? Well, it's cool, put it on your resume. It looks cool, impress your friends. There are also browser capabilities that require https, such as hardware access for camera.
Local IP Mapping
To set this up, the first thing we'll do is enter your name and number into the phone book, /etc/hosts, the first place for name lookup for addresses typed into your browser's omni-box.
Edit with sudo so you can save without having to restart your editor because the file's readonly to peons:
sudo vi /etc/hostsAnd add a line that connects 127.0.0.1, the IP for localhost, to whatever name you'd like. Here's an example of the dev environment for a site for yours truly:
127.0.0.1 dev.jaketrent.comSave and exit.
Reverse Proxy
Now we'll set up a reverse proxy to sit in front of our local app server. Why do we want a proxy?
A "reverse" proxy sits in front of a server. That's what we have. It's going to take care of HTTP termination, so that requests up to the proxy happen in https. The app server itself can remain in http mode. It's going to handle the port mapping from https on :443 to our app server, which is going to run on :3000. It's also going to map the hostname, dev.jaketrent.com to localhost.
We'll choose to install a proxy called nginx:
sudo apt install nginxAnd make sure to start it up:
sudo systemctl enable --now nginxSelf-signed Certificate
Now let's get https working. Https, aka SSL, or secure socket layer, is going to provide some security. The added assurances of https are two-fold: The site you're talking to is run by the people who purport to run it, and your conversation will be private.
A certificate, issued usually by a certificate authority, will do the identity checks to ensure site ownership. Then that certificate is also used as the key to encrypt communications to and from that site.
In this case, we will self-sign. This means that the certificate gives no benefit of security assurances, but it will exist so that the mechanism of https will work.
Let's download the tools to make a certificate:
sudo apt install mkcert libnss3-toolsNow let's make and install a new root certificate and private key:
mkcert -install
Created a new local CA 💥
The local CA is now installed in the system trust store! ⚡️
The local CA is now installed in the Firefox and/or Chrome/Chromium trust store (requires browser restart)! 🦊This makes it so that any self-signed certificate on your system will be trusted by your browser.
Now we want to create a certificate for the specific site:
cd /etc/nginx && sudo mkcert dev.jaketrent.com
Created a new local CA 💥
Note: the local CA is not installed in the system trust store.
Note: the local CA is not installed in the Firefox and/or Chrome/Chromium trust store.
Run "mkcert -install" for certificates to be trusted automatically ⚠️
Created a new certificate valid for the following names 📜
- "dev.jaketrent.com"
The certificate is at "./dev.jaketrent.com.pem" and the key at "./dev.jaketrent.com-key.pem" ✅
It will expire on 28 July 2028 🗓Start App Server
Now let's make sure that our local app server is started. That could be started any number of things. Start the process that makes the server app on a localhost/port combo. In my case, I'll run:
clj -M:serverNow that app server is available on localhost:3000
Add Site to Proxy
Now let's add localhost:3000 to the proxy so that we can do the port and name mapping and https certificate mapping.
On Debian systems, nginx uses site config under /etc/nginx/sites-enabled/. But we're going to author in /etc/nginx/sites-available/ so that we can store the original config there and then turn off/on in the "enabled" directory, leaving the configs in the "available" directory in tact.
sudo vi /etc/nginx/sites-available/jaketrent-webAnd set the config as this:
server {
listen 443 ssl;
server_name dev.jaketrent.com;
ssl_certificate /etc/nginx/dev.jaketrent.com.pem;
ssl_certificate_key /etc/nginx/dev.jaketrent.com-key.pem;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
}
}It's all mapping. Defines external 443 port listening. The name to respond to. Where the certificates are. That protocol, name and port to proxy to.
Now link "enabled" to what we just defined in "available"
ln -s /etc/nginx/sites-available/jaketrent-web /etc/nginx/sites-enabled/Now validate the config with a dry run:
nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successfulAnd restart the proxy:
sudo systemctl reload nginxOpen URL
Now you're set to open your browser and access your localhost app server with https at the name you set up:
xdg-open https://dev.jaketrent.comNote that your browser will still give you a warning and balk about your self-signed certificate. Open the Advanced option in order to continue onward to the site.
It'll work on https, though it will still look "unsafe", without a padlock.
Ah, it's either this https bliss or the beach at the South of France. Ahh...