How to install ‘Let’s Encrypt’ Free SSL on ubuntu (14.04)

Heyy guys! Today, I am going to tell you about how to install free ssl on your server. As we all know, most of the popular websites on the internet are running on SSL and tell their users to trust websites that have SSL certificate. In this post, I am not going to tell you about what is SSL or why we need SSL as there is already enough information on other websites about this. Due to the complexity and cost of installing a SSL certificate, Big companies like Google, Mozilla, Akamai etc have started Lets Encrypt Project to enable users to install SSL certificates on their server as quickly as possible without any cost.

In this post, I will show step-by-step process to install Lets Encrypt’s Free SSL certificate and how to automate renewal of that certificate as it is valid for 3 months only. (Don’t worry, renewal is free too!)

Assumptions

  • Ubuntu server (as of now I am using 14.04)
  • Website domain running on Nginx server installed
    If it is not installed, run this command:

    sudo apt-get install nginx

Setting up environment

  1. Install gitBut first of all, update your server’s package manager using command:

    sudo apt-get update

    Then, install git:

    sudo apt-get install git

  2. As Lets Encrypt project is hosted on github, using git, we can easily clone project on our server and install it. Lets clone the project repo in the /opt directory:

    sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt

  3. Lets Encrypt provides variety of plugins to obtain SSL certificate. These plugins are only used to obtain certificate but you have to manually configure and install on web server. There’s also third party packages like certbot which automatically obtains and deploy SSL certificate on your server.

    How To Use the Webroot Plugin

    The Webroot plugin works by placing a special file in the /.well-known directory within your document root, which can be opened (through your web server) by the Let’s Encrypt service for validation. Depending on your configuration, you may need to explicitly allow access to the /.well-known directory.

  4. I have assumed that you have nginx installed and configured for your domain. Add this location block to your server configuration file (mine is location at /etc/nginx/sites-available/default):
    location ~ /.well-known {
                    allow all;
            }

    It will look like this:

    server {
     listen 80 default_server;
     listen [::]:80 default_server ipv6only=on;
    
    root /var/www/html;
     index index.html index.htm index.php;
    
    # Make site accessible from http://localhost/
     server_name arunsharma.me;
    
    location ~ /.well-known {
                    allow all;
            }
    
    location / {
     # First attempt to serve request as file, then
     # as directory, then fall back to displaying a 404.
     try_files $uri $uri/ =404;
     # Uncomment to enable naxsi on this location
     # include /etc/nginx/naxsi.rules
     }
    
    # Only for nginx-naxsi used with nginx-naxsi-ui : process denied requests
     #location /RequestDenied {
     # proxy_pass http://127.0.0.1:8080;
     #}
    
    #error_page 404 /404.html;
    
    # redirect server error pages to the static page /50x.html
     #
     #error_page 500 502 503 504 /50x.html;
     #location = /50x.html {
     # root /usr/share/nginx/html;
     #}
    
    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
     #
     location ~ \.php$ {
     # fastcgi_split_path_info ^(.+\.php)(/.+)$;
     # # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
     #
     # # With php5-cgi alone:
     # fastcgi_pass 127.0.0.1:9000;
     # # With php5-fpm:
     fastcgi_pass unix:/var/run/php5-fpm.sock;
     fastcgi_index index.php;
     fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
     include fastcgi_params;
     }
    
    # deny access to .htaccess files, if Apache's document root
     # concurs with nginx's one
     #
     #location ~ /\.ht {
     # deny all;
     #}
    }
  5. Save and exit. Now, check if the configuration is correct:

    sudo nginx -t

    If OK, then restart your nginx server

    sudo service nginx restart

    Getting SSL Certificate

  6. Now that we know our webroot-path, we can use the Webroot plugin to request an SSL certificate with these commands. Here, we are also specifying our domain names with the -d option. If you want a single cert to work with multiple domain names (e.g. example.com and www.example.com), be sure to include all of them.
    Go to directory where you have cloned the project:

    cd /opt/letsencrypt/

    And run this command:

    ./letsencrypt-auto certonly -a webroot –webroot-path=<YOUR WEBROOT PATH> -d <YOUR DOMAIN NAME>

    e.g.

    ./letsencrypt-auto certonly -a webroot –webroot-path=/var/www/html -d arunsharma.me

  7. During installation, It will asks for certain information like your email. Just enter them and accept their Terms and conditions (which we have never read in our lifetime :D)
  8. If everything goes fine, you will have this output:
    30f7d94bed2e45b3b067456c3974333d copy
  9. As you see, our newly generated certificate will expire on 15 Oct 2016 that is 3 months from now and is located at  /etc/letsencrypt/live/arunsharma.me/fullchain.pem
  10. After obtaining the cert, you will have the following PEM-encoded files which are located in /etc/letsencrypt/live/<YOUR-DOMAIN_NAME> ( mine is located in /etc/letsencrypt/live/arunsharma.me/):
    • cert.pem: Your domain’s certificate
    • chain.pem: The Let’s Encrypt chain certificate
    • fullchain.pem: cert.pem and chain.pem combined
    • privkey.pem: Your certificate’s private key

      Generate Strong Diffie-Hellman Group (Optional)

      If you want to increase security, it is recommended to generate a strong DH group.

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

      This will take a few minutes but once done, you will get DH group at /etc/ssl/certs/dhparam.pem

Configuring and Installing SSL certificate

  1. We have two options to two this:
    1. If we want to redirect all HTTP traffic to HTTPS
    2. If we want to have both HTTP and HTTPS traffic
      I am going to select second option as I want to have separate configuration for HTTPS but If you want to have first one, take a look at this great article by DigitalOcean.
  2. I am going to create two files: one will contain location of our certificate and private key and other will contain nginx configuration for SSL. Then, I will merge this files into our nginx server configuration.
  3. Create a directory which contains ssl configuration:

    sudo mkdir /etc/nginx/sslconf

  4. Create a file in this directory:

    sudo nano /etc/nginx/sslconf/arunsharma.me.conf

  5. Add this lines to the files:
    ssl_certificate /etc/letsencrypt/live/arunsharma.me/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/arunsharma.me/privkey.pem;
    

    Note: Remember to replace path with your certificate path.

  6. Save and exit(ctrl+O to save and ctrl+x to exit). Now, create another file that will contain SSL configuration for nginx server:

    sudo nano /etc/nginx/sslconf/arunsharma.me_sslparams.conf

    and copy paste this configuration in this file:

    
    # from https://cipherli.st/
    # and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
    
    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:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
            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;
    

    Note: Remove dhparam line if you have not configured it.

  7. Now, Lets test our nginx configuration again:

    sudo nginx -t

    If the test is successful, then restart the nginx server

    sudo service nginx restart

  8. And its done. You can test your website by going to HTTPS version of your website e.g. https://arunsharma.me/

    Auto-Renew your SSL certificate

    Lets Encrypt’s SSL certificate will expire in 3 months but you can generate another certificate as many times as you want as it is free. You can renew your certificate using this command:

    /opt/letsencrypt/letsencrypt-auto renew

    If your domain is not already expired, it will show this, other It will update the certificate.

  9. To automate this process, we need to create a cron job then will run every week to make sure our SSL certificate will never expire. Run this command to create a cron job:

    sudo crontab -e

    And add this to the file:

    30 2 * * 1 /opt/letsencrypt/letsencrypt-auto renew >> /var/log/le-renew.log
    35 2 * * 1 sudo service nginx reload

    Customization

    Typically, you should follow the above process. But what I have done is, I have created a small shell script which will run this command and sends notification to my slack channel. If you are familiar with custom slack integration, use this script:

    /opt/letsencrypt/letsencrypt-auto renew &gt;&gt; /var/log/le-renew.log
    curl -X POST --data-urlencode 'payload={"channel": "#notifications", "username": "DomainSSLBOT", "text": "'"`cat /var/log/le-renew.log`"'", "icon_emoji": ":ghost:"}' https://hooks.slack.com/services/&lt;YOUR SLACK INCOMING WEBHOOK URL&gt;
    

    And then, add this script to the cron job:

    30 2 * * 1 /home/ubuntu/domain.sh
    35 2 * * 1 /etc/init.d/nginx reload
    

    Note: If you are wondering HTTPS is not installed on this blog domain, then how the hell I wrote this tutorial. Actually, I have installed on my other domain and I will install on this domain soon.

    We should all install SSL on our websites as it keeps our users safe and Now its is simple, free and easy to install. Go ahead, install now. 🙂