Introduction
Having a HTTPS (Hypertext Transfer Protocol Secure) certificate on your website will improve the security of your website (especially if your site processes personal information like passwords or payment details) and will make your site look more professional with the green lock.
If you are already using a domain with your website, it's completely free!
Despite this tutorial being focused on websites, a Let's Encrypt TLS certificate can be used with other services like SMTP/IMAP (mail servers), FTP, or XMPP (IM servers)
This tutorial will guide you through the steps necessary to update an already existing FreeBSD 12 server with a FEMP stack to use a HTTPS certificate provided by Let's Encrypt. If you do not have a FEMP stack setup yet, please follow this tutorial first.
- It is assumed that you are running as the
root
user during this guide. Usesu
to change toroot
if you are not running asroot
already.
Prerequisites
- A FreeBSD 12 server with root access.
- A FEMP stack (FreeBSD, Engine X, MySQL, PHP) installed as setup in this tutorial.
- A domain or subdomain which can work with Let's Encrypt (e.g. *.your-server.de won't work as it has a CAA record preventing certificates for Let's Encrypt)
Step 1 - Configuring Domain DNS Records
If your domain/subdomain is already pointing to your server through the use of an A and/or AAAA record -- you may skip this step.
Through your domain registrar or DNS hosting service, you need to create either an A record for an IPv4 address, or an AAAA record for an IPv6 address.
The TTL (Time to live) of your domain will tell DNS resolvers how often in seconds to query the DNS server for changes to the record. There is no minimum time requirement, but between 3600 seconds (one hour) and 86400 seconds (one day) is a good TTL range.
Here is an example of what that may look like for the domain "example.com"
Step 2 - Updating FreeBSD
By default, FreeBSD does not come with the pkg
package manager, but comes with a tool to bootstrap it. If FreeBSD asks to install it, answer 'Yes'.
It is best to update the system beforehand to ensure you are getting the latest packages when installing certbot
. You can do this by running the following command:
pkg update ; pkg upgrade
This will update the repositories of pkg
, and then upgrade any installed packages that you may have.
Step 3 - Installing Certbot
This will install certbot through pkg
. Alternatively the pip
package manager for Python may be used if it is installed.
Certbot can be installed by using the pkg
tool that may have been installed in the previous step. To do this, run the following command:
pkg install py37-certbot
Assuming that your webroot directory is in /var/www/html/
as setup in the previous tutorial, run the following command to get your TLS certificate:
- Replace example.com with the domain you are using. To add additional subdomains, just use the
-d
option with certbot, prefaced with the webroot with-w
if using a different server root. e.g.-d example.com -d www.example.com
certbot --webroot -w /var/www/html -d example.com
It will ask for your email address. Please put a real email address here, as this will be used for security notices and renewal notices in case auto-renewal fails.
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel):
You must agree to the Terms of Service of letsencrypt.org to be able to get your certificate.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel:
You should now have your SSL certificate and chain saved at /usr/local/etc/letsencrypt/live/example.com/
.
It would be a good idea to backup your /usr/local/etc/letsencrypt
folder as it contains your account credentials. If you lose it you will need to repeat this process again.
Your certificate will expire after 3 months, and you can renew certificates 1 month before they expire. Simply running certbot renew
will renew your certificate.
Automatic renewal is preferred however, to make sure someone browsing your site doesn't see an error relating to certificate expiration. To have certbot
automatically attempt a renewal every week:
echo 'weekly_certbot_enable="YES"' >> /etc/periodic.conf
Step 4 - Configuring Nginx to use HTTPS
Now we will be configuring Nginx to utilise the certificate we just created with certbot
.
But first, we need to create a new Diffie-Hellman group for Nginx as it is a good idea for security:
This may take a few minutes to complete
openssl dhparam -out /usr/local/etc/letsencrypt/dhparams.pem 2048
We will be using the "Intermediate" Server Side TLS configuration that Mozilla provides. Very old clients may not be able to connect to your website with this however, if this is importtant consider using the "Old" configuration. Keep in mind the security implications in doing so however.
If you followed the FEMP tutorial your nginx
configuration (/usr/local/etc/nginx/nginx.conf
) should look something like this -- without the commented out parts:
server {
listen 80;
listen [::]:80; # If using IPv6
server_name example.com;
root /var/www/html;
index index.php index.html index.htm;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/local/www/nginx-dist;
}
location ~ [^/]\.php(/|$) {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
try_files $uri $document_root$fastcgi_script_name =404;
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
The following changes need to be made:
- Change
listen 80;
andlisten [::]:80;
tolisten 443 ssl http2;
andlisten [::]:443 ssl http2;
respectively. - Add an additional server block listening on port 80, for redirecting HTTP connections to HTTPS.
- Adding the TLS certificate, key, and dhparam paths.
- Configuration relating to TLS session.
- Specifying allowed TLS protocols and ciphers to ensure no outdated ciphers vulnerable to attacks are offered by the server.
- Requiring HTTPS always by adding a header for HSTS (HTTP Strict Transport Security).
- Making sure your servers domain or subdomain is listed under
server_name
.
Nginx's configuration should look something like this:
server {
listen 80 default_server;
listen [::]:80 default_server; # If using IPv6
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2; # If using IPv6
server_name example.com;
root /var/www/html;
index index.php index.html index.htm;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/local/www/nginx-dist;
}
location ~ [^/]\.php(/|$) {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
try_files $uri $document_root$fastcgi_script_name =404;
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
ssl_certificate /usr/local/etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /usr/local/etc/letsencrypt/live/example.com/privkey.pem;
ssl_dhparam /usr/local/etc/letsencrypt/dhparams.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:le_nginx_SSL:1m;
ssl_session_tickets on;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
add_header Strict-Transport-Security "max-age=63072000" always;
}
Then to test your configuration, restart nginx:
service nginx restart
Conclusion
Congratulations! Your web server is now using HTTPS, and redirecting HTTP to HTTPS!
- Consider testing your server's HTTPS configuration with Qualys's SSL Server Test to see how your TLS configuration is rated. If you followed this tutorial you should get an
A+
grade. - HSTS is enabled as part of the configuration, but won't be acknowledged by browsers until the initial connection to your site. To have your domain included as part of the HSTS Preload list, please see https://hstspreload.org.