Jenkins and Jekyll
For this blog, I’m using Jekyll, a Ruby based static site generator that uses markup pages to generate static html pages.
I wanted to automate the build and deployment process using Jenkins.
As i’m using Proxmox in my homelab, I can install various container images, one of which is Turnkey linux Jenkins which simplfies the setup.
After deploying the container and logging in as root and I can begin setting up the prerequisites for Jekyll.
Prerequsites for Jekyll
Install Ruby dev env and lftp
sudo apt-get install ruby-full build-essential lftp
Install Jekyll gem
gem install jekyll bundler
Local Development site
I want to have a local development site to view changes before pushing to the live site. For this I am using Jenkins pipelines to configure a local deployment on the develop branch. Turnkey linux Jenkins image includes apache2 which is proxying the Jenkins tomcat instance which I can use to host the development Jekyll blog.
Add a site configuration and create a directory to hold our development site that is writable by the jenkins user: drwxrwxr-x 2 jenkins www-data 2 Feb 13 21:21 jekyll-dev
/etc/apache2/sites-available/jekyll-dev.conf
Listen 8000
<VirtualHost *:8000>
DocumentRoot "/var/www/jekyll-dev"
</VirtualHost>
Then symlink it to the sites-enabled folder.
root@jenkins .../apache2/sites-enabled# ln -s ../sites-available/jekyll-dev.conf jekyll-dev.conf
Restart apache with apachectl restart
Double check apache is listening on the new port
root@jenkins .../apache2/sites-enabled# netstat -altp | grep 8000
tcp6 0 0 [::]:8000 [::]:* LISTEN 340/apache2
In Jenkins create new job that is a multibranch pipeline and configure it to use our GIT repo with our Jekyll blog, I’m selfhosting a gogs.io GIT server.
The branches must have a Jenkins pipeline file in the root of the repo. I’ll be using rsync to copy the generated static html files over to our web directory. For deployment to production i’ll be using lftp.
Jenkinsfile
pipeline {
agent any
stages {
stage('Install Bundles') {
steps {
echo 'Installing bundles..'
sh 'bundle install --path ~/.gem'
}
}
stage('Building site') {
steps {
echo 'Building..'
sh 'bundle exec jekyll build'
}
}
stage('Deploy') {
when {
branch 'develop'
}
steps {
echo 'Deploying to dev....'
sh 'rsync -avzh ./_site/ /var/www/jekyll-dev/
}
when {
branch 'master'
}
steps {
echo 'Deploying....'
}
}
}
}
Dev deployment
Assuming the above configuration goes correctly, upon triggering the Jenkins build it should build our site and rsync it to our local web directory
Prod deployment
To deploy to my webserver I need to FTP the site over, rsync won’t work for this. On my webhost I have created an FTP user to send the site files. I then need to add the FTP user credentials to Jenkins.
Finallly, within our Jenkinsfile, we need to reference the Jenkins credentials to FTP our site by the id we used when setting up the credentials: ftp_prod_blog. Using the withCredentials function, we can pass the username and password to the lftp command to mirror the local site to the remote webserver.
Within the Jenkins file in our step for master branch deployment add the following:
withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId:'ftp_prod_blog', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) {
sh 'lftp -e "mirror -R ./_site/ ~/" -u $USERNAME,$PASSWORD <FTPSITE>:21'
}
Hopefully as you are now reading this, the prod deployment was successful!
Now my deployment is automated via Jenkins I no longer need to manually generate the static html files and FTP them to my host.