Moving pelican blog to own server
Rationale
For the longest time my website consisted only of a contact page -- it was a pyramid process that served only a single template page, with a very few variables on it. Talk about overkill.
Given that, when I created my blog with Pelican static site generator I just threw it up on github.io and kind of forgot about, except for the times when I felt that I had something to say.
I thought I was going to expand my website at some point, but I never did, in fact running one-off web application took surprising amount of effort: debian python system version would get updated, pyramid app will get security patches, and the virtualenv that runs from @reboot cronjob would inevitably break.
I didn't want to keep maintaining pyramid stack just for a single page, and expending it into something bigger would mean coding styling from scratch, instead using an existing theme for an existing static site generator would be way simpler.
When my interest in videography became serious where that I actually end up getting a few referrals, I needed a page to to show my work. I would also need a place to group any of the articles or instructional videos I have in mind.
About a month ago I removed google analytics from my blog, but I'm still a bit curious how people are visiting my site, and when I host content on my own server I have logs which I can analyze without also giving google all the information.
This ended up being one of my holiday projects.
Styling
I wanted to switch from standard layout by Smart Magazine to something that displays a bit more content. I looked through a collection of pelican themes and settled on a Brutalist pelican theme that follows Brutalist Web Design philosophy.
I made a couple of minor tweaks to the theme: article description text has more contrast, content element has smaller padding that more content is displayed horizontally, tables have visible cell borders and MASTODON is available as an option in social media links section. See my fork on github.
Configuration changes
Pelican has ability to have static pages and articles (blog posts).
Before the move I used pelican only for blogging, and adding back article in the exact way I wanted was the most involved part. What I wanted to have is a number of articles linked from the front page, and all the blog articles live under url /blog/.
In this stack overflow answer the author of pelican project describes how to implement what I wanted. However, I didn't have patience to resolve the issue in this way -- I kept getting template rendering failure with no clear error message, so I 'well, actually' my own answer that has fewer drastic changes, but may need more maintenance in the long run, as in my case article pages only show up in navigation when they are added to MENUITEMS list.
Here is my pelicanconf.py
#!/usr/bin/env python
# -*- coding: utf-8 -*- #
from __future__ import unicode_literals
AUTHOR = 'Alex Volkov'
SITENAME = 'Alex Volkov | A personal electronic web page'
FIRST_NAME = 'Alex'
SITEURL = 'https://flamy.ca'
PATH = 'content'
TIMEZONE = 'America/Toronto'
DEFAULT_LANG = 'en'
# Feed generation is usually not desired when developing
FEED_ALL_ATOM = None
CATEGORY_FEED_ATOM = None
TRANSLATION_FEED_ATOM = None
AUTHOR_FEED_ATOM = 'feeds/{slug}.atom.xml'
AUTHOR_FEED_RSS = 'feeds/{slug}.rss.xml'
DEFAULT_PAGINATION = 10
# Uncomment following line if you want document-relative URLs when developing
# RELATIVE_URLS = True
PLUGINS = ['pelican_youtube']
STATIC_PATHS = ['images']
ARTICLE_URL = "blog/{date:%Y}-{date:%m}-{date:%d}-{slug}.html"
ARTICLE_SAVE_AS = "blog/{date:%Y}-{date:%m}-{date:%d}-{slug}.html"
INDEX_SAVE_AS = "blog/index.html"
# Theming
THEME = 'themes/brutalist'
# used for OG tags and Twitter Card data on index page
# used for OG tags and Twitter Card data of index page
# path to favicon
# FAVICON = 'pelly.png'
# path to logo for nav menu (optional)
# LOGO = 'pelly.png'
# first name for nav menu if logo isn't provided
ATTRIBUTION = False
## Add a link to the tags page to the menu
## Other links can be added following the same tuple pattern
DISPLAY_PAGES_ON_MENU = False
DISPLAY_CATEGORIES_ON_MENU = False
MENUITEMS = [
('home', '/'),
('blog', '/blog'),
('presentations', '/pages/presentations'),
('videography', '/pages/videography'),
('tags', '/tags'),
]
GITHUB = 'https://github.com/avolkov'
MASTODON = 'https://mastodon.xyz/@avolkov'
Nginx config
I had to tweak nginx configuration that instead of connecting to a socket, the web server just displays static content.
server {
listen 0.0.0.0:443;
ssl on;
ssl_certificate /etc/letsencrypt/live/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/privkey.pem;
server_name flamy.ca;
access_log /var/log/nginx/flamy_ca.access.log;
location / {
root /srv/flamy_ca/;
try_files $uri $uri/ $uri.html =404;
index index.html index.htm;
}
}
Updating old links
I didn't want to remove my existing pages from github.io, as they are getting referrals from the search engines. Instead I went through the old HTML blog entries, and manually updated each page to contain a crawler-friendly redirect url.
Here's the template I used to create the redirects
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="refresh" content="0; URL=https://flamy.ca/blog/NEW-URL" />
<link rel="canonical" href="https://flamy.ca/blog/NEW-URL">
</head>
<body id="index" class="home">
</body>
</html>
Deployment
My previous setup used internal gitlab repo for drafts and a github.com repo that points to github.io. That setup was somewhat confusing but not the worst, as I've seen configs that use the only github.io-based repository with a deploy script that uses two branches: one for storing source text, and the other for generated content.
Right now I use single repository to store content and a command that syncs the contents of output/ directory to remote server.
The following command generates content and start the serve in development mode, for when I'm working on an article.
$ make clean && make html && make serve
Once an article is finished, copy generated content to remote directory
$ rsync --archive --del --progress output/* flamy.ca:/srv/flamy_ca/
I'm planning to automate this with gitlab runner, so the steps of generating content and deployment are done every time commit is pushed to master branch.