GoatCounter is an Open Source Analytics written in Go.
GoatCounter offers a free hosted version for small and hobby websites.
One issue however occurs when users with an adblocker access the website, as access to external websites is often blocked.
By hosting GoatCounter yourself on a different subdomain, most adblockers will allow the request to go through.
GoatCounter most likely does not require a GDPR consent notice.
GoatCounter is distributed as a statically compiled binary.
Releases can be found on GitHub
As GoatCounter is a separate binary, I'm using the path /usr/local/bin
with a new folder called goatcounter
as the destination.
The binary file will be moved after downloading, in order to avoid modifying the systemd service after every update.
mkdir /usr/local/bin/goatcounter
cd /usr/local/bin/goatcounter
wget https://github.com/arp242/goatcounter/releases/download/v2.4.1/goatcounter-v2.4.1-linux-amd64.gz
gzip -d goatcounter-v2.4.1-linux-amd64.gz
mv goatcounter-v2.4.1-linux-amd64 goatcounter
The extracted binary needs to be marked as executable.
chmod +x goatcounter
GoatCounter needs write permissions for the directory it is located in to create its SQLite database on startup.
As I will be using a reverse proxy in front of it, I need to add the following two parameters when executing GoatCounter.
-listen :8888: Set listening Port to 8888 for use with a reverse proxy
-tls http: By default GoatCounter tries to generate a certificate using ACME. This option forces unencrypted HTTP
Run GoatCounter once to generate the necessary database files.
./goatcounter serve -listen :8888 -tls http
To use GoatCounter, a new site needs to be defined.
You will be prompted for the user password.
-vhost: Domain used for GoatCounter
-user.email: Login email address
./goatcounter db create site -vhost {URL} -user.email {EMAIL}
Create a service file at /etc/systemd/system/goatcounter.service
The WorkingDirectory
option can be changed to control where you want to create the SQLite database file.
Do note, that you will have to specify the database location using -db 'sqlite+{PATH TO DB}.sqlite3
when running the binary directly.
[Unit]
Description=GoatCounter Service
After=network.target
[Service]
Type=simple
WorkingDirectory=/usr/local/bin/goatcounter
ExecStart=/usr/local/bin/goatcounter/goatcounter serve -listen :8888 -tls http
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now goatcounter
server {
server_name goat.exu.li;
# Security / XSS Mitigation Headers
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
location / {
# Proxy main traffic
proxy_pass http://172.18.50.105:8888;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
}
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate_key /etc/acme-sh/goat.exu.li/key.pem;
ssl_certificate /etc/acme-sh/goat.exu.li/cert.pem;
}
server {
if ($host = goat.exu.li) {
return 301 https://$host$request_uri;
}
listen 80;
listen [::]:80;
server_name goat.exu.li;
return 404;
}