Migrating from http to https
using lets encrypt, certbot and configuring Nginx

Lets Encrypt

I wanted to migrate to https for long. Back then, we need to shell out extra bucks for SSL certificate.
Then, I heard about Letsencrypt.

First Attempt

Earlier sakthipriyan.com was running on a CentOS 6. I tried to install SSL certificates from Letsencrypt using the certbot. I had faced few issues. Then I got carried away with other things and didn't try to set it up.

Taste of Success

I had another domain name which I hadn't used for anything. So, I tried setting it up with SSL in CentOS 7. It was like breeze. So simple and it worked out as it should be.

Migration

I had to go through the following steps to set it up like old school way.

New Instance

I had created a new CentOS 7 instance in Vultr Cloud.
From price point it is very competitive compared more prominant cloud providers.

Install Nginx, Start Nginx and Set up auto Start

yum update
yum -y install epel-release 
yum -y install nginx
service nginx start
service nginx status
systemctl enable nginx

Open up firewall

firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --zone=public --add-port=443/tcp --permanent
firewall-cmd --reload

Setting up website on the Nginx

mkdir -p /var/www/sakthipriyan.com
nano /etc/nginx/conf.d/sakthipriyan.com.conf
service nginx reload

Contents of the initial /etc/nginx/conf.d/sakthipriyan.com.conf

#
# HTTPS server configuration
#

server {
    listen       80;
    server_name  sakthipriyan.com;

    location / {
        root   /var/www/sakthipriyan.com/;
        index  index.html index.htm;
    }
}

server {
    listen         80;
    server_name    www.sakthipriyan.com;
    return         301 http://sakthipriyan.com$request_uri;
}

I had set up two server_names.

  1. Actual website will be served at sakthipriyan.com
  2. www.sakthipriyan.com will be redirected to sakthipriyan.com

Installing PIP, Jinja2 and Markdown

Required for webgen to generate the website from markdown src files.

yum -y install python-pip
pip install --upgrade pip
pip install jinja2
pip install markdown

Cloning webgen and sakthipriyan.com

yum -y install git 
git clone https://github.com/sakthipriyan/sakthipriyan.com.git
git clone https://github.com/sakthipriyan/webgen.git

Generate website and serve via Nginx

cd webgen
python webgen.py ../sakthipriyan.com/conf/prod.json
cp -fr ../sakthipriyan.com/dist/* /var/www/sakthipriyan.com/

Changing DNS records

I had to edit DNS A Records to point to new instance's IP address for both sakthipriyan.com and www.sakthipriyan.com

Installing certbot and installing certificates in Nginx

yum -y install yum-utils
yum-config-manager --enable rhui-REGION-rhel-server-extras rhui-REGION-rhel-server-optional
yum install certbot
yum install python2-certbot-nginx
certbot --nginx

If I remember correctly, I had used default options and directly I had updated the Website Nginx Config using the above certbot command.

Updated Nginx Config

Nginx config after using certbot --nginx

cat /etc/nginx/conf.d/sakthipriyan.com.conf
#
# HTTPS server configuration
#

server {
    server_name  sakthipriyan.com;

    location / {
        root   /var/www/sakthipriyan.com/;
        index  index.html index.htm;
    }

    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/sakthipriyan.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sakthipriyan.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}

server {
    server_name    www.sakthipriyan.com;
    return         301 https://sakthipriyan.com$request_uri;

    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/sakthipriyan.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sakthipriyan.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}

server {
    if ($host = sakthipriyan.com) {
        return 301 https://$host$request_uri;
    }
    listen       80;
    server_name  sakthipriyan.com;
    return 404;
}

server {
    if ($host = www.sakthipriyan.com) {
        return 301 https://$host$request_uri;
    }
    listen         80;
    server_name    www.sakthipriyan.com;
    return 404;
}

I had removed # managed by Certbot in the above config for simplicity.

In short, following redirections are set up in the above Nginx config

  1. https://sakthipriyan.com - Website served here, generated by webgen whenever I add new posts.
  2. https://www.sakthipriyan.com > https://sakthipriyan.com
  3. http://sakthipriyan.com > https://sakthipriyan.com
  4. http://www.sakthipriyan.com > https://sakthipriyan.com

Installing in Crontab

Two crontab items installed.

  1. For auto renewing the Certificate
  2. For auto updating the Website

crontab -l will list the installed crontabs. You have to use crontab -e to edit.

crontab -l
0 0,12 * * * python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew 
0,30 * * * * /root/sakthipriyan.com/update.sh

If you wonder, why we have random sleep here because this would prevent peak load to certbot services.

Thank You

Thank you Somin Mithraa for insisting on setting up https whenever I referenced my website. Finally I made it!

References

  1. https://www.godaddy.com/garage/how-to-install-and-configure-nginx-on-centos-7/
  2. https://certbot.eff.org/lets-encrypt/centosrhel7-nginx

Share

Great!! You read till this point, just go ahead and share this post to your followers, collegues and friends. Thanks!

About Author

Sakthi Priyan H
Passionate Programmer

  • Sakthi Priyan is passionate about building high quality reliable software.
  • He has vast experience in full stack web since 2006.
  • He primarily codes in Java, Scala and Python.
  • He currently works in backend API services and big data technologies.