During the automated setup of my local Kubernetes cluster, I decided to cache most of my requests to APT. This works in a similar fashion to e.g. Artifactory, which I use to proxy Java/Kotlin dependencies. I soon faced the need to do the same for GO.
The easiest way would probably have been to continue with Artifactory and use it for APT, GO, NPM and so on. Unfortunately, only the Maven part is free for individual applications.
An alternative could have been Nexus. The open-source version offers all the repository types needed, e.g. APT or GO (and more). But there are some downsides. For example, there is no .deb package available. Installations must be done by hand. Configuration is another point of critic. Compared with Artifactory, it feels cumbersome to me. And finally, it still needs Java 8! The folks behind Nexus haven't been able to port it to Java 9 and later, yet.
Either way, Artifactory and Nexus are quite "heavy". Not something I would run on a Raspberry Pi 3. So, I found Athens, a specialized proxy cache for GO modules. It's still in development, but exactly what I needed: Lightweight, simple setup. Only drawback here: No .deb file, either. But they provide an install script that builds Athens and installs a Systemd service, fully automated. There are some things to consider, though. What follows is a little step-by-step instruction of my journey installing Athens on a Raspberry Pi 3.
Note: In the following sections I will use
proxy to denote my laptop and my Raspberry Pi (which I baptized 'proxy'). In former times,
pi was the default user on any Raspberry Pi. Nowadays, when you install Raspberry Pi OS, you will be prompted to name a first user. To make things simple, I'll stick wih the user
Before I could install Athens by means of compiling it, I heeded a GO versions >= 1.17. Raspberry Pi OS is based on Debian Bullseye (stable), which currently only ships with GO 1.15. But one can add the Debian backports repository to have newer versions of GO available.
First, I added the backports repo:
echo "deb http://deb.debian.org/debian bullseye-backports main" | sudo tee -a /etc/apt/sources.list
Then I needed to get the repository keys. For that, I spun up a Debian container on my local machine with Docker and copied over the public keys:
mkdir -p /tmp/transfer docker run -it --rm debian:bullseye -v /tmp/transfer:/transfer #Within the container cp -r /etc/apt/trusted.gpg.d/ /transfer
Next, I copied the keys over to my Raspi:
scp -r /tmp/transfer/trusted.gpg.d/ pi@proxy:
After I logged in on the Raspi, I finally copied the keys so APT would find them:
sudo cp ~/trusted.gpg.d/* /etc/apt/trusted.gpg.d/
Now, I was able to install GO 1.19 from the backports repository:
sudo apt update && sudo apt install golang -t bullseye-backports
Installing Athens was quite simple. First, I had to get the code:
git clone https://github.com/gomods/athens.git
Then, I had to copy over the template config and adjust is to my liking. So far, I only made sure that instead of storing everything in memory, Athens would store all cached data on disk:
cd athens #systemd.sh expect a file config.toml at the root of the repository folder cp config.dev.toml config.toml
config.toml I changed
StorageType = "memory" to
StorageType = "disk" and in the '[Storage]' tree I set the path to where I wanted to have all files saved by replacing
RootPath = "/path/on/disk" with
RootPath = "/var/cache/athens".
I also needed to create that 'RootPath' (with the right permissions). When invoked by SystemD, Athens will be executed with the user
www-data. So, I had to take that into account:
sudo mkdir -p /var/cache/athens sudo chown -R www-data:www-data /var/cache/athens
scripts/systemd.sh I had to comment out the following four lines in
ATHENS_DISK_STORAGE_ROOT=/var/run/athens sudo mkdir -p $ATHENS_DISK_STORAGE_ROOT sudo chown www-data $ATHENS_DISK_STORAGE_ROOT sudo chgrp www-data $ATHENS_DISK_STORAGE_ROOT
Otherwise, my customized 'RootPath' would have been overwritten.
I also had to edit
scripts/service/athens.service. Again, there was some hard-coded stuff:
Environment=ATHENS_DISK_STORAGE_ROOT=/var/run/athens. I simply comment out that line.
Environment=ATHENS_DISK_STORAGE_ROOT=/var/run/athens neded to be adapted to the same path from the config.toml.
Now, with the right GO version installed, a customized config file and a some fixed applied, I was fully prepared to install Athens. So, from the root of the repository folder I only had to execute:
sudo scripts/systemd.sh install
That execution compiled Athens and installed a Systemd service. Sudo is required, otherwise the Systemd service would not be installed.
Finally, I ran
scripts/systemd.sh status and made sure, everything was in order.
Back on my host machine, I was then able to install for instance yq (which is not yet in the Debian repositories):
export GOPROXY="http://proxy:3000 go install github.com/mikefarah/yq/v4@latest
After that I had a look on the Raspi. There should now be some data in
/var/cache/athens, and it was. So, from now on, Athens will intercept each call, download any available updates or directly serve any cached version, in case there are no updates available upstream.
Athens is simple and easy to set up. The only thing that cost me some time was the hard-coded
ATHENS_DISK_STORAGE_ROOT variable. Unfortunately this installation procedure is not promoted by the project. Neither on the official homepage nor on the README. You can find it in DEVELOPMENT.md file. Athens offers an abundance of configuration settings. You should definitely check out the full
config.dev.toml file. Hint: If you execute
scripts/systemd.sh without any parameters, it will tell you what it can do!