Create and Host a Pelican Site on OpenBSD

Pelican is a static site generator which is a tool for translating templated web content into a functional website. As the name static would imply, there are limitations to what the site will do since all content is generated ahead of time, rather than on-the-fly as a user requests it. For basic websites, like this one, a static site generator is a perfect tool and allows you to stage and develop your website in one place but host it in another. We'll cover setting up Pelican as well as establishing the git hooks that will allow you to push your site to another machine for hosting (i.e. a production machine).

At the time of writing, Pelican is at version 3.7.1.

Installing software

All we need for this is Pelican and git. You can install them both like so

$ doas pkg_add pelican git

OpenBSD will install all necessary dependencies for you. It's also worth noting that if you're only hosting the site on an OpenBSD machine, but developing/generating it on another, you only need to install git.

Create a site template

Once Pelican is installed, create a new directory inside of which your content will live and move in to it.

$ mkdir jblog-pelican
$ cd jblog-pelican

Issue the pelican-quickstart command to perform the initial configuration.

$ pelican-quickstart
Welcome to pelican-quickstart v3.7.1.

This script will help you create a new Pelican-based website.

Please answer the following questions so this script can generate the files
needed by Pelican.

> Where do you want to create your new web site? [.]
> What will be the title of this web site? JBlog
> Who will be the author of this web site? Joe
> What will be the default language of this web site? [English]
> Do you want to specify a URL prefix? e.g.,   (Y/n) Y
> What is your URL prefix? (see above example; no trailing slash)
> Do you want to enable article pagination? (Y/n) Y
> How many articles per page do you want? [10] 5
> What is your time zone? [Europe/Paris] US/Eastern
> Do you want to generate a Fabfile/Makefile to automate generation and publishing? (Y/n) Y
> Do you want an auto-reload & simpleHTTP script to assist with theme and site development? (Y/n) Y
> Do you want to upload your website using FTP? (y/N) N
> Do you want to upload your website using SSH? (y/N) N
> Do you want to upload your website using Dropbox? (y/N) N
> Do you want to upload your website using S3? (y/N) N
> Do you want to upload your website using Rackspace Cloud Files? (y/N) N
> Do you want to upload your website using GitHub Pages? (y/N) N
Done. Your new project is available at /home/joe/gridc0-pelican

Write a test post

Create a file in the content/ directory named and add the following text to it:

Title: Hello World
Date: 2018-07-12
Tags: pelican
Summary: Pelican test post

Hello World

Here is some markdown content:

* A short
* list with
* a few items

Obviously, you can update the tags at the top, but this is a test post anyways.

Generate and publish your website

Now that you have content you can generate the website with the following command

$ pelican content/

And the website will be placed in the output/ directory. Assuming you have an existing site root location, such as /var/www/htdocs/jblog/, you will need to copy the contents of the output/ directory to it. This might be a good time to utilize the www user group who will own the document root directory. Add yourself to it like so, substituting in your username for joe, and log out/in.

$ doas user mod -G www joe
$ exit

Now make sure www is the owner of the document root:

$ doas chown -R www:www /var/www/htdocs/jblog/
$ chmod -R 775 /var/www/htdocs/jblog/

And finally, copy your generated content to it

$ cd jblog-pelican
$ cp -R output/* /var/www/htdocs/jblog

If your website is already running then you can browse to your URL and the content should be displayed, including the test post we just created.

Version control website materials

Now that your Pelican site is working, let's version control it and setup git to automatically push/pull repository contents so you can automatically publish your site from a different machine.

I prefer storing the pelican files in one repository and the actual site contents in another, so I use two git repos per website. This provides nice separation between development files and published content.


Site generation files

First, we'll put the pelican files in the pelican repo, so get rid of the non-development content and push the rest into your repo.

$ rm -rf ./output/ __pycache__/
$ git config --global "Joe Doe"
$ git config --global ""
$ git init
$ git add .
$ git commit -m "Initial commit"
$ git remote add origin
$ git push -u origin master

Website content

Next, we'll generate the site again and place the web content into a separate repository.

$ pelican content/
$ mkdir ../jblog-html
$ cp -R output/* ../jblog-html/
$ cd ../jblog-html/
$ git init
$ git add .
$ git commit -m "Initial commit"
$ git remote add origin
$ git push -u origin master

Website publishing through git

Now that your web materials are in git, we can setup a method by which you can push code to this server and have it automatically placed in the appropriate location. We'll create yet a third directory to act as the production area which we'll initialize as a bare git repo.

$ cd && mkdir jblog-prod && cd jblog-prod
$ git init --bare

If you list this directory, you'll see a few folders, one of which is hooks/. We'll move into this directory and create a file named post-receive.

$ cd hooks && touch post-receive

Place the following text into that file:


git --work-tree=/var/www/htdocs/ --git-dir=/home/joe/jblog-prod checkout -f

When code is pushed into this repo (i.e. received) this script will be executed afterward. It essentially says to pull the most recent version of the repo in jblog-prod and put it in /var/www/htdocs/ which is the root directory of our website. This means pushing code to this repo also pushes it to the website directory.

You must mark this file as executable which can be done like so

$ chmod +x post-receive

Now we need to tell the html repo about this production repo. With git this means we'll add a new remote repository with the following commands.

$ cd ../../jblog-html
$ git remote add prod ssh://

Almost there. Now delete the files that are currently "live" at /var/www/htdocs/ so we'll know whether this works or not. Ensure that www is the owner of the destination directory (i.e. the work tree) and push the contents of this repository to the "prod" remote as a way of updating your website.

$ chown -R www:www /var/www/htdocs/
$ git push prod

SSH setup

Depending on how you have SSH configured, you may need to use a specific key for this connection. If the private key is ~/.ssh/jblog_priv then you can place the following in ~/.ssh/config in order to use that key whenever you connect to

    IdentityFile ~/.ssh/jblog_priv

And make sure the private key file has its permissions set to 600.

$ chmod 600 ~/.ssh/jblog_priv

Pushing to prod

Now your infrastructure is setup so that you can push from any machine that could normally SSH to your web server. As long as you add the remote repository appropriately then you can push. If you're on a new machine then clone your repo and add the prod origin and you can work.

$ git clone
$ cd jblog-html
$ git remote add prod ssh://

Let's author a new file in the pelican repo as content/ with some more test content.

Title: More Tests
Date: 2018-07-13
Tags: git
Summary: Testing git

Git web publishing

A new post with fresh content about git

Then we'll generate the site, copy it to the html folder and push to the main repo and to prod.

$ pelican content/
$ \cp -R ./output/* ../jblog-html/
$ cd ../jblog-html
$ git add -A
$ git ci -m "Adding second post about git"
$ git push origin master
$ git push prod master

Now visit your website again and you will see your new post!

Alternate organization via git submodule

I experimented with setting up the output/ directory as a git submodule so the files automatically get placed in the HTML repository. However, in the process of generating the HTML content, pelican will blow away the git version control directory of your submodule. This cancels out the point of using a submodule in the first place and isn't work the hassle.

Comments !