Post

Creating a Personal Website with Jekyll

Creating a Personal Website with Jekyll

If you’re someone like me and like to host various services, you might also want to have your own personal website. There are many approaches to this, for example you could use a CMS like WordPress or ghost, you could use a static site generator like Jekyll (that’s what GitHub Pages use) or you could program your own site if you want.

I’ve tried a bit of all of them, but it never really worked for me. Eventually I landed on Jekyll, so this is also where you’re reading this on now. To be honest, I don’t have too much expertise on the topic, but I made it work, and a Blog needs posts.

Pros of Jekyll

Dead Simple

Usage of Jekyll is really easy in my opinion. You kind of just write markdown files and add some front matter. That is if you’re using a pre-made template of course, you can make it as complicated as you want, just note that Jekyll generates static sites, so no fancy server side computation.

A lot of modern themes

There are a lot of modern and good-looking themes for Jekyll. At the time this post is written, cscherr.de uses chirpy.

A large collection of Jekyll themes can be found here (note: this site does not use HTTPS for some reason).

The ones I’d recommend:

  • Chirpy - This is what this website uses too!
  • Digital Garden - Excellent for notes instead of a blog, I’m customizing this for a private novel. This template even features a graph showing the relationships between the notes!

Insane extendability

As Jekyll is just a generator for static html pages, we can make use of the endless amount of web technologies without worrying how they will play with our backend. Want to use your favorite CSS framework, or even add your own CSS? No problem. Using existing template websites is easy too! Jekyll even has builtin SCSS support, which makes adding your own custom CSS much more comfortable.

Cons of Jekyll

Multilingual sucks

With the chirpy theme at least, I couldn’t get Multilingual content to work without going into the rabbit hole. You can select from a good amount of main languages, but you cannot have multiple versions of your website for various languages in a single project.

Various projects for multilingual Jekyll sites exist, but the only one that seems to be still maintained is polyglot.

Deployment with Docker

Docker is a really useful program that can be used to deploy many services, Jekyll too. I won’t go into the details here, but the idea is that your kernel runs a separate mini OS, which reproduces the same environment every time and streamlines deployment. It’s also good for security, as someone who takes over the webserver will only have the rights of the webserver inside the docker container, instead of on your real OS.

The “official” Jekyll Docker container is unmaintained since 2022, so if you want to deploy Jekyll with docker you need to create your own container. I based this on the standard ruby image.

We can use a Dockerfile like this:

1
2
3
4
5
6
7
8
FROM ruby:3.4
WORKDIR /app

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
RUN git config --global --add safe.directory /app
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 4000

We need to mount our Jekyll project to /app, it is not included with this Dockerfile.

1
2
3
4
5
6
7
#!/bin/bash
set -e

bundle install

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"

In the entrypoint.sh, we need to install the dependencies of our actual project. This will take a while…

We can then use a docker-compose.yml file to deploy our config.

1
2
3
4
5
6
7
8
9
10
services:
  jekyll:
    build: .
    volumes:
      - .:/app
    container_name: mysite
    ports:
      - 127.0.0.1:4000:4000
      - 127.0.0.1:35729:35729
    command: bundle exec jekyll serve --host 0.0.0.0 --port 4000 --livereload --watch

This is a docker compose file for a development environment. It may work for production, but it is likely inefficient and less secure.

The --livereload flag makes it so that your browser reloads everytime there is a change. This requires port 35729 to be open.

Now you should be able to start the docker container with Jekyll inside by using docker compose up. Access your site on localhost:4000.

Update

After running my site for a while, I have been made aware that basically just having jekyll serve is maybe not the best way to do things. Jekyll also provides the command jekyll build, which exports your website without all the data used to build it, so that any regular webserver can serve the static site.

Having a static website be built and then just be served as files, without an additional process seems to make more sense, so that’s what I will do from now on.

For that purpose, I have made a small build script:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
GID=$(id -g)
set -e

rm -rf _site
echo "
set -e
echo doing the building
JEKYLL_ENV=production bundle exec jekyll build --no-watch
rm -vrf /app/_site/docker* /app/_site/*.sh /app/_site/entrypoint.sh
chown $UID:$GID /app/_site -R
" \
| docker run -iv "$PWD:/app" krata /bin/bash

After this script, just serve the _site directory with a webserver of your choice. (My recommendation is caddy)

If you do this, be careful not to let your webserver expose your .git directory, otherwise your (possibly private) repository gets leaked.

I’m still using docker to make sure the versions match. The ruby version in the repositories of my Linux Distribution is rather outdated and not suitable for building with jekyll. You don’t strictly need docker to build, but in my opinion at least, it makes things easier.

That being said, you definitely don’t need docker to actually make the site accessible.

To upload the build dir to the remote server, you may use the following script. You just need to have ssh access to a user that can control the webroot directory.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/bin/bash
UNIXTIME=$(date +%s)
DEPLOY_TO=cscherr.de
WEBROOT=/srv/caddy/site # if you unset this, everything will explode
TMP_FILE=$(printf "/tmp/%s_site.tar.gz" "$UNIXTIME")
set -e

echo building website
bash ./build.sh

echo making archive...
tar czf $TMP_FILE _site
echo uploading archive to $DEPLOY_TO : "$TMP_FILE"
scp $TMP_FILE $DEPLOY_TO:"$TMP_FILE"
echo installing archive in webroot: $WEBROOT
echo "
set -e
mkdir -p $WEBROOT
rm -rvf $WEBROOT/* $WEBROOT/.*
tar xvf $TMP_FILE --directory $WEBROOT
rm -vf $TMP_FILE
mv -fv $WEBROOT/_site/* $WEBROOT
rmdir -v $WEBROOT/_site
" \
| ssh $DEPLOY_TO /bin/bash
echo removing local upload file
rm -f $TMP_FILE

There we have it! Now we can make changes, run our deploy.sh, and things are up to date on the webserver, without the need for docker stuff or something extra on the server.

If you have more questions, feel free to comment below or write me an E-Mail.

This post is licensed under CC BY 4.0 by the author.

Trending Tags