Skip to main content

Installing & Configuring Nikola

Installation

This assumes that you have virtualenvwrapper.sh installed which isolates this installation from other projects you may have installed locally.

Create a virtual environment

bash$ mkvirtualenv myenv
This command creates a new virtual environment named "myenv". You can choose any name you like as long as it makes sense to you. Because I use this virtual environment for Nikola, I unimaginatively call mine "nikola". Once the command has completed, virtualenvwrapper automatically puts you in that virtual environment as shown by the prefix "(myenv)".

Optionally integrating shell completion

Adding shell completion is optional, but a nice addition that Nikola provides. The following two commands enable Nikola-specific tab-completion when you activate your virtual environment, and disable it when you deactivate the virtual environment.

(myenv)bash$ nikola tabcompletion --shell bash --hardcode-tasks >> "${VIRTUAL_ENV}/bin/postactivate"
(myenv)bash$ echo "complete -r nikola" >> "${VIRTUAL_ENV}/bin/predeactivate"

If you use zsh instead of bash, you can specify "--shell zsh" instead of "--shell bash".

Deactivating the virtual environment

(myenv)bash$ deactivate
This exits the virtual environment you created. Alternatively, you can just quit your command shell using "exit". During initial setup, you can skip this step, as you'll just need to reactivate the virtual environment to install Nikola.

Reactivating the virtual environment

bash$ workon myenv
This will activate the "myenv" environment again, as well as put the environment-name indicator in your prompt. If you didn't deactivate the virtual environment using deactivate, then you won't need to reactivate your virtual environment.

Install Nikola

(myenv)bash$ pip install Nikola
Inside your virtual environment (as shown by the environment-name inside parentheses before your usual prompt), this uses pip to fetch the latest version of Nikola and install it. This brings in a number of dependencies, some of which may need to be compiled. As such, if you don't have a compiler installed on your machine, you'll want to do that before this step.

Create a new blog

(myenv)bash$ cd /path/to/your/blog
(myenv)bash$ nikola init myblog
You can choose a name that you like for the folder instead of "myblog" (or similarly boring reasons, I named mine "blog"). This creates a folder called /path/to/your/blog/myblog in which your content, templates, cache, and output will go. It also prompts you for the name of your site, the main author's name, the main author's email address, a description of the site, the root URL for the site (which should end with a trailing slash such as "http://example.com/"), the languages you intend to use, your time zone, and which comment system you want to use (if any).

Configuration

Nikola's configuration takes place in "/path/to/your/blog/myblog/conf.py". Opening this file in your favorite text editor, you'll notice that the answers you gave during the "nikola init" process appear as the values to various settings within this file.

By default, Nikola expects markup to be reST but I prefer the straight-forward nature of HTML. So my first stop was to add HTML as a processed language. By putting it first in the list, it becomes the default for new_post which saves me from forgetting to specify the template as "-f html" every time I generate a new post. To do this, I modified the "POSTS = (…)" and "PAGES = (…)" to include the following lines:

POSTS = (
    ("posts/*.html", "posts", "post.tmpl"),
    ("posts/*.rst", "posts", "post.tmpl"),
    ("posts/*.txt", "posts", "post.tmpl"),
)
PAGES = (
    ("stories/*.html", "posts", "post.tmpl"),
    ("stories/*.rst", "stories", "story.tmpl"),
    ("stories/*.txt", "stories", "story.tmpl"),
)

I want to have my templates contain additional metadata fields for author (allowing me to easily override this for guest posts) and category. To do this, I found the comment containing ADDITIONAL_METADATA and added the following lines:

ADDITIONAL_METADATA = {
    "author": BLOG_AUTHOR, # default to me
    "category": "uncategorized",
    }

I also customized the CONTENT_FOOTER to show a minimal copyright notice:

CONTENT_FOOTER = """
    Contents © {date}
    <a href="mailto:{email}">{author}</a>
    {license}
    """
CONTENT_FOOTER = CONTENT_FOOTER.format(
    email=BLOG_EMAIL,
    author=BLOG_AUTHOR,
    date=time.gmtime().tm_year,
    license=LICENSE,
    )

To round out some personal preferences, I explored the Nikola handbook and added the following settings in their respective places:

PRETTY_URLS = True
SOCIAL_BUTTONS_CODE = ""
COPY_SOURCES = SHOW_SOURCELINK = False
USE_BUNDLES = False

Finally, I wanted to enable automated deployment of my blog to my web-hosting service. To deploy without needing to enter the password for my hosting service, I set up SSH keys and used ssh-copy-id to push the public key up to my server. With that in place, I adjusted the (formerly empty) list of commands DEPLOY_COMMANDS .

DEPLOY_COMMANDS = [
    "rsync -avr --delete output/ {login}@{host}:{path}".format(
        login="myusername",
        host="thechases.com",
        path="/home/myusername/public_html/",
        ),
    ]

This allows me to deploy by simply issuing "nikola deploy".

With Nikola installed and configured to my liking, it's time to go write some blog posts.

Why Nikola?

Why a static site generator over a dynamic blog engine?

  • I prefer to work in raw HTML because I've been doing it for years, and the markup is readable. For some reason, Markdown, Textile, and reST drive me nuts—mostly because it's easy for me to enter things I don't intend as markup, and when I want to do complex markup, I have to look up the obscure syntax in the documentation. Every. Single. Time.

    Most of the blogging engines do allow for directly entering raw HTML, but it always feels like I'm fighting against the grain. Every time I go to compose a post, I have to toggle into a special "HTML entry" mode. One wrong turn and some of the engines will "sanitize" my HTML, reformatting everything. A blogging engine should treat my content as sacred and never try to second-guess (or reformat) what I want.

  • To deploy these dynamic blog engines, it requires a server with the ability to run code (usually PHP but some used mod_perl, mod_python, or mod_cgibin) and a backing database such as MySQL. Granted, you can find free and low-cost hosting that provides simple PHP/MySQL access, so this isn't a huge hurdle, but it does place additional restrictions on which services you can use.
  • Some of the cheap/free shared-hosting plans put so many hosts co-located on the same hardware that performance becomes an issue—both database processing and the engine's processing. With a static site generator, there is very little overhead in serving static pages.
  • The more dynamic components in play, the more likely it is that vulnerabilities lurk due to the extra exposure. With a static site, far fewer parts are in motion to be attacked so I don't worry about vulnerabilities in PHP, Wordpress, or MySQL.
  • Many of the blog engines don't support versioning of the content. I can keep my static site content under revision control with git, Mercurial, Subversion, or a multitude of others.

Why Nikola rather than the other static site generators?

I compared several static site generators, both using a static site generator comparison site and my own testing. Top contenders included the following:

As I tested them, I started to develop a list of criteria that mattered to me:

  • As a Python developer, I had a bias towards those built in Python. It allows me to poke around under the hood, create patches when I find things I want to change, and gain a deeper understanding of how things worked in the event I hit edge cases.
  • Documentation mattered. Several projects had documentation that was incomplete, hard to navigate, or required JavaScript (which prevented the docs from working nicely on one of my e-readers).
  • Additionally, some projects seem less than active in their development. According to the static site generator comparison site, some hadn't been updated in months or years while others have had sustained, ongoing development.
  • Most importantly, I wanted the ability to compose in HTML fragments rather than being forced to use Markdown, Textile, or reST.
  • So I ended up settling on Nikola as it's developed in Python, allows me to use HTML fragments, has thorough documentation, and is actively developed.

Getting started with blogging

Intro

I've long had an interest in starting up a simple blog for the purpose of documenting various projects on which I'm working. So it seems that the first thing I should blog about is the process of choosing and configuring blogging software.

Hand-coded HTML

I started posting things on the web when I was in college where every page was hand-crafted HTML and dumped in ~/public_html/ of my account on the Computer Science web server (I believe it started as a DEC ULTRIX, but then became a Red Hat box) and everything went live thanks to Apache running mod_userdir. Even before using HTML, I frequently used WordPerfect 5.1's "Reveal Codes" ability to inspect the control tags/codes used by the document which saved me much grief. I still prefer HTML over modern markup competitors like Markdown, Textile, or reST because HTML's tags are consistent. When trying the other markup languages, I frequently get stung by entering text that turns out to mean something to the markup engine, and when I reach for some of the more powerful features (tables, acronyms, code blocks, etc), I have to go to the reference materials every single time to make sure I get it correct. In HTML, all markup consists of an opening < followed by a closing >, and entities are always escaped with &. Consistent—the way I like it.

However, any time I wanted to change the look and feel of the site, I had to touch every single file (at least those that I cared about) and I also had to remember to update any index pages every time I added or renamed a page.

Server Side Includes

At some point, I explored using Server side includes to make the site look more uniform. While it was a bit of a hassle, it had the advantage that I could update the look of the site by changing a couple included files. I still had to manually update indexes, but it was a step in the right direction. Again, for deployment, since my college server was running Apache with mod_include installed,

Dynamic blogging platforms

Then blogging platforms such as Wordpress and Drupal came along with dynamic sites backed by a database. These held a lot more promise, allowing me to maintain my content and site theme independently.

Static Site Generators

Finally, static site generators have grown in popularity. They allow for lower server demands, a smaller attack-surface, and a separation of the content from the structure it populates and its . This site has been created with Nikola, a static site generator developed in Python.