2023-03-16 11:07:11 +01:00
|
|
|
---
|
|
|
|
title: GoatCounter
|
|
|
|
visible: true
|
|
|
|
---
|
|
|
|
|
|
|
|
[toc]
|
|
|
|
|
|
|
|
GoatCounter is an Open Source Analytics written in Go.
|
|
|
|
|
2023-03-16 13:54:00 +01:00
|
|
|
## Why self host?
|
|
|
|
|
|
|
|
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](https://www.goatcounter.com/help/gdpr) does not require a GDPR consent notice.
|
|
|
|
|
2023-03-16 11:07:11 +01:00
|
|
|
## Installation
|
|
|
|
|
|
|
|
GoatCounter is distributed as a statically compiled binary.
|
|
|
|
Releases can be found on [GitHub](https://github.com/arp242/goatcounter/releases)
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
```sh
|
|
|
|
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.
|
|
|
|
|
|
|
|
```sh
|
|
|
|
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.
|
|
|
|
|
|
|
|
```sh
|
|
|
|
./goatcounter serve -listen :8888 -tls http
|
|
|
|
```
|
|
|
|
|
|
|
|
### Create site
|
|
|
|
|
|
|
|
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
|
|
|
|
```
|
|
|
|
|
|
|
|
```sh
|
|
|
|
./goatcounter db create site -vhost {URL} -user.email {EMAIL}
|
|
|
|
```
|
|
|
|
|
|
|
|
### Systemd Service
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
```systemd
|
|
|
|
[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
|
|
|
|
```
|
|
|
|
|
|
|
|
```sh
|
|
|
|
systemctl daemon-reload
|
|
|
|
systemctl enable --now goatcounter
|
|
|
|
```
|
|
|
|
|
|
|
|
### Nginx config
|
|
|
|
|
|
|
|
```nginx
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
```
|