Building an Encrypted Website or Blog

Posted on 17 Nov 2017 in Full-Stack Web Development • 6 min read


In my last article, I wrote about how we can build a professional personal site without monthly fees. This time I would like to share how we can build our own secure website or blog. secure means here that our website uses the secure protocol (HTTPS) instead of HTTP. In short, HTTPS is HTTP over SSL with a certificate authentication. Our own website means that we have control of our data. As we know from the late leaks, the internet is fully monitored by several organizations which we don't know. Thus, HTTPS is very important to be utilized if we want to build a secure website.

Overview

An overview of the preparation is described as following:

  1. A Linux Virtual Private Server (VPS): I use Digital Ocean Ubuntu VPS. You can use your own server if you have or use another Linux VPS provider. Note, for a 100% ownership of your data and privacy, you have to use your own server. However, the maintenance of a private server can be overwhelming.
  2. An account at a domain name provider: I have an account at Namecheap*, and I can recommend this domain provider.
  3. A web server software: I installed 'Nginx' for my web server software in my Ubuntu VPS. See the Nginx's documentation to learn more.
  4. A certbot client: Check the installation on the certbot website.
  5. A CMS software: You can use your favorite CMS. For my PHP-based website, I use Grav, and for a Python-based website, I use Pelican or Django.
  6. An analytic software like Google Analytics or Piwik. In this article, I'll explain how to use Piwik for my analytic software because I want to own my data analytic myself. I don't want to share it with Google or other third parties who I don't know.

Linux VPS

Finding a VPS Provider

Choosing a good VPS can be annoying if you always try to compare and optimize the monthly fee and the hardware what you get, plus the privacy aspect. To avoid wasting time, make clear and write down your priority based on your purpose for your VPS. I choose Digital Ocean because of the possibility to deploy the VPS in a different country. If you know another better provider for this case, you can suggest me.

VPS Initial configuration

  1. Do this tutorial for initial setup from Digital Ocean.
  2. Learn to set up and use Secure Shell (SSH) as an alternative to FileZilla.

Filesystem Configuration

Before I install or extract applications (e.g. CMS and Piwik), I need to have a fixed structure in my VPS file system. Since I will not have a daily work in my VPS, it is very important to document this so that I don't forget where I've copied a file or a software, since I don't have a file management with graphical user interface.

  • /var/www/ is the place for installing or extracting my web application, such as CMS and Piwik analytics.
  • /etc/nginx/ is the place for the nginx configuration files
    • /etc/nginx/sites-available contains all the configuration files that I created for test and for production. Each file represents a configuration of a web application.
    • /etc/nginx/sites-enable by linking a configuration file from /etc/nginx/sites-available we can activate the web application. See Nginx section for more details.
  • /var/log/ is the folder for debugging the Nginx and web application errors
  • /etc/letsencrypt/live is the folder where Let's Encrypt SSL certificate for the HTTPS can be found.

Domain Name

For your website, you need a domain name for your business or blog site. You need to register with a domain name registrar/provider, log in, and buy your domain. If you are log in in the domain provider portal, you can manage your domain to be linked to the IP address of your Linux VPS. For this article, I use example.com as an example of my tutorial. Furthermore, you can create a subdomain such as stats.example.com for your login page of your Piwik analytic page. Below is an example how to set up the DNS for your main page and the stats subdomain:

DNS setting

Grav CMS

  1. In your SSH server, navigate to the home folder by typing cd, and download the Grav CMS core and its admin plugin, for example for the version 1.3.8:

    wget https://getgrav.org/download/core/grav-admin/1.3.8 -O grav-admin138.zip
    unzip grav-admin138.zip
    
  2. Create a new folder for your website and copy the content of the grav-admin folder

    sudo mkdir /var/www/example
    cp -r ~/grav-admin/* /var/www/example
    

Nginx

In order to run the installation of the CMS (or Piwik), we need to configure the Nginx web server. Not like a desktop installation, we need to install the CMS through the browser. Therefore, we need to configure the web server on our VPS to handle the web request of our domain.

For the Nginx web server installation and setup, we can read this tutorial.

Activation a Web Application

  1. Create and define a configuration file for a web application

    server {
        #listen 80; due to HTTPS we forward the port 80
        index index.html index.php;
    
        ## Begin - Server Info
        root /home/USER/www/html;
        server_name localhost;
        ## End - Server Info
    
        ## Begin - Index
        location / {
            try_files $uri $uri/ /index.php?_url=$uri&$query_string;
        }
        ## End - Index
    
        ## Begin - Security
        # deny all direct access for these folders
        location ~* /(\.git|cache|bin|logs|backup|tests)/.*$ { return 403; }
        # deny running scripts inside core system folders
        location ~* /(system|vendor)/.*\.(txt|xml|md|html|yaml|yml|php|pl|py|cgi|twig|sh|bat)$ { return 403; }
        # deny running scripts inside user folder
        location ~* /user/.*\.(txt|md|yaml|yml|php|pl|py|cgi|twig|sh|bat)$ { return 403; }
        # deny access to specific files in the root folder
        location ~ /(LICENSE\.txt|composer\.lock|composer\.json|nginx\.conf|web\.config|htaccess\.txt|\.htaccess) { return 403; }
        ## End - Security
    
        ## Begin - PHP
        location ~ \.php$ {
            # Choose either a socket or TCP/IP address
            fastcgi_pass unix:/var/run/php5-fpm.sock;
    
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
        }
        ## End - PHP
    }
    
  2. Activate a web application by executing this command:

    sudo ln -s /etc/nginx/sites-available/example.conf /etc/nginx/sites-enable/example.conf
    sudo systemctl restart nginx
    

If the configuration is correct, we can see the Grav installation page on our browser after typing example.com. In case of misconfiguration, we have to look the Nginx logs in /var/log/nginx/.

Easy Encryption Setup using certbot

Certbot is part of EFF’s effort to encrypt the entire Internet... Certbot is an easy-to-use client that fetches a certificate from Let’s Encrypt—an open certificate authority launched by the EFF, Mozilla, and others—and deploys it to a web server. - Certbot Documentation.

So, using certbot we can obtain a free certificate from Let's Encrypt for our HTTPS communication. Check the installation for your system in the certbot website. For an Ubuntu 16.04 server, we can run these commands to install the certbot:

$ sudo apt-get update
$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt-get update
$ sudo apt-get install python-certbot-nginx

After the installation, run this command to automatically get the certificates for all of your enabled Nginx configuration. You can run this command after you create the Nginx configuration file for the Piwik site below

certbot --nginx

Checking the expiration date of certificates can be done by running this command:

certbot certificates

Piwik Self Hosting

We can follow below instructions to set up the Piwik site:

  1. Login to the SSH of your server using

    ssh <username>@<VPS IP address> -p <port_number>
    
  2. Download the Piwik software package to your VPS by running:

    wget https://builds.piwik.org/piwik.zip
    
  3. extract it to /var/www/piwik:

    sudo mkdir /var/www/piwik
    sudo unzip piwik.zip && mv piwik /var/www/piwik
    
  4. Create a Nginx configuration file for Piwik. Here we remove the line with listen 80. As the replacement, we define the configuration to only listen the port 443 for the SSL communication.

    server {
       # listen 80;
       # listen [::]:80;
        listen 443 ssl;
        root /var/www/piwik;
    
        server_name stats.example.com;
    
        access_log /var/log/nginx/stats_example_access.log;
        error_log /var/log/nginx/stats_example_error.log; 
        ssl_certificate /etc/letsencrypt/live/stats.example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/stats.example.com/privkey.pem;
    
        # use the strong Diffie-Hellman from /etc/ssl/certs/dhparam.pem
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        add_header Strict-Transport-Security max-age=15768000;
    
        location / {
           index  index.php;
        }
        location /config.ini.php {
           root /etc/webapps/nginx;
           index config.ini.php;
        }
        location ~* \.php$ {
           try_files $uri =404;
           include fastcgi_params;
           fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
           fastcgi_index index.php;
           fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
           fastcgi_intercept_errors on;
           fastcgi_split_path_info ^(.+\.php)(.*)$;
           fastcgi_hide_header X-Powered-By;
           fastcgi_param HTTPS $https if_not_empty;  # additional config for SSL
        }
        location ~ /.well-known {
           allow all;
        }
    }
    
    server {
        listen 80;
        server_name stats.example.com;
        return 301 https://stats.example.com$request_uri;
    }
    
  5. Run

    $ certbot --nginx
    
  6. Activate the Piwik page for login and restart the Nginx web server

    $ sudo ln -s /etc/nginx/sites-available/stats.example.conf /etc/nginx/sites-enabled/stats.example.conf
    $ sudo sudo systemctl restart nginx
    

Conclusion


As we can read above, creating our own free encrypted website may seem overwhelming for the first time. However, it's worth it. Thanks to Let's Encrypt to allow us to get a free SSL certificate. Things that cost us money are the domain name and the monthly VPS rent, which most people do. If you still have difficulties, you can learn more from the source in the overview section, post a comment or hire me for few hours to support your website. Good luck!

* affiliate links