With the loss of trust of Startcom certs I found myself needing a new way to obtain free SSL certificates. Let’s Encrypt is perfect for this. Unfortunately SophosUTM does not support Let’s Encrypt. It became time to replace Sophos as my reverse proxy. Enter nginx.
The majority of the information I used to get this up and running came from digitalocean with help from howtoforge. My solution involves CentOS7, nginx, and the let’s encrypt software.
Install necessary packages
sudo yum install nginx letsencrypt sudo firewall-cmd --add-service=http --permanent sudo firewall-cmd --add-service=https --permanent sudo systemctl enable nginx
Inform selinux to allow nginx to make http network connections:
sudo setsebool -P httpd_can_network_connect 1
Generate certificates
Generate your SSL certificates with the letsencrypt command. This command relies on being able to reach your site over the internet using port 80 and public DNS. Replace arguments below to reflect your setup
sudo letsencrypt certonly -a webroot --webroot-path=/usr/share/nginx/html -d example.com -d www.example.com
The above command places the certs in /etc/letsencrypt/live/<domain_name>
Sophos UTM certificates
In my case I had a few paid SSL certificates I wanted to copy over from Sophos UTM to nginx. In order to do this I had to massage them a little bit as outlined here.
Download p12 from Sophos, also download certificate authority file, then use openssl to convert the p12 to a key bundle nginx will take.
openssl pkcs12 -nokeys -in server-cert-key-bundle.p12 -out server.pem openssl pkcs12 -nocerts -nodes -in server-cert-key-bundle.p12 -out server.key cat server.pem Downloaded_CA_file.pem > server-ca-bundle.pem
Once you have your keyfiles you can copy them wherever you like and use them in your site-specific SSL configuration file.
Auto renewal
First make sure that the renew command works successfully:
sudo letsencrypt renew
If the output is a success (a message saying not up for renewal) then add this to a cron job to check monthly for renewal:
sudo crontab -e
30 2 1 * * /usr/bin/letsencrypt renew >> /var/log/le-renew.log
35 2 1 * * /bin/systemctl reload nginx
Configure nginx
Uncomment the https settings block in /etc/nginx/nginx.conf to allow for HTTPS connections.
Generate a strong DH group:
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
Create SSL conf snippets in /etc/nginx/conf.d/ssl-<sitename>.conf. Make sure to include the proper location of your SSL certificate files as generated with the letsencrypt command.
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
Here is a sample ssl.conf file:
server {
listen 443;
ssl_certificate /etc/letsencrypt/live/<HOSTNAME>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<HOSTNAME>/privkey.pem;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
access_log /var/log/<HOSTNAME.log>;
server_name <HOSTNAME>;
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_set_header X-Forwarded-Proto $scheme;
proxy_pass http://<BACKEND_HOSTNAME>/;
}
}
Redirect http to https by creating a redirect configuration file (optional)
sudo vim /etc/nginx/conf.d/redirect.conf
server {
server_name
<DOMAIN_1>
...
<DOMAIN_N>;
location /.well-known {
alias /usr/share/nginx/html/.well-known;
allow all;
}
location / {
return 301 https://$host$request_uri;
}
}
Restart nginx:
sudo systemctl restart nginx
Troubleshooting
HTTPS redirects always go to the host at the top of the list
Solution found here: use the $host variable instead of the $server_name variable in your configuration.
Websockets HTTP 400 error
Websockets require a bit more massaging in the configuration file as outlined here. Modify your site-specific configuration to add these lines:
# we're in the http context here map $http_upgrade $connection_upgrade { default upgrade; '' close; }
server {proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade;
}
Hey Nick,
great post – my server running w/ nice SSL now 🙂 Thx!
But I recognized a small bug in your post concerning the crontab for monthly renewal:
=> 30 2 * * 1 /usr/bin/letsencrypt renew >> /var/log/le-renew.log
=> 35 2 * * 1 /bin/systemctl reload nginx
…afaik means renewel each and every monday, not monthly.
Correct version:
30 2 1 * * /usr/bin/letsencrypt renew >> /var/log/le-renew.log
35 2 1 * * /bin/systemctl reload nginx
Greetz,
Flo.
Thanks for the clarification!