Goatcounter analytics in ikiwiki
I have started using Goatcounter for analytics after reading this LWN article called "Lightweight alternatives to Google Analytics". Goatcounter has an interesting approach to privacy in that it:
tracks sessions using a hash of the browser's user agent and IP address to identify the client without storing any personal information. The salt used to generate these hashes is rotated every 4 hours with a sliding window.
There was no Debian package for the project, so I filed a request for package and instead made a fork of the project to add a Docker image.
This page documents how Goatcounter was setup from there...
Initial server configuration
Note that this procedure was slightly modified to use docker-compose
to ease upgrades, see the upgrade procedure at the end for details.
build the image from this fork
docker build -t zgoat/goatcounter .
create volume for db:
docker volume create goatcounter
start the server:
exec docker run --restart=unless-stopped --volume="goatcounter:/home/user/db/" --publish 127.0.0.1:8081:8080 --detach zgoat/goatcounter serve -listen :8080 -tls none
apache configuration:
<VirtualHost *:80> ServerName analytics.anarc.at Redirect / https://analytics.anarc.at/ DocumentRoot /var/www/html/ </VirtualHost> <VirtualHost *:443> ServerName analytics.anarc.at Use common-letsencrypt-ssl analytics.anarc.at DocumentRoot /var/www/html/ ProxyPass /.well-known/ ! ProxyPass / http://localhost:8081/ ProxyPassReverse / http://localhost:8081/ ProxyPreserveHost on </VirtualHost>
add
analytics.anarc.at
to DNScreate a TLS cert with LE:
certbot certonly --webroot -d analytics.anarc.at --webroot-path /var/www/html/
note that goatcounter has code to do this on its own, but we avoid it to follow our existing policies and simplify things
create site:
docker run -it --rm --volume="goatcounter:/home/user/db/" zgoat/goatcounter create -domain analytics.anarc.at -email anarcat+rapports@anarc.at
rebuild wiki:
ikiwiki --setup ikiwiki.setup --rebuild --verbose
Remaining issues
- Docker image should be
FROM scratch
, this is statically built golang stuff after all... update: someone else made an image based on alpine, but still notFROM scratch
... mine could possibly work, but I'm not sure how to create the user... or do i need aUSER
to run as non-root? TBD. - this is all super janky and should be put in config management somehow
- do log parsing instead of Javascript or 1x1 images? now possible, but not deployed (yet?)
Fixed issues
cache headers are wrong (120ms!)deployed workaround in apache, reported as a bug upstreamremove self-refererdone, just a matter of configuring the URL in the settings. could this be automated too?add pixel tracking fordone, but required a patch to ikiwi (and I noticed another bug while doing it)noscript
users(fixed upstream!)goatcounter monitor
doesn't with sqlitethe :8080 port leaks in some places, namely in the "Site config" documentationthat is because i was using-port 8080
which was not necessary.move to Docker Compose or podman instead of just starting the thing by handdone, although i still need to watch for releasescompare with goaccess logs, probably at the end of july, to have two full weeks to compare.done, see this post.remove "anarc.at" test site (the site is the analytics site, not the tracked site), seems like this is not possible yetfixed upstream, site marked as deletedtitles are messed up since the 2.x upgrade, see upstream bug reportdue to a database migration that normalized the tables, will fix itself eventually apparently
Upgrade procedure
This procedure was done to upgrade from ~1.4.0 to 1.4.2, 2.0.4, and 2.1.1:
rebase on top of target release
cd ~anarcat/dist/goatcounter/ git rebase v2.1.1
build image:
docker build -t anarcat/goatcounter:2.1.1 .
stop old container:
cd ~anarcat/src/composes/goatcounter/ docker-compose rm --stop
backup container data:
tar -c -z -C /var/lib/docker/volumes/ -f /var/lib/docker/volumes/goatcounter.tgz goatcounter_goatcounter/
update the image version:
sed -i s,anarcat/goatcounter:.*,anarcat/goatcounter:2.1.1, docker-compose.yml
run the migrations:
docker-compose run goatcounter db migrate all
start container with new image, make sure to update the
image:
tag:docker-compose up -d