--- title: GoatCounter visible: true --- [toc] GoatCounter is an Open Source Analytics written in Go. ## 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. ## 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; } ```