Let’s Encrypt and Zend Framework on NGINX

In this blog post I will get into getting your hands dirty and setting up SSL encryption (HTTPS) with Let’s Encrypt for your PHP Zend Framework. So this article is for developers or DevOps that do NOT have the automated option given by more and more hosters. This tutorial is for Let’s Encrypt and Zend Framework on NGINX. So for Apache people, sorry. Can’t help you in this article though part of it is the same. For others with the same setup but different apps, do stick around as most of this applies to most web app setups in the same server environment

HTTPS and Let’s Encrypt

I wrote about the importance of securing your website using TLS or SSL to have a encrypted website starting with https and the green lock before. In that article I explained all the SEO benefits and ins and outs of HTTPS Encryption. I also stated that for basic encryption (Not OV or EV) you could use Let’s Encrypt.  Well, let’s go ahead and set it all up on your server shall we?

Prerequisites

There are a few things that need to be up and running before you can participate and set up a Let’s Encrypt HTTPS encrypted site on your server. Some may be obvious, but let’s put it all out there shall we? Here is the basic prerequisites list:

  • VPS or Dedicated Server
  • Ubuntu 16.0.4*
  • NGINX installed
  • Zend Framework
  • Sudo access
  • Domain name connected to your ip

*  With other OS you can follow this tutorial as well, but you will have to change the commands as your package manager will differ.

NGINX Access to .well-known

If your NGINX server is setup to not show .files in the webroot to the public you must make sure that the .well-known folder is accessible:

sudo nano /etc/nginx/sites-available/default

Inside the server block, add this location block:

Add to SSL server block
server {
        . . .

        location ~ /.well-known {
                allow all;
        }

        . . .
}

Once you made this change, or any NGINX changes for that matter do a

sudo nginx -t

to check whether it is all correct. And then do a server restart:

sudo service nginx restart

Locate Webroot

You should have set up your site details including the webroot for your Zend Framework app.  Default is:

/usr/share/nginx/html

But for most Zend Framework app this is more likely:

/usr/share/nginx/domain/ZendSkeletonApplication/public

You can find it either inside:

/etc/nginx/conf.d/default.conf

or

/etc/nginx/sites-available/default

In our test server case we did all in the former as we will run only one domain and one Zend App there. But most of you will edit the latter and I suggested so for the .well-known folder access as well. This webroot you will  need shortly to tell the Certbot for what site / domain you want the certificate to be set up for.

Let’s Encrypt Installation

To install Let’s Encrypt on your Ubuntu NGINX setup do the following. First run this command to install it:

sudo apt-get install letsencrypt

Once it has been installed you can instruct Let’s Encrypt to set up the certificate for you and do the necessary tests:

 letsencrypt certonly --webroot -w /usr/share/nginx/domain/ZendSkeletonApplication/public -d domain.com

You will be asked to enter an email address:

let's encrypt email
You will also have to agree with their TOS:

Let's Encrypt TOS

Then if all went well you will have your Zend Framework with the Let’s Encrypt Certificate running securely. You will get this confirmation in the terminal:

IMPORTANT NOTES:
 - If you lose your account credentials, you can recover through
 e-mails sent to you@domain.com.
 - Congratulations! Your certificate and chain have been saved at
 /etc/letsencrypt/live/domain.com/fullchain.pem. Your cert
 will expire on 2017-02-25. To obtain a new version of the
 certificate in the future, simply run Let's Encrypt again.
 - Your account credentials have been saved in your Let's Encrypt
 configuration directory at /etc/letsencrypt. You should make a
 secure backup of this folder now. This configuration directory will
 also contain certificates and private keys obtained by Let's
 Encrypt so making regular backups of this folder is ideal.
 - If you like Let's Encrypt, please consider supporting our work by:

Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
 Donating to EFF: https://eff.org/donate-le

Strong Diffie Hellman

To get the most secure certificate and a A+ rating at SSL Labs do the following:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

This creates a super secure 2048 bit Diffie Hellman group certificate.

Enforcing SSL/TLS on NGINX

To push NGINX to use SSL and no longer use ordinary https you will have to tell it to do so. Add the following to your NGINX config file. In our case doing a:

sudo nano /etc/nginx/conf.d/default.conf

NB Again, for most situations you would edit /etc/nginx/sites-available/default or the file in sites-available having your site’s name.

Then we tweaked the server block so you would see this at the top:

server {
 listen 443 ssl;

server_name domain.com;

ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:D$
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security max-age=15768000;

root /usr/share/nginx/domain/ZendSkeletonApplication/public;
index index.php index.html index.htm index.nginx-debian.html;

Part of the addition is using the certificates:

ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;

part using the strongest Diffie Hellman Encryption:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:D$
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security max-age=15768000;

And the very first server block line is simply enforcing https via the proper 443 port:

listen 443 ssl;

Push HTTP Traffic to HTTPS

We also pushed not https port 80 traffic to go full https using a new block with a 301 redirect:

server {
 listen 80;
 server_name domain.com;
 return 301 https://$host$request_uri;
}

This making sure no one is accessing your site using http via port 80.

Then save and check if it works:

sudo nginx -t

and then restart the server again:

sudo service nginx restart

Final Test

Once all that is done you should have Let’s Encrypt and Zend Framework on NGINX. A beautiful Zend app with an A+ certificate. Do test it at

https://www.ssllabs.com/ssltest/analyze.html?d=example.com

To make sure you have it running properly.

Troubleshooting

If you do see errors or do not get the green lock there are multiple possible issues. The certificate was not assigned properly and you somehow missed to warning of errors during the generation. Then please re-generate.

But most likely you have to deal with some hard coded http links or links to load non secure data from a third party. You may get warning on this such as:

Mixed Content: The page at 'https://domain.com/page' was loaded over HTTPS, but requested an insecure script 'http://www.skypeassets.com/i/scom/js/skype-uri.js'. This request has been blocked; the content must be served over HTTPS.

This means that you have to load that content securely as well. Should still not cause you to get a red lock and have the browser not accept your certificate, but you better solve it by loading from an https source. See more on this in earlier mentioned article here.

Renewal

To renew the certificate you can run:

letsencrypt renew

Further Reading: Cerbot Config Generator and DO Tutorial

Tagged in : Tagged in : ,
Jasper Frumau

Jasper has been working with web frameworks and applications such as Laravel, Magento and his favorite CMS WordPress including Roots Trellis and Sage for more than a decade. He helps customers with web design and online marketing. Services provided are web design, ecommerce, SEO, content marketing. When Jasper is not coding, marketing a website, reading about the web or dreaming the internet of things he plays with his son, travels or run a few blocks.