Building a Deployment Pipeline for my Blog
Updated 12 Feb 2025
Updated 12 Feb 2025
This is a follow-up to my previous post on building a blog with Go. In it, I'll go over how I host my blog on a Raspberry Pi in my basement. In order to explain in it in a linear way, I'll walk through the deployment pipeline I have set up. But before I do that, I'll talk about some issues I had with SQLite and compiling my code to run on my pi.
Here's the code for my blog.
Back when I was first trying to get the blog to run on my Raspberry Pi, I didn't quite understand this command:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o web
I was encountering errors like undefined: sqlite3.Error
and undefined: sqlite3.ErrConstraint
However, when I checked the file where there error is coming from, those two variables were defined and the code compiled just fine in my development environment. It turned out that there were two issues:
CGO_ENABLED=0
disables CGo, but my code depended on the sqlite3
package which relies on CGo to interface with SQLite's C library, and when CGO_ENABLED=0
was set, it was preventing any C code from being compiled.GOARCH=amd64
was the wrong architecture for my Raspberry Pi. I knew this but somehow my eyes kept reading it as GOARCH=arm64
.I really lost the script for a while on this one. I tried a bunch of things before I realized my mistakes. I also needed to install the gcc
and libsqlite3-dev
packages on my Raspberry Pi.
So in the end, it's not a perfectly portable blog app. But I learned a lot and it's still pretty cool to have the database and UI embedded in the binary.
I just recently redid my deployment pipeline to simplify things a little. It's probably not going to be a permanent solution as I plan on deploying my blog to my Kubernetes cluster in the not-too-distant future. Here's an overview of how the new pipeline works:
main
branch on Githubcloudflared
service on my pi passes this onto Caddy which acts as a reverse proxy for the services running on my pi.deployprod.sh
script in my Go application's scripts
directory.deployprod.sh
script does the following:
main
buildprod.sh
script that builds my blog for arm64main.css
and if I don't bust the cache, my website may be left in an undesirable visual state.There were several bumps in the road to getting the pipeline up and running. Here are a few of them and what I learned in the process:
deployprod.sh
to run without requiring a passwordopenssl rand -base64 32
.cloudflare_zone_id
, and cloudflare_token
to get the cache purge working.Overall, not a bad solution! The next step would be to codify the server environment and dependencies in an Ansible playbook so that if I want to move this site off of my pi and onto another machine, I can just run the playbook on the new machine, clone the blog repo (and webhook repo) and I'll be off to the races. I have been thinking of turning my Raspberry Pi into a PiKVM so that I can have remote management of my two main storage servers. So maybe this Ansible playbook will happen sooner rather than later.