{ pkgs, lib, ... }: let src = pkgs.fetchurl { url = "https://github.com/zgoat/goatcounter/releases/download/v2.0.4/goatcounter-v2.0.4-linux-amd64.gz"; sha256 = "1h7hv5lk2gm3klbfbgwfa7xn31az9zmlryd8bqqq38lp5r56cpb4"; }; goatcounter-bin = pkgs.runCommand "goatcounter-bin" {} '' mkdir -p $out/bin gunzip -c ${src} > $out/bin/goatcounter chmod +x $out/bin/goatcounter ''; goatcounter-token = pkgs.privateValue "" "goatcounter-token"; in { environment.systemPackages = [goatcounter-bin]; users = { users.goatcounter = { isSystemUser = true; group = "goatcounter"; }; groups.goatcounter = {}; }; services.postgresql = { enable = true; ensureUsers = [ { name = "goatcounter"; ensurePermissions = { "DATABASE goatcounter" = "ALL PRIVILEGES"; }; } ]; ensureDatabases = ["goatcounter"]; }; services.nginx = { appendHttpConfig = lib.mkAfter '' log_format vcombined '$host $remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent"'; access_log /run/nginx/access.log vcombined; ''; virtualHosts."analytics.maralorn.de" = { enableACME = true; forceSSL = true; locations."/".proxyPass = "http://localhost:8081/"; }; }; systemd.services = { goatcounter = { requires = ["postgresql.service"]; after = ["postgresql.service"]; serviceConfig = { User = "goatcounter"; ExecStart = "${goatcounter-bin}/bin/goatcounter serve -db 'postgresql://host=/run/postgresql dbname=goatcounter' -listen *:8081 -tls http -automigrate"; WatchdogSignal = "SIGTERM"; WatchdogSec = "20m"; Restart = "always"; }; wantedBy = ["multi-user.target"]; }; goatcounter-feeder = { requires = ["goatcounter.service"]; after = ["goatcounter.service"]; serviceConfig = { User = "nginx"; Type = "oneshot"; }; script = '' (cat /run/nginx/access.log && truncate --size 0 /run/nginx/access.log) |\ sed 's/\([^ ]*\) \(.*"[^ ]* \/\)/\2\1\//; s/ \(\/.*\)?[^ ]* / \1 /' |\ GOATCOUNTER_API_KEY=${goatcounter-token} ${goatcounter-bin}/bin/goatcounter import -follow -site http://localhost:8081 - -format combined \ -exclude '!method:GET' \ -exclude 'remote_addr:2a02:c207:3002:7584:' \ -exclude 'remote_addr:glob:::1' \ -exclude 'remote_addr:127.0.0.1' \ -exclude redirect ''; }; }; systemd.timers = { goatcounter-feeder = { timerConfig.OnCalendar = "minutely"; wantedBy = ["timers.target"]; }; }; }