My personal website, build with Jekyll and a simple CI/CD pipeline to keep the long-term costs (ie: my time) as low as possible.
I wanted a simple website where I could put up some personal information and descriptions of projects I have worked on.
Because it is not something I want to spend a lot of time on in the future it had to be easy to update, require little maintenance and use minimal server resources.
The visual aspect should be simple but not too basic, compatible with modern browsers/window sizes/etc. and be mostly ready-to-use, as frontend work is not my strong point.
Because of my current and past interests I also wanted it to be something I build/run myself with CI/CD tools. As the end result would (ideally) only involve serving static files it could also serve as a nice minimal requirements case study.
Based on my goals and existing experience I chose the following tools:
Initial steps consisted of registering the domain name, creating a new Digital Ocean droplet, creating a Gitlab group and project, getting an initial commit with Jekyll+desired template, etc. Besides it being my first domain name most of this was pretty familiar and went smooth enough.
I also had some experience with running Jekyll via Gitlab CI, so next up was getting it to run inside a Docker image. I chose an Nginx base image and after some fiddling I got Gitlab CI to build it and push it to Gitlab's container registry. Now all that remained was deploying it to production!
To get visible results as soon as possible I initially pulled/deployed the site by hand on the server, which worked well enough. In previous projects I had used Gitlab Pages which handles the deployment/hosting step for you, so I assumed that Gitlab CI would provide tools in this case as well.
Unfortunately I could not find anything that fit my use-case and I ended up letting Gitlab CI execute a series of Bash commands that replicated my manual deployment method (but see updates). This is far from optimal (I have to store deploy keys into temporary files so SSH can login for instance) but learning and running Kubernetes for a website this tiny seemed excessive :-P.
All in all I spend a couple of hours on each of four days to go from initial idea to having everything up and running (sans content). I managed to "outsource" the jobs I don't know/like (graphic design, site performance) to existing tools while using my strengths to achieve something I normally never would want to spend time on.
While creating new content I only have to focus on that content, with everything from browser reloads to page style to publication done automatically.
The production environment is cheap, stable and responsive.
Besides the site itself I am also very happy to finally have a personal domain name under my full control.
Searching for the right Jekyll template taught me how much unconscious requirements I had besides "simple" :-P, and took more time than I had intended.
The deployment method (Gitlab CI running a bash script that runs "docker pull" over SSH) really needs to be improved (but see updates).
Jekyll uses (Ruby) Bundler to manage dependencies and I am not too familiar with Ruby or Bundler. So maybe it is my fault, but so far I've have had two occasions where a previously working environment refused to run because it somehow ran into a dependency conflict. This was especially annoying when it would only occur during the CI build stage, but not in my development environment. Not what I would have expected from using a proper dependency management system in combination with Docker, but maybe I missed something.
Changes to the CI/CD pipeline should be tested locally as much as possible, as running the pipeline takes a few minutes and does not always give the best error output. Roughly 80% of the "pre-1.0" commits where variations on "minor change, lets see if this works" so quick, clear feedback would have sped up development immensely.
Livereload is really neat! (and usable with Jekyll)
Adding a command like this:
to your .bash_aliases file can make it feel like you run a tool natively while keeping the isolation advantages of Docker. I was not surprised to later discover that package managers like Snappy and Flatpak work similar to this, because it is really convenient!
Initial version as described above.
Access of the site now runs via an Nginx reverse proxy, with automatic binding of domain names to docker containers managed by nginx-proxy. This allows me to keep all configuration of project (including which sub-domain it is published under) inside the project folder.
Delivery of new images to the production server is now done by Watchtower (with this configuration). This means no more Gitlab CI scripts that perform docker image pulls over SSH, which felt clunky and error prone from the beginning.