Code Father's Blog

/dev/null/Project - Mar 22, 2019

Make your SSL Get An A+ Rating (NGINX Edition)

Update (2021-02-19): Important TLSv1.3 Note – For those of you looking to enable TLSv1.3 under Engintron, keep in mind that as of the latest update to this article cPanel is in-fact shipping with OpenSSL v1.1.1i.  However, the caveat is that NGINX is installed from the NGINX repository (, which currently ships a version of NGINX that’s built against OpenSSL v1.0.2k-fips.

In order to get TLSv1.3 support from NGINX, you’ll need to get NGINX from a source that compiled it against OpenSSL v1.1.1+.   It’s important to note that this is not the fault of Engintron in the sense that they’re not providing NGINX, they’re providing an installer and a WHM interface.

In order to get NGINX with TLSv1.3 support with Engintron, the only repository or RPM source is NGINX-MOD, which is a $7.00 per month subscription service.  If you feel that’s not an option, then you can try using NGINX from cPanel directly. It’s in “experimental” status as of right now, but it is compiled against OpenSSL v1.1.1i, which gives you TLSv1.3.  cPanel also doesn’t advise using it in a production environment due to it’s experimental status.  Lastly, you can compile NGINX from source on any cPanel server running cPanel v86+ since it’s got OpenSSL v1.1.1+ on it.  Until the NGINX repository is updated to provide NGINX compiled against OpenSSL v1.1.1+, there really is no other way to get TLSv1.3 support at this time.

Update (2020-12-22): The Feature-Policy header has been renamed to Permissions-Policy.  The headers provided have added the Permissions-Policy header but keeps the Feature-Policy header for compatibility for now.

We’ve provided the steps on how to get an A+ rating with  ImmuniWeb, as well as passing PCI-DSS, NIST, and HIPAA compliance as per the ImmuniWeb site.  However, those settings only apply to Apache servers running cPanel and Web Host Manager (WHM).  What about those of you that are running servers with NGINX?  Well, you can perform all of those settings in our prior post, but there are some additional steps you must take for NGINX servers.

For this guide, we’re running a CentOS 7 server with cPanel/WHM and Engintron as our NGINX installation source.  While these steps should be the same for NGINX servers, keep in mind that file names and other steps may differ.  Additionally, it may also be possible for your particular hosting provider to provide their own version of NGINX that’s modified for their servers.

Before we being, the question is going to come up.  Why Engintron?  Well, it came down to features and ease of use.  Engintron is one of the few (possibly the only at the time of this writing and subsequent updates) that has a WHM plugin so that you can manage your NGINX installation from within WHM and you don’t need to use the command line.  This can help a ton for those that are comfortable with making changes to Linux text files but lack the command line experience or confidence to do the work in the command line.  Otherwise, we haven’t seen a difference in the Engintron version of NGINX versus another version of NGINX.

To being, install Engintron from the steps listed on this page.

Now, with Engintron installed, head over to your WHM and make sure you login as the administrative user.  You may also have to login as Root to get full access if the Engintron options are not available.  Under the WHM logo, type “engin” and you’ll be presented with the lone “Engintron for cPanel/WHM” option.  Click on it.

The first thing we’re going to edit is the common_https.conf file.  Right under all of the copyrights, add or change the following lines (some entries may already be there, but need to be updated/changed:

# TLS/SSL common
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;

# Diffie-Hellman parameter for DHE ciphersuites (2048 bits)
ssl_dhparam /etc/ssl/certs/dhparam.pem;

# Protocols & Ciphers
ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0
# We don't want to use TLSv1.0, it's EOL and unsecure.
# ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_protocols TLSv1.2 TLSv1.3;
# This set of ciphers is from
# Force server-specified cipher order
ssl_prefer_server_ciphers on;

# Force OSCP Stapling
ssl_stapling on;
ssl_stapling_verify on;

Now, we added the following, but it’s optional if you want to:

# Set the secure resolvers
resolver valid=300s;
resolver_timeout 5s;

Now, click the “Update /etc/nginx/common_https.conf” button at the bottom.

The next edit is the nginx.conf file.  For that, select it from the left and then add the following near the bottom of the file, preferably above the Virtual hosts Configs entry.

# Security Headers
add_header X-XSS-Protection "1; mode=block;" always;
add_header X-Content-Type-Options "nosniff" always;

That pretty much does it for your NGINX configuration with Engintron.  Save your stuff, then reload and restart Engintron.

These changes do affect the header entries that needed to be in the .htaccess files for the sites.  So, in your sites, make sure the following has been added. Remember, .htaccess files are hierarchical, the order of operations if you will.  The items at the top of the file process before the items at the bottom.  Since we’re setting security protocols for browsers, these should be right up at the top, preferably after you’ve forced your traffic to use HTTPS instead of HTTP.  These are copied straight from the .htaccess file for this very site, just the domain sections have been edited, so make sure to update the “your-domain” areas.

# These force additional security for all pages. These values result in an "A+"
# grade at These also help the Qualsys SSL Labs and
# ImmuniWeb tests get an "A+" rating. Visit at:
# Qualsys SSL:
# ImmuniWeb: <<-- Preferred by
Header always set Content-Security-Policy "report-uri"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-UA-Compatible "IE=Edge"
Header always set Referrer-Policy "strict-origin"
Header set Cache-Control "no-transform"
Header set Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()"
Header set Feature-Policy "vibrate 'self'; sync-xhr 'self'"
Header set NEL "{\"report_to\":\"default\",\"max_age\":31536000,\"include_subdomains\":true}"
Header set Expect-Staple "report-uri=''"
Header set Expect-CT "max-age=0, report-uri=''"
Header set Report-To "{\"group\":\"default\",\"max_age\":31536000,\"endpoints\":[{\"url\":\"\"}],\"include_subdomains\":true}"
Header set NEL "{\"report_to\":\"default\",\"max_age\":31536000,\"include_subdomains\":true}"

# Rewrite any session cookies to make them more secure
# Make ALL cookies created by this server are HttpOnly and Secure
Header always edit Set-Cookie (.*) "$1;HttpOnly;Secure"

# Strip off double Secure or HttpOnly settings as if App and Apache sets above you can sometimes get both
Header edit Set-Cookie ^(.*);\s?Secure;?\s?(.*);\s?Secure;?\s?(.*)$ "$1; $2; $3; Secure"
Header edit Set-Cookie ^(.*);\s?HttpOnly;?\s?(.*);\s?HttpOnly;?\s?(.*)$ "$1; $2; $3; HttpOnly"

# Strip off double ;; settings
Header edit Set-Cookie ^(.*);\s?;\s?(.*)$ "$1; $2"

For those of you WordPress users that use the Really Simple SSL plugin, that second section does the secure cookies that you have to pay extra for.  The same goes for that Content-Security-Policy entry for HSTS. You’re welcome.

That’s it!  Head on over to ImmuniWeb to test your new settings and to Security Headers to test the headers for security protocols and misconfigurations.