Introduction
I have a dev server (currently running Ubuntu 14.04 LTS), which I have been using for a while now for hosting various development tools on different ports. Because the ports can be hard to remember I have decided to to use port 80 for all of my services and do the port forwarding internally, based off hostname.
Instead of writing domain.com:5432, I can simply access it through sub.domain.com
For example the application X, which is using the port 7547 and is running on sub.domain.com has the following nginx configuration:
upstream sub {
server 127.0.0.1:7547;
}
server {
listen 80;
server_name sub.domain.com www.sub.domain.com;
access_log /var/log/nginx/sub.log combined;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:7547;
proxy_set_header Authorization "";
}
}
The Question
Given the current configuration structure, which I have chosen, is it possible to use letsencrypt and run the different services under https?
Best Answer
Yes, you can have nginx proxy requests to HTTP servers, and then itself respond to clients over HTTPS. When doing this, you will want to be sure that the nginx<->proxy connect is unlikely to be sniffed by whoever is your expected attacker. Safe-enough approaches might include:
Proxying to another host on the public Internet is unlikely to be safe-enough.
Here are instructions for obtaining a Let's Encrypt certificate using the same webserver you are using as a proxy.
Requesting your initial certificate from Let's Encrypt
Modify your
server
clause to allow the subdirectory.well-known
to be served from a local directory, eg:http://sub.domain.com/.well-known
is where the Let's Encrypt servers will look for the answers to the challenges it issues.You can then use the certbot client to request a certificate from Let's Encrypt using the webroot plugin (as root):
Your key, certificate, and certificate chain will now be installed in
/etc/letsencrypt/live/sub.domain.com/
Configuring nginx to use your certificate
First create a new server clause like this:
Reload nginx:
Verify that HTTPS now works by visiting
https://sub.domain.com
andhttps://www.sub.domain.com
in your browser (and any other browsers you specifically wish to support) and checking that they don't report certificate errors.Recommended: also review raymii.org: Strong SSL Security on nginx and test your configuration at SSL Labs.
(Recommended) Redirect HTTP requests to HTTPS
Once you have confirmed that your site works with the
https://
version of the URL, rather than have some users served insecure content because they went tohttp://sub.domain.com
, redirect them to the HTTPS version of the site.Replace your entire port 80
server
clause with:You should also now uncomment this line in the port 443 configuration, so that browsers remember to not even try the HTTP version of the site:
Automatically renew your certificate
You can use this command (as root) to renew all certificates known to certbot and reload nginx using the new certificate (which will have the same path as your existing certificate):
certbot will only attempt to renew certificates that are more than 60 days old, so it is safe (and recommended!) to run this command very regularly, and automatically if at all possible. Eg, you could put the following command in
/etc/crontab
:You can test renewals with either a dry-run, which will contact Let's Encrypt staging servers to do a real test of contacting your domain, but won't store the resulting certificates:
Or you can force an early renewal with:
Note: you can dry run as many times as you like, but real renewals are subject to Let's Encrypt rate limits.