Tutorial

How To Create an SSL Certificate on Nginx for Ubuntu 14.04

Published on May 10, 2014
How To Create an SSL Certificate on Nginx for Ubuntu 14.04

Introduction

TLS, or transport layer security, and its predecessor SSL, which stands for secure sockets layer, are web protocols used to wrap normal traffic in a protected, encrypted wrapper.

Using this technology, servers can send traffic safely between the server and the client without the concern that the messages will be intercepted and read by an outside party. The certificate system also assists users in verifying the identity of the sites that they are connecting with.

In this guide, we will show you how to set up a self-signed SSL certificate for use with an Nginx web server on an Ubuntu 14.04 server. A self-signed certificate will not validate the identity of your server for your users since it is not signed by one of their web browser’s trusted certificate authorities, but it will allow you to encrypt communications with your web clients.

Note: You may want to consider using Let’s Encrypt instead of a self-signed certificate. Let’s Encrypt is a new certificate authority that issues free SSL/TLS certificates that are trusted in most web browsers. Check out the tutorial to get started: How To Secure Nginx with Let’s Encrypt on Ubuntu 14.04

Prerequisites

To get started on this guide, you will need to set up some basic things on your server.

You should have a non-root user available who has sudo privileges. You can learn how to set up such a user account by following steps 1-4 in our initial server setup for Ubuntu 14.04.

After that, you’ll also need to have the Nginx web server installed. If you would like to install an entire LEMP (Linux, Nginx, MySQL, PHP) stack on your server, you can follow our guide on setting up LEMP on Ubuntu 14.04.

If you just want the Nginx web server, you can instead just type:

sudo apt-get update
sudo apt-get install nginx

Step One — Create the SSL Certificate

We can start off by creating a directory that will be used to hold all of our SSL information. We should create this under the Nginx configuration directory:

sudo mkdir /etc/nginx/ssl

Now that we have a location to place our files, we can create the SSL key and certificate files in one motion by typing:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt

You will be asked a series of questions. Before we go over that, let’s take a look at what is happening in the command we are issuing:

  • openssl: This is the basic command line tool for creating and managing OpenSSL certificates, keys, and other files.
  • req: This subcommand specifies that we want to use X.509 certificate signing request (CSR) management. The “X.509” is a public key infrastructure standard that SSL and TLS adheres to for its key and certificate management. We want to create a new X.509 cert, so we are using this subcommand.
  • -x509: This further modifies the previous subcommand by telling the utility that we want to make a self-signed certificate instead of generating a certificate signing request, as would normally happen.
  • -nodes: This tells OpenSSL to skip the option to secure our certificate with a passphrase. We need Nginx to be able to read the file, without user intervention, when the server starts up. A passphrase would prevent this from happening because we would have to enter it after every restart.
  • -days 365: This option sets the length of time that the certificate will be considered valid. We set it for one year here.
  • -newkey rsa:2048: This specifies that we want to generate a new certificate and a new key at the same time. We did not create the key that is required to sign the certificate in a previous step, so we need to create it along with the certificate. The rsa:2048 portion tells it to make an RSA key that is 2048 bits long.
  • -keyout: This line tells OpenSSL where to place the generated private key file that we are creating.
  • -out: This tells OpenSSL where to place the certificate that we are creating.

As we stated above, these options will create both a key file and a certificate. We will be asked a few questions about our server in order to embed the information correctly in the certificate.

Fill out the prompts appropriately. The most important line is the one that requests the Common Name (e.g. server FQDN or YOUR name). You need to enter the domain name that you want to be associated with your server. You can enter the public IP address instead if you do not have a domain name.

The entirety of the prompts will look something like this:

<pre> Country Name (2 letter code) [AU]:<span class=“highlight”>US</span> State or Province Name (full name) [Some-State]:<span class=“highlight”>New York</span> Locality Name (eg, city) []:<span class=“highlight”>New York City</span> Organization Name (eg, company) [Internet Widgits Pty Ltd]:<span class=“highlight”>Bouncy Castles, Inc.</span> Organizational Unit Name (eg, section) []:<span class=“highlight”>Ministry of Water Slides</span> Common Name (e.g. server FQDN or YOUR name) []:<span class=“highlight”>your_domain.com</span> Email Address []:<span class=“highlight”>admin@your_domain.com</span> </pre>

Both of the files you created will be placed in the /etc/nginx/ssl directory.

Step Two — Configure Nginx to Use SSL

We have created our key and certificate files under the Nginx configuration directory. Now we just need to modify our Nginx configuration to take advantage of these by adjusting our server block files. You can learn more about Nginx server blocks in this article.

Nginx versions 0.7.14 and above (Ubuntu 14.04 ships with version 1.4.6) can enable SSL within the same server block as regular HTTP traffic. This allows us to configure access to the same site in a much more succinct manner.

Your server block may look something like this:

<pre> server { listen 80 default_server; listen [::]:80 default_server ipv6only=on;

    root /usr/share/nginx/html;
    index index.html index.htm;

    server_name your_domain.com;

    location / {
            try_files $uri $uri/ =404;
    }

} </pre>

The only thing we would need to do to get SSL working on this same server block, while still allowing regular HTTP connections, is add a these lines:

<pre> server { listen 80 default_server; listen [::]:80 default_server ipv6only=on;

    <span class="highlight">listen 443 ssl;</span>

    root /usr/share/nginx/html;
    index index.html index.htm;

    server_name <span class="highlight">your_domain.com</span>;
    <span class="highlight">ssl_certificate /etc/nginx/ssl/nginx.crt;</span>
    <span class="highlight">ssl_certificate_key /etc/nginx/ssl/nginx.key;</span>

    location / {
            try_files $uri $uri/ =404;
    }

} </pre>

When you are finished, save and close the file.

Now, all you have to do is restart Nginx to use your new settings:

sudo service nginx restart

This should reload your site configuration, now allowing it to respond to both HTTP and HTTPS (SSL) requests.

Step Three — Test your Setup

Your site should now have SSL functionality, but we should test it to make sure.

First, let’s test to make sure we can still access the site with using normal HTTP. In your web browser, go to your server’s domain name or IP address:

<pre> <span class=“highlight”>http</span>://<span class=“highlight”>server_domain_or_IP</span> </pre>

You should see your normal website. In my example, I’m just serving the default Nginx page:

Nginx non-SSL

If you get this page, then your server is still handling HTTP requests correctly.

Now, we can check whether our server can use SSL to communicate. Do this by specifying the https protocol instead of the http protocol.

<pre> <span class=“highlight”>https</span>://<span class=“highlight”>server_domain_or_IP</span> </pre>

You will likely get a warning in your web browser that looks something like this:

Nginx SSL warning

This is expected. It is telling you that it cannot verify the identity of the server you are trying to connect to because it isn’t signed by a certificate authority that the browser has been configured to trust. Since we created a self-signed certificate, this makes perfect sense.

Click on “Proceed anyway”, “Continue”, or whatever similar option is available. You should see your site again:

Nginx SSL

Your browser may show the “https” crossed out in the address bar or a broken or crossed out “lock” icon. If you click on the lock icon, you can see some more information about the connection:

Nginx SSL information

As you can see, the issue is only that the browser cannot verify the identity of the server because it isn’t signed by a certificate authority that it is configured to trust. The middle section shows that the connection is encrypted, however, so we have achieved that goal.

Conclusion

You have configured your Nginx server to handle both HTTP and SSL requests. This will help you communicate with clients securely and avoid outside parties from being able to read your traffic.

If you are planning on using SSL for a public website, you should probably purchase an SSL certificate from a trusted certificate authority to prevent the scary warnings from being shown to each of your visitors.

<div class=“author”>By Justin Ellingwood</div>

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
10 Comments


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Andrew SB
DigitalOcean Employee
DigitalOcean Employee badge
July 18, 2014

@yuri:

Assuming you’ve already generated a key to create the CSR which you submitted to Comodo PositiveSSL, you’ll need to create a certificate bundle to use with Nginx. You should have received three file via email. Move them to the server and combine them with:

cat domain_com.crt PositiveSSLCA2.crt AddTrustExternalCARoot.crt > domain.com.pem

Then, the rest of your Nginx configuration will look like the article above. Just remember to use the file you just generated and the key you created when making the CSR.

        ssl_certificate /path/to/your/domain.com.pem;
        ssl_certificate_key /path/to/your.key;

Nice tutorial, it helped! Might worth mentioning that if you have ufw installed you need to allow 443.

Thank you so much for this tutorial!

I followed your instructions to finish that other tutorial explaining how to get an actual SSL certificate/key via StartSSL.

Now my website has a beautiful green URL :)

Hi, do we also need to include this in the server block section?

ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
ssl_prefer_server_ciphers on;

The tutorial comment for Ubuntu 12.04 version says this can prevent Beast Attack on SSL. Or does Ubuntu 14.04 already take care of that by default thus no need to include those lines in?

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
May 29, 2014

@Adriano: You can remove the passphrase from a key by running the following command: <pre>openssl rsa -in key -out key</pre> Make sure you take a backup first in case anything goes wrong (a <code>cp key key.bak</code> should suffice). You don’t need to reissue the certificate or resend it to the CA. Let me know how it goes! :)

Hi everyone! I’m tried all the steps with 1 difference. I have a sub-domain like akshit.xxx.com which is pointed to my ip. Then i created a server block for akshit.xxx.com then added these lines in block name (akshit.xxx.com):

server {
        listen 80;# removed default_server as my default conf has that
        listen [::]:80;

        listen 443 ssl;

        root /var/www/akshit/html;
        index index.html;

        server_name akshit.www.com;
        ssl_certificate /etc/nginx/ssl/nginx.crt;
        ssl_certificate_key /etc/nginx/ssl/nginx.key;

        location / {
                try_files $uri $uri/ =404;
        }
}

and enabled https in ufw. Now it keeps loading for a long time and says “The site can’t be reached”. When I try in incognito, it works without ssl. Please help with this!

Thanks for tutorial. But nginx configuration didn’t worked until I added ssl on; . You may consider to add it.

Thanks a lot. Great tutorial with clarity and simplest explanation. Worked well.

It works but how do I make it https by defualt?

This comment has been deleted

    Try DigitalOcean for free

    Click below to sign up and get $200 of credit to try our products over 60 days!

    Sign up

    Join the Tech Talk
    Success! Thank you! Please check your email for further details.

    Please complete your information!

    Become a contributor for community

    Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

    DigitalOcean Documentation

    Full documentation for every DigitalOcean product.

    Resources for startups and SMBs

    The Wave has everything you need to know about building a business, from raising funding to marketing your product.

    Get our newsletter

    Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

    New accounts only. By submitting your email you agree to our Privacy Policy

    The developer cloud

    Scale up as you grow — whether you're running one virtual machine or ten thousand.

    Get started for free

    Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

    *This promotional offer applies to new accounts only.