How to Secure Nginx with SSL and Let’s Encrypt in FreeBSD

In this guide we’ll discuss how to secure Nginx web server in FreeBSD with TLS/SSL certificates offered for by Let’s Encrypt Certificate Authority. We’ll also show you how to automatically renew the Lets’ Encrypt certificates before the expiring date.

TLS, an acronym for Transport Layer Security, is a protocol which runs under HTTP protocol and uses certificates and keys in order to encapsulate the packets and encrypt the data exchanged between a server and a client, or in this case between Nginx web server and client’s browser, in order to secure the connection, so that a third party, who might intercept traffic, cannot decrypt the transmission.

Read Also: Install Let’s Encrypt for Apache on FreeBSD

The process of obtaining a free Let’s Encrypt certificate in FreeBSD can be greatly simplified by installing certboot client utility, which is the official Let’s Encrypt client used for generating and downloading certificates.

Requirements

  1. Install FBEMP (Nginx, MariaDB and PHP) stack in FreeBSD

Step 1: Configure Nginx TLS/SSL

1. By default, the TLS/SSL server configuration is not enabled in FreeBSD because the TLS server block statements are commented in Nginx default configuration file.

In order to activate the TLS server in Nginx, open nginx.conf configuration file, search for the line which defines the starting of SSL server and update the entire block to look like in the below sample.

# nano /usr/local/etc/nginx/nginx.conf

Nginx HTTPS block excerpt:

Nginx HTTPS Configuration
server {
       listen 443 ssl  default_server;
       server_name  www.yourdomain.com;
	
	access_log /var/log/nginx/access.log;
	error_log /var/log/nginx/error.log;
	error_page   500 502 503 504  /50x.html;
        
	location = /50x.html {
            root   /usr/local/www/nginx-dist;
        }
	
	location / {
	    root   /usr/local/www/nginx;
       	    index  index.html index.htm;
	    try_files $uri $uri/ /index.php?$args;
				}

	ssl_certificate "/usr/local/etc/letsencrypt/live/www.yourdomain.com/cert.pem";
	ssl_certificate_key "/usr/local/etc/letsencrypt/live/www.yourdomain.com/privkey.pem";
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
	ssl_dhparam /usr/local/etc/nginx/dhparam.pem;
	ssl_session_cache shared:SSL:1m;
	ssl_session_timeout 10m;
	ssl_ciphers HIGH:!aNULL:!MD5;
	ssl_prefer_server_ciphers  on;

	# Use gzip compression
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_buffers 16 8k;
gzip_http_version 1.0;

	# Set a variable to work around the lack of nested conditionals
	
	set $cache_uri $request_uri;
	
	location ~ /.well-known {
	allow all;
		}
    


        location ~ \.php$ {
        root	/usr/local/www/nginx;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        #fastcgi_param  SCRIPT_FILENAME /scripts$fastcgi_script_name;
        fastcgi_param SCRIPT_FILENAME $request_filename;    
		include        fastcgi_params;
        }	
    }

The above block, in addition to SSL block, also contains some statements for enabling gzip compression and FastCGI Process Manager, used for passing PHP code to PHP-FPM gateway in order to run dynamic web applications.

After you’ve added the above code to Nginx main configuration file, do not restart the daemon or apply the settings before installing and obtaining an Let’s Encrypt certificate for your domain.

Step 2: Install Certbot Client in FreeBSD

2. The process of installing Let’s Encrypt certbot client utility in FreeBSD involves downloading the source code for py-certbot and locally compile it, by issuing the below commands.

# cd /usr/ports/security/py-certbot
# make install clean

3. Compiling the py-certbot utility takes a lot of time comparing to installing a regular binary package. During this time, a series of dependencies are required to be downloaded in compiled locally in FreeBSD.

Also, a series of prompts will appear on your screen, demanding you to select what packages will be used at compile time for each dependency. At the first screen, select the following tools, by pressing [space] key, for compiling the python27 dependency, as illustrated in the below image.

  • IPV6
  • LIBFFI
  • NLS
  • PYMALLOC
  • THREADS
  • UCS4 for Unicode support
Enable UCS4 for Unicode
Enable UCS4 for Unicode

4. Next, select DOCS and THREADS for gettext-tools dependency and press OK to continue as shown in the below image.

Install Documentation
Install Documentation

5. On the next screen leave the TESTS option disabled for libffi-3.2.1 and press OK to move further.

Disable TESTS for libffi
Disable TESTS for libffi

6. Next, hit space to select DOCS for py27-enum34 dependency, which will install the documentation for this tool, and press OK to continue, as illustrated in the below screenshot.

Install Documentation for Py27
Install Documentation for Py27

7. Finally, choose to install example samples for py27-openssl dependency by pressing [space] key and hit OK to finish the compilation and installation process for py-certbot client.

Install Py27 Openssl
Install Py27 Openssl

8. After the process of compiling and installing py-certbot utility finishes, run the below command in order to upgrade the tool at the latest version of the package as illustrated in the below screenshots.

# pkg install py27-certbot
Upgrade Py-certbot Tool
Upgrade Py-certbot Tool

9. In order to avoid some issues it might occur while obtaining a free Let’s Encrypt certificate, the most common error being “pkg_resources.DistributionNotFound”, make sure the following two dependencies are also present in you system: py27-salt and py27-acme.

# pkg install py27-salt
# pkg install py27-acme

Step 3: Install Let’s Encrypt Certificate for Nginx on FreeBSD

10. In order to obtain a Let’s Encrypt standalone certificate for your domain, run the following command and provide you domain name and all subdomains you wish to obtain certificates for by implying the -d flag.

# certbot certonly --standalone -d yourdomain.com -d www.yourdomain.com
Install Lets Encrypt for Nginx
Install Lets Encrypt for Nginx

11. While generating the certificate you will be asked to enter you email address and to agree with Let’s Encrypt terms of service. Type a from keyboard to agree and continue and you will also be asked if you willing to share your email address with Let’s Encrypt partners.

In case you don’t want to share your email address, just type no word in the prompt and press [enter] key to continue. After the certificates for your domain had been successfully obtained, you will receive some important notes which will inform you where the certificates are stored in your system and when they expire.

Lets Encrypt Summary
Lets Encrypt Summary

12. In case you want to obtain a Let’s Encrypt certificate using the “webroot” plugin by adding the webroot directory of Nginx server for your domain, issue the following command with the --webroot and -w flags. By default, if you haven’t changed Nginx webroot path, it should be located in /usr/local/www/nginx/ system path.

# certbot certonly --webroot -w /usr/local/www/nginx/ -d yourdomain.com -d www.yourdomain.com

As in the --strandalone procedure for obtaining a certificate, the --webroot procedure will also ask you to supply an email address for certificate renewal and security notices, to press a to agree with Let’s Encrypt terms and conditions and no or yes to or not share the email address Let’s Encrypt partners as illustrated in the below sample.

Be aware that certbot client can detect a fake email address and will not let you continue with generating a certificate until you supply a real email address.

Cerbot sample:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel):[email protected]  #A fake email address will be detected
There seem to be problems with that address. Enter email address (used for
urgent renewal and security notices)  If you really want to skip this, you can
run the client with --register-unsafely-without-email but make sure you then
backup your account key from /etc/letsencrypt/accounts   (Enter 'c' to cancel):[email protected]

-------------------------------------------------------------------------------
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf. You must agree
in order to register with the ACME server at
https://acme-v01.api.letsencrypt.org/directory
-------------------------------------------------------------------------------
(A)gree/(C)ancel: a ------------------------------------------------------------------------------- Would you be willing to share your email address with the Electronic Frontier Foundation, a founding partner of the Let's Encrypt project and the non-profit organization that develops Certbot? We'd like to send you email about EFF and our work to encrypt the web, protect its users and defend digital rights. ------------------------------------------------------------------------------- (Y)es/(N)o: n Obtaining a new certificate Performing the following challenges: http-01 challenge for www.domain.com Using the webroot path /usr/local/www/nginx/ for all unmatched domains. Waiting for verification... Cleaning up challenges IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at /usr/local/etc/letsencrypt/live/www.yourdomain.com/fullchain.pem. Your cert will expire on 2017-12-28. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - Your account credentials have been saved in your Certbot configuration directory at /usr/local/etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Certbot so making regular backups of this folder is ideal. - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le

Step 4: Update Nginx TLS Certificates

13. The location of obtained Let’s Encrypt certificates and keys in FreeBSD is /usr/local/etc/letsencrypt/live/www.yourdomain.com/ system path. Issue ls command in order to display the components of your Let’s Encrypt certificate: the chain file, the fullchain file, the private key and the certificate file, as illustrated in the following example.

# ls /usr/local/etc/letsencrypt/live/www.yourdomain.com/
List Lets Encrypt Domain SSL-Keys
List Lets Encrypt Domain SSL-Keys

14. In order to install Let’s Encrypt certificates for your domain in Nginx web server, open Nginx main configuration file or the configuration file for Nginx TLS server, in case it’s a separate file, and modify the below lines to reflect the path of let’s Encrypt issued certificates as illustrated below.

# nano /usr/local/etc/nginx/nginx.conf

Update the following lines to look like in this sample:

ssl_certificate "/usr/local/etc/letsencrypt/live/www.yourdomain.com/cert.pem";
	ssl_certificate_key "/usr/local/etc/letsencrypt/live/www.yourdomain.com/privkey.pem";
Configure SSL for Nginx
Configure SSL for Nginx

15. Also, if the line ssl_dhparam is present in Nginx SSL configuration, you should generate a new 2048 bit Diffie–Hellman key with the following command:

# openssl dhparam –out /usr/local/etc/nginx/dhparam.pem 2048 

16. Finally, in order to activate Nginx TLS configuration, first check Nginx global configuration for possible syntax errors and, then, restart Nginx service to apply the SSL configuration by issuing the following commands.

# nginx -t
# service nginx restart

17. Confirm if Nginx daemon is binding on 443 port by issuing the following commands which can list all opened network sockets in the system in listening state.

# netstat -an -p tcp| grep LISTEN
# sockstat -4 
Verify Nginx Ports
Verify Nginx Ports

18. You can also visit your domain address via HTTPS protocol by opening a browser and type the following address in order to confirm that Let’s Encrypt certificates are working as expected. Because you’re using certificates generated by a valid Certificate Authority, no error should be displayed in the browser.

https://www.yourdomain.com

19. Openssl utility can also help you find information about a certificate obtained from Let’s Encrypt CA, by running the command with the following options.

# openssl s_client -connect www.yourdomain.com:443
Check SSL Certificate
Check SSL Certificate

In case you want to force Nginx to direct all http to https requests received for your domain on port 80 to HTTPS, open Nginx configuration file, locate the server directive for port 80 and add the below line after server_name statement as illustrated in the below example.

rewrite ^(.*) https://www.yourdomain.com$1 permanent;
Nginx Redirect HTTP to HTTPS
Nginx Redirect HTTP to HTTPS

20. Setting up auto renewal for certificate issued by Let’s Encrypt authority before they expire can be done by scheduling a cron job to run once a day by issuing the following command.

# crontab -e

Cron task to renew certificate.

0 0 * * * certbot renew >> /var/log/letsencrypt.log

That’s all! Nginx can now serve secured web applications to your visitors using Let’s Encrypt free certificates.

Matei Cezar
I'am a computer addicted guy, a fan of open source and linux based system software, have about 4 years experience with Linux distributions desktop, servers and bash scripting.

Each tutorial at TecMint is created by a team of experienced Linux system administrators so that it meets our high-quality standards.

Join the TecMint Weekly Newsletter (More Than 156,129 Linux Enthusiasts Have Subscribed)
Was this article helpful? Please add a comment or buy me a coffee to show your appreciation.

3 thoughts on “How to Secure Nginx with SSL and Let’s Encrypt in FreeBSD”

  1. Hi, thanks for the tutorial. It is great. I am using Freebsd 11.1 and this command did not work for me:

    # certbot certonly --standalone -d yourdomain.com -d www.yourdomain.com
    

    it returned no match

    However, certbot alone did work and took me through all the steps above. It also gave me the option to secure all my domains. I entered yes, and everything else worked just like above.

    Thanks again.

    Reply

Got something to say? Join the discussion.

Thank you for taking the time to share your thoughts with us. We appreciate your decision to leave a comment and value your contribution to the discussion. It's important to note that we moderate all comments in accordance with our comment policy to ensure a respectful and constructive conversation.

Rest assured that your email address will remain private and will not be published or shared with anyone. We prioritize the privacy and security of our users.