I’ve written before about how I deploy this blog using Drone.io. It works well, and does exactly what you’d expect.

Lately I’ve started looking into reducing complexity in homelab systems that I use — and using “a Continuous Integration platform for busy development teams” felt a bit overkill for this tiny blog.

So I switched to something simple; GNU Make.

Table of contents

Using Drone.io

Let’s quickly recap my Drone.io setup — this was the production entry in my .drone.yml file:

---
kind: pipeline
type: ssh
name: production

trigger:
  event:
  - promote
  target:
    include:
    - production

server:
  host: build.lan.uctrl.net
  user: hebron
  password:
    from_secret: password

steps:
- name: initialize
  commands:
  - git submodule update --init
  - hugo version
  - ln -s /home/hebron/hugo_resources/production resources

- name: build
  commands:
  - hugo --gc -b https://blog.cavelab.dev/

- name: cleanup
  commands:
  - rm public/style.css
  - rm public/assets/main.js
  - rm public/assets/prism.js
  - rm public/assets/style.css

- name: s3-deploy
  environment:
    AWS_ACCESS_KEY_ID:
      from_secret: AWS_ACCESS_KEY_ID
    AWS_SECRET_ACCESS_KEY:
      from_secret: AWS_SECRET_ACCESS_KEY
  commands:
  - hugo deploy

- name: s3-aliases
  environment:
    AWS_ACCESS_KEY_ID:
      from_secret: AWS_ACCESS_KEY_ID
    AWS_SECRET_ACCESS_KEY:
      from_secret: AWS_SECRET_ACCESS_KEY
  commands:
  - ./aliases_s3.sh

- name: algolia-index
  environment:
    ALGOLIA_APP_ID: B9W2KAEOUF
    ALGOLIA_ADMIN_KEY:
      from_secret: ALGOLIA_ADMIN_KEY
    ALGOLIA_INDEX_NAME: content
    ALGOLIA_INDEX_FILE: public/algolia.json
  commands:
  - atomic-algolia

Three services are involved here:

  • Drone.io (docker container)
  • Drone.io SSH runner (docker container)
  • Build machine (LXC container)

The production deployment triggered when a build was promoted to production.

Briefly explained; here is what happened:

  • The git repository and submodules were cloned
  • Symbolic link for Hugo’s resources folder created (to preserve processed images)
  • Site was built
  • Leftover files from the theme were removed
  • Deployed to AWS S3
  • Hugo aliases converted to redirects
  • Content pushed to Algolia
Build steps in Drone.io

The process took about two and a half minute — with the clone step taking the longest, at almost one minute.

Having to clone the repository every time felt unnecessary, the repository for this blog is fairly large at 808 MiB. And keeps growing with every publish.

Most of that are images — you could store images outside the repository, but I like to have everything together. The images are a critical part of the site, so they have to be kept in sync somehow.

Alright, enough of that. Over to Make 🙂

Using Make

This is the Makefile I’m currently using:

-include .env
export

UID=dev
GIT_ID=$(shell git rev-parse --short HEAD)
HOSTNAME=$(shell hostname)

export FOOTER_BUILD_INFO=$(GIT_ID)

.PHONY: server
server:
	hugo -D server --renderStaticToDisk

# The UID can be overwritten from the CLI: make deploy UID=`uuidgen`
.PHONY: deploy_dev
deploy_dev:
	hugo -D -b https://blog-${UID}.staging.mydomain.no/
	rsync -ah --stats public/ staging:/var/www/html/blog/${UID}
	@echo Deployed to https://blog-${UID}.staging.mydomain.no/

.PHONY: deploy_production
deploy_production: build_only initialize
	hugo -b https://blog.cavelab.dev/
	rm public/style.css
	rm public/assets/main.js
	rm public/assets/prism.js
	rm public/assets/style.css
	hugo deploy
	./aliases_s3.sh
	atomic-algolia

.PHONY: initialize
initialize:
	git pull
	git submodule update --init
	rm -r public/

.PHONY: build_only
build_only:
ifneq ($(HOSTNAME),build)
	$(error Must be run on build machine.)
endif

content/homelab/cover.png: rack.diag
    rackdiag rack.diag -o $@ 

A phony target is one that is not really the name of a file; rather it is just a name for a recipe to be executed when you make an explicit request. (…) — Make manual

I don’t know about you — but this syntax just speaks to me 😃 Each step, or rules as they are called, is laid out with its dependencies and shell commands.

Make can also be used like NPM scripts — the server rule in my Makefile simply starts a Hugo server, with drafts and static rendering to disk. Quick and easy 🙂

The FOOTER_BUILD_INFO environment variable is used to show the current git commit hash in the site footer.

The last rule, for content/homelab/cover.png, is used to rebuild the rack drawing for my homelab — using rackdiag.

Deploy

Let’s look closer at the deploy_production rule; we can see that it depends on build_only and initialize. build_only ensures that it can only be done on the build machine, while initialize does a git pull, submodule update, and clears the public folder.

After that; the same steps as before is done: build, clean up, deploy, make redirects, and push to Algolia 👍

So; to deploy to production — I SSH into by build machine, navigate to the cavelab-blog folder and type: make deploy_production.

Credentials

Credentials are stored as environment variables, in a .env file:

AWS_ACCESS_KEY_ID=xxxx
AWS_SECRET_ACCESS_KEY=xxxx

ALGOLIA_APP_ID=xxxx
ALGOLIA_ADMIN_KEY=xxxx
ALGOLIA_INDEX_NAME=xxxx
ALGOLIA_INDEX_FILE=xxxx

Performance

Let’s take a quick look at performance; using Drone.io took 2 minutes 24 seconds, with the longest step being clone.

$ time make deploy_production
Start building sites … 

                   |  EN    
-------------------+--------
  Pages            |   514  
  Paginator pages  |   153  
  Non-page files   |  2088  
  Static files     |    32  
  Processed images | 10813  
  Aliases          |   144  
  Sitemaps         |     1  
  Cleaned          |     0  

Total in 26098 ms
real 1m15.423s
user 0m17.833s
sys 0m14.397s

Now it takes 1 minute 15 seconds 🎉 Most, if not all, of that can be attributed to the lack of a clone step — instead I’m now doing a git pull, which is much faster 🙂

Conclusion time

Using Make instead of Drone.io means less moving parts — reduced complexity. But it’s also faster and more suited for my use case 🙂

It may not be for everyone; I now have to run a terminal command to deploy the site — as before I could do it through a web interface.

This isn’t a problem for me — I do my writing in the terminal anyway, with Vim.

🖖

Last commit 2023-12-25, with message: replace emoji slight_smile/slightly_smiling_face