Adding SSL to NGINX

May 19, 2017 2.7k views

I am not sure how to open port 443 on the server for SSL.

When I run sudo lsof -iTCP -sTCP:LISTEN -P

Here is what i get

memcached 1723 memcache 26u IPv4 14967 0t0 TCP *:11211 (LISTEN)
beanstalk 1736 beanstalkd 3u IPv4 14417 0t0 TCP *:11300 (LISTEN)
sshd 1746 root 3u IPv4 14992 0t0 TCP *:22 (LISTEN)
sshd 1746 root 4u IPv6 15001 0t0 TCP *:22 (LISTEN)
redis-ser 1773 redis 4u IPv4 14989 0t0 TCP *:6379 (LISTEN)
postgres 2051 postgres 6u IPv4 17225 0t0 TCP *:5432 (LISTEN)
postgres 2051 postgres 7u IPv6 17226 0t0 TCP *:5432 (LISTEN)
mysqld 2078 mysql 27u IPv6 17340 0t0 TCP *:3306 (LISTEN)

5 Answers


What OS (Operating System) are you running?


Unless NGINX is configured to listen on port 443, you generally won't see that port in the listing when you run that command. You'd need a valid server block that specifically listens on port 443 before it'll be listed.

For example:

server {
    listen [::]443 ssl http2;

    location / {
        try_files $uri $uri/ /index.php;

The above is a very basic server block and doesn't define much of what's needed for SSL (yet), but it gives you an idea of what you need to be using for NGINX to listen on port 443.

A more complete example would be:

server {
    listen [::]:80;

    return 301 https://$host$request_uri;

    listen [::]:443 ssl http2;

    resolver valid=300s;
    resolver_timeout 5s;

    ssl on;
    ssl_certificate /path/to/ssl/cert.pem;
    ssl_certificate_key /path/to/ssl/private.pem;

    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    ssl_ecdh_curve secp384r1;
    ssl_prefer_server_ciphers on;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_session_cache shared:SSL:50m;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_session_tickets off;
    ssl_session_timeout 5m;

    root /home/nginx/htdocs/public;

    location /
        try_files $uri $uri/ =404;

The above redirects requests on port 80 to 443 so everything is handled by SSL.

Here is my server configuration.

No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.1 LTS
Release: 16.04
Codename: xenial


Since you're running Ubuntu, unless you have ufw enabled, you won't need to physically open the port. The configuration that I posted above is how you'd go about getting NGINX to listen on 443.

You'd need to change to your actual domain and modify the path to your SSL cert and private key file as well as set up the location blocks to fit with your application.

Beyond that, additional configuration may or may not be needed depending on the type of site that you're trying to serve.

I don't have .pem files. Is that good

here is the keys i have

 ssl_certificate /etc/nginx/ssl/;
    ssl_certificate_key /etc/nginx/ssl/;

  • @kyoukhana

    Sorry I missed this one! To ensure I get notifications, make sure you include @jtittle in each reply -- that sends me a notification when you do and I can get back to you faster :-).


    As for the SSL, some use PEM files, some use crt and key -- whichever you're provided with is fine. It'll work the same.

    You'd simply replace my two lines:

        ssl_certificate /path/to/ssl/cert.pem;
        ssl_certificate_key /path/to/ssl/private.pem;

    With your actual paths, as you did in your response, and then restart NGINX. This is the standard way of doing it and will work in most cases, though if Forge configures things differently, my previous configuration may not work.

    I've not personally used Forge, so I would backup any existing configuration (server blocks) before using mine, that way you can revert back if needed.

    If you run in to any errors, you'd want to check the error log, which is generally located at:


    To get the last few lines, you could use:

    tail -20 /var/log/nginx/error.log

    You can replace 20 with any number to increase or decrease the output.

Here is my current configuration without SSL

include forge-conf/*;

server {
    listen 80;
    listen [::]:80;
    root /home/forge/;

    # ssl_certificate;
    # ssl_certificate_key;

    #ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    #ssl_prefer_server_ciphers on;
    #ssl_dhparam /etc/nginx/dhparams.pem;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    index index.html index.htm index.php;

    charset utf-8;

    include forge-conf/*;

   location / {
       try_files $uri $uri/ /index.php?$query_string;

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    access_log off;
    error_log  /var/log/nginx/ error;

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        fastcgi_intercept_errors off;
        fastcgi_buffer_size 16k;
        fastcgi_buffers 4 16k;
        fastcgi_connect_timeout 300;
        fastcgi_send_timeout 300;
        fastcgi_read_timeout 300;

location ~ .(mp3)$ {
    valid_referers blocked;
    if ($invalid_referer) {
        return 403;

## Deny certain Referers (case insensitive)
    ## The ~* makes it case insensitive as opposed to just a ~
 if ($http_referer ~* (babes|click|diamond|forsale|girl|jewelry|love|nudit|organic|poker|porn|poweroversoftware|sex|teen|video|webcam|zippo))
    {  return 403;   }

location ~ /\.ht {
    deny all;


include forge-conf/*;

Have another answer? Share your knowledge.