Now that's is so easy for me to create new containers and VMs with Proxmox, that's
exactly what I've been doing. However, I like to be a good netizen and use https
.
Here's my nginx config that lets me easily add a new LetsEncrypt certificate to a new vm/container for a new webapp.
Let's pretend to install Sentry.
My general pattern is to:
- run avahi so the vm is
locally available. eg
sentry.local
- make a dns entry on my provider for
sentry.burgundywall.com
- make an entry in nginx for
sentry.burgundywall.com
. This allows a public name to reverse proxy for an internal machine. - create and install an ssl certificate
- enjoy
https
goodness
avahi
Read the docs for your distro but it's probably no harder than apt
install avahi-daemon
. If you're doing this in container and running into problems
then see my article about that here.
dns entry
I use Gandi.net but follow the instructions
for your dns provider. You may have to wait an hour or two before your
entry is propagated. If certbot-auto
gives an error about unresolved
hostname that's what has happened.
I used to use dyn.com but they got bought by the worse netizen ever, Oracle.
nginx
Here's the meat of this post. Create two files that all vms/container will include. This is a one time thing. Note, your paths may be different.
# /etc/nginx/common/letsencrypt.conf
location /.well-known {
alias /var/www/html/letsencrypt/.well-known;
}
# /etc/nginx/common/redirect_ssl.conf
location / {
return 302 https://$host$request_uri;
}
Now create a new server configuration file:
# /etc/nginx/sites-available/sentry.conf
upstream sentry {
server sentry.local:9000 fail_timeout=0;
}
server {
server_name sentry.burgundywall.com;
listen 80;
include common/letsencrypt.conf;
include common/redirect_ssl.conf;
}
Link the new site and then reload nginx.
cd /etc/nginx/sites-enabled
ln -s ../site-available/sentry.conf
nginx -t && nginx -s reload
letsencrypt certificate
Install LetsEncrypt as per their instructions.
Now run the command to generate a new certificate.
certbot-auto certonly --webroot -w /var/www/html/letsencrypt/ -d sentry.burgundywall.com
So assuming that worked here's what happened:
certbot-auto
did some hand shaking withletsencrypt.com
and got a sentinel filecertbot-auto
then installed the sentinel to/var/www/html/letsencrypt/
letsencrypt.com
then did an http request for the sentinel- if the contents match what
letsencrypt.com
is expecting… - a certificate key-pair installed to
/etc/letsencrypt/live/sentry.burgundywall.com/
This handshaking proves that you are in control of this sub-domain.
new ssl entry in nginx
Now append the following to sentry.conf
.
server {
server_name sentry.burgundywall.com;
listen 443 ssl;
allow 192.168.1.0/24;
deny all;
ssl_certificate /etc/letsencrypt/live/sentry.burgundywall.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sentry.burgundywall.com/privkey.pem;
ssl_session_cache shared:SSL_sentry:1m;
access_log /var/log/nginx/sentry.access.log;
error_log /var/log/nginx/sentry.error.log;
#error_log /var/log/nginx/sentry.debug.log debug;
location / {
proxy_pass http://sentry;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
and reload
nginx -t && nginx -s reload
test
If you browse to http://sentry.burgundywall.com
you'll get redirected to
https://sentry.burgundywall.com
and get a nice green lock in your url bar.
renew
LetsEncrypt certificates are relatively short lived so you have to renew them
frequently. Thankfully the certbot-auto
can do that for us if we add it to
cron.
Check the command works properly, run it without --quiet
.
/opt/certbot-auto renew --no-self-upgrade -w /var/www/html/letsencrypt/
And then add it to a weekly cron job.
# as root
crontab -e
# add the following, double check your paths
@weekly /opt/certbot-auto renew --quiet --no-self-upgrade -w /var/www/html/letsencrypt/
# nginx doesn't automatically pickup the new certificates so reload every day, no downtime
@daily /sbin/nginx -s reload