This is the latest iteration of my website, written in Crystal.
Markdown files in a Git repository are used to produce the archive pages.
Archive posts are sorted based on the filenames, so they are prepended with
YYMMDD format and don't contain spaces. Filenames prepended with
underscores are not rendered, providing a way to unpublish content or choose
which content is ready to be published at any given time. Dates displayed
alongside the titles are simply the first line in the file, while the titles are
extracted from the second line.
Changes to the markdown files on the server are automatically detected, causing
those pages to be rerendered as necessary. This allows for a single
to publish content to the website, after committing the changes.
Convenient place to push files that need to be temporarily made available
publicly, without having to take the website offline and spin up a static
fileserver instead. While this functionality is basic, it often obviates the
need for external services, and comes in particularly useful for things like
making presentation resources available. Accessible at
/temp, although not
directly linked to from anywhere on the website.
Simplistic request count statistics, intended to give some hint about which
pages are getting traffic, without resorting to third-party analytics services.
Query parameters are not tracked, nor are paths that get routed to
for security reasons. The data is saved to the filesystem in JSON format so
that it gets retained across server restarts. Accessible at
not directly linked to from anywhere on the website.
Custom logger middleware for keeping persistent logfiles, since otherwise they disappear according to the scrollback settings, which is occasionally unhelpful. Logging statements are written simultaneously to STDOUT and an in-memory buffer, the contents of which are periodically appended to a logfile. This approach has the benefit of avoiding the overhead of constant opening and closing of files in the request pipeline hot-path; slow filesystem IO is minimized.
- install Crystal
ln -s ~/archive archive && mkdir temp
crystal run src/website.cr -- --dev
These deployment steps assume that certificates have already been obtained from
Let's Encrypt (see
CERTS.md for details on that process), that the
redirect server has been setup, that the domain has been registered
(through Namecheap or some other registrar), and finally that the records
are set in the networking management section within DigitalOcean. For
reference, the required networking records are documented in
they're not very obvious and are of the frequent stumbling blocks people hit
trying to initially deploy websites.
# clone and build on the server sudo dnf install crystal git openssl-devel git clone email@example.com:delgrecoj/website.git cd website shards install crystal build --release --no-debug src/website.cr
# setup bare repository, hook, and symlink on the server mkdir archive.git cd archive.git git init --bare echo '#!/bin/sh' > hooks/post-receive echo 'GIT_WORK_TREE=$HOME/archive git checkout -f' >> hooks/post-receive chmod +x hooks/post-receive mkdir ../archive cd ~/website && ln -s ~/archive archive
# setup local repository to push to the server git remote add pserver ssh://pserver/~/archive.git git push -u pserver master
# must be ran with sudo for access to port 443 sudo ./website
- occasionally stops working, with unhelpful SSL errors
- update local and server setup to use Nix
- deprecate running in detached
- consider adding support for images
- consider adding support for tags
- migrate archive posts across