Exploring Jekyll for Static Sites


I have several years of experience hosting multiple Wordpress websites on a personal LAMP stack server I administer from my home (I recently migrated this workload to GCP, see blog post Migrating Wordpress to GCP). For readers unfamiliar with Wordpress, it is a great option for hosting dynamic websites for a business, a personal blog, or an enterprise content management system. Wordpress is an open source platform and widely popular for it’s quick and easy setup, easy administration, and abundance of functional options (plug-ins). Figures posted by W3Tech show Wordpress powering over 35% of all websites on the internet.

Static vs. Dynamic Website Architecture Static vs. Dynamic Website Architecture

The figure above from ApacheBooster visualizes the difference between a static and dynamic website architecture, Scheme A shows how web calls are served back to the requestor directly whereas Scheme B shows the additional layers/dependencies when a web call is made to a dynamic site. Each of those layers does result in additional latency, which is the time it takes before you receive a response back from the server.

So why Jekyll, I was looking to move some of the content I host using Wordpress to a more lightweight platform that is responsive and easy to install and post updates. Additionally, unlike Wordpress, there is no need to update themes, plug-ins, and databases - so ideally less risk of your site getting compromised, and if it does, it’s easy enough to regenerate your blog and/or site and redeploy the build files to your hosting server. It’s pretty simple.

I’m not advocating for static sites over dynamic sites or vise versa, both have use cases where one would be more desirable over the other. For the remainder of this article I will walk you through how to setup a virtual hosting server where you can host one or many sites concurrently.

Server Specs: small box I have tucked away in my closet

  • cpu: Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz (8 cores)
  • memory: 15GiB
  • storage: 2TB
  • CentOS 7
  • Apache Web Server

Step 1: you will need to install the Fedora EPEL repository to get started

~]$ sudo yum update -y
~]$ sudo yum install epel-release -y

Step 2: next you’ll need to install Ruby

~]$ sudo yum install ruby -y

Step 3: now you will need to install Jekyll using gem. You do not need to run this with sudo privileges

~]$ gem install jekyll 

Step 4: now check you installed Ruby and Jekyll

~]$ ruby -v
~]$ jekyll -v

Step 5: use gem to install the Ruby Bundler

~]$ gem install bundler

Before we generate a Jekyll package we first need to discuss where it should be created. Do you install it locally on your Linux machine and/or MacBook Pro, or how about a remote server in your house or in the cloud? Honestly, either is fine, but there are implications for how to preview the site. The less confusing strategy is to install Jekyll locally on your machine so you can view the site using http://localhost:4000/ and/or http://127.0.0.1:4000/. Jekyll has a serve feature that will instantiate an ephemeral version of the site using port 4000.

If you install the Jekyll source code on a remote server, which is not running a graphical user interface (GUI), then you will have to use the --host flag. The flag will allow you to view your site using a class 3 IP address (beginning with 192.168.6.73). Simply type-in the IP address followed by the port number in your browser. Please note I installed the source code on a personal remote server.

Okay, let’s keep going.

Step 6: create a folder for your site and install Jekyll

~]$ mkdir mysite ; cd mysite
mysite]$ jekyll new myblog

You will need to check your firewall setting if you’re running on a remote server - Jekyll will render the ephemeral site on port 4000. You can use the following commands to check and update your local firewall, if you’re running CentOS.

~]$ sudo systemctl status firewalld ##determine if the firewall is enabled
~]$ sudo firewall-cmd --list-ports ##list ports 
Output: 10000/tcp
~]$ sudo firewall-cmd --permanent --add-port=4000/tcp ##open port 4000
Output: 10000/tcp 4000/tcp

For quick testing, you can always turn off the local firewall all together.

~]$ sudo systemctl stop firewalld 

Step 7: change directories and view site using IP address of host server (I’m using an internal IP address)

~]$ cd myblog
myblog]$ jekyll server --host 192.168.6.73

Picture of new Jekyll install New Jekyll Homesreen

Step 8: now I need to push the build to the apache web server directory. If you are planning to run multiple sites you will want to create subdirectories in /var/www/html. For example, /var/www/html/site1, /var/www/html/site2, etc… If running a single web site, then deploy the package to /var/www/html.

myblog]$ jekyll build --destination /var/www/html/site1

Step 9: create apache configuration file

~]$ sudo su - ##change to root user 
 # vi /etc/httpd/conf.d/site1.conf
-----
paste in the following:
#NameVirtualHost *:80
<Directory /var/www/html/site1>
    AllowOverride All
    Require all granted
</Directory>

<VirtualHost *:80>
    DocumentRoot "/var/www/html/site1"
    ServerName http://site1.com
    ServerAlias site1.com
    ServerAdmin root@site1.com
    ErrorLog "/var/log/httpd/error_log_site1.com"
    CustomLog "/var/log/httpd/access_log_site1.com" combined
RewriteEngine on
RewriteCond %{SERVER_NAME} =www.site1.com [OR]
RewriteCond %{SERVER_NAME} =site1.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

 # exit
~]$ sudo systemctl reload httpd ##restart apache server to load update 

Before you proceed to the next step you will need to ensure port forwarding is enabled on your router, if you’re using a home-based server.

Step 10: update DNS setting with IP address

Access your domain registration dashboard and update the “A Record”(e.g., GoDaddy, Bluehost and HostGator). Name: yourdomain.com Value: ip-address

Updates can take anywhere from 1 minute to 20 minutes to propagate domain controllers. You can check the record of the site with the nslookup utility.

gcp]$ nslookup sitename.com
##or you can watch for the update
~]$ watch -d "nslookup sitename.com"
##wait for the DNS to update before updating your ssl/tls cert

Step 11: apply TLS encryption using LetsEncrypt

sudo certbot --apache
...
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator apache, Installer apache
Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org
Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: site1.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 1

Cert not yet due for renewal

You have an existing certificate that has exactly the same domains or certificate name you requested and isn't close to expiry.
(ref: /etc/letsencrypt/renewal/sitename.com.conf)

What would you like to do?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Attempt to reinstall this existing certificate
2: Renew & replace the cert (limit ~5 per 7 days)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 1

Keeping the existing certificate
Deploying Certificate to VirtualHost /etc/httpd/conf.d/site1-le-ssl.conf

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2

Enhancement redirect was already set.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled
https://site1.com

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=sitename.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/site1.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/site1/privkey.pem
Your cert will expire on 2019-10-27. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the "certonly" option. To non-interactively renew *all* of
your certificates, run "certbot renew"
- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le

Congrats, now your site is running over TLS encryption!

Now you should initiate git in the new root directory to ensure you have adequate version control for your source code. You’ll want to log into your github account and create a public or private repo. Ensure your ssh key is added so you can push your code from the terminal.

myblog]$ git config --global user.name "name"  
myblog]$ git config --global user.email "email address"
myblog]$ git init
myblog]$ git add .
myblog]$ git commit -m "message"
myblog]$ git remote add origin git@github.com:"username"/"site1"
myblog]$ git push -u origin master

Now toggle back to your github account, you should see the source code for your site.

That should do it, I hope you found this post informative and helpful to you on your journey to host your own website, whether using Wordpress or Jekyll.


References: