GoAccess (goaccess.io, github) is a tool that analyses server logs and gives real-time
statistics on network traffic.
It took me some time to figure out exactly how to get the real-time websocket
server working through Nginx, so I’m just sharing my configuration here.
Install via your package manager, e.g. sudo pacman -S goaccess on Arch.
The result will look like this.
1 Nginx setup
First we make sure that nginx logs all requests. I have a bunch of nginx
server blocks, so I’m logging the curiouscoding.nl logs to their own file:
1
2
3
4
5
6
7
8
9
10
11
12
13
# /etc/nginx/sites-available/curiouscoding.nl
server{server_namecuriouscoding.nl;root/srv/nginx/...;listen[::]:80;listen[::]:443sslhttp2;include/etc/nginx/ssl_settings.conf;# Write logs here
access_log"/var/log/nginx/access-curiouscoding.log";...}
Code Snippet 1:
Nginx access log setup.
2 GoAccess configuration
Now we’ll do some configuration to parse nginx logs. I’m not quite sure all
of these are strictly needed, but this is what I currently have. See the full
file on your system for docs for each option.
# /etc/goaccess/goaccess.conf# nginx uses the combined format by default. Important!log-format COMBINED# The nginx logs can be found here.log-file /var/log/nginx/access-curiouscoding.log# default time & date formatstime-format %H:%M:%Sdate-format %d/%b/%Ydatetime-format %d/%b/%Y:%H:%M:%S %z# Some UI tweaks (most are defaults)config-dialog falsehl-header truejson-pretty-print falseagent-list falsehttp-method yeshttp-protocol nono-query-string falseno-term-resolver false444-as-404 false4xx-to-unique-count falseall-static-files truebrowsers-file /etc/goaccess/browsers.list# Show the initial 'visitors per day' by hour.date-spec hrdouble-decode false# Eanble some additional panelsenable-panel REFERRERSenable-panel GEO_LOCATION# Show the 'time distribution' graph per 10-minutes rather than hours.hour-spec minignore-crawlers truecrawlers-only falseunknowns-as-crawlers falseignore-statics panelsreal-os true
Code Snippet 2:
GoAccess configuration file.
You should now be able to run goaccess --output /tmp/index.html on your
server. You can either cp it somewhere into the public/ directory of your
site or scp it to your local machine to view it in a browser.
3 Systemd setup
We’d like to have goaccess running in the background.
First, create the goaccess user:
1
sudo useradd goaccess --system --no-create-home
Then, create /srv/nginx/goaccess, owned by the goaccess user, which is where
we’ll host the static index.html page.
This should now write /srv/nginx/goaccess/index.html.
4 Serving the static file
Now we want to view /srv/nginx/goaccess/index.html. Add the following server
block:
1
2
3
4
5
6
7
8
9
10
11
12
13
# /etc/nginx/sites-available/goaccess
server{# (I'm actually hosting it somewhere else.)
server_namegoaccess.curiouscoding.nl;root/srv/nginx/goaccess/;listen[::]:80;listen[::]:443sslhttp2;include/etc/nginx/ssl_settings_wildcard.conf;# Add http authentication to it.
auth_basic"Authenticationrequired";auth_basic_user_file/etc/nginx/.htpasswd;}
Now sudo systemctl restart nginx and go to goaccess.curiouscoding.nl to see
the generated report.
5 Serving live statistics
By default, we just see the generated index.html file, and we have to restart
goaccess.service to regenerate it. But GoAccess also supports a websocket
server that can show real-time statistics. This was slightly more tricky to get
working, but ends up being very nice!
Heads-up: while the static page shows up to 366 table rows per panel, the live
view only shows up to 50 to save data. See
this issue for possible workarounds if you want to see the full data anyway.
(To work around this, I created a second goaccess-staticone-shot systemd service that drops
the --realtime-html flag and the Restart and RestartSec lines, that writes
to .../index-static.html.)
First, make sure that you add the --real-time-html flag to the systemd
service, as I already did in Code Snippet 3.
Then, update the goaccess configuration with:
1
2
3
4
5
6
7
# /etc/goaccess/goaccess.conf# The goaccess server listens on this port.port 7890# (Not actually sure we need this.)pid-file /var/run/goaccess.pid# The browser can find the websocket server here.ws-url wss://goaccess.curiouscoding.nl:443/ws
Code Snippet 4:
Updated goaccess configuration for websocket server.
Also update the nginx configuration for goaccess.curiouscoding.nl like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# /etc/nginx/sites-available/goaccess
server{server_namegoaccess.curiouscoding.nl;...# Redirect requests to /ws to local port 7890, where goaccess is listening.
# Note: No trailing slash after /ws!
location/ws{proxy_connect_timeout7d;proxy_send_timeout7d;proxy_read_timeout7d;proxy_passhttp://localhost:7890;proxy_set_headerConnection"upgrade";proxy_set_headerConnection"keep-alive";proxy_http_version1.1;# Drop the leading /ws from the passed-through url.
rewrite^/ws(.*)/$1break;}}
Now sudo systemctl restart nginx, and go to goaccess.curiouscoding.nl. You
should see a green dot in the top left indicating the websocket server is working.
6 GeoIP database
If you want to see where your users are coming from, you’ll need a database for it.
As linked in goaccess.conf, I went to
https://db-ip.com/db/download/ip-to-city-lite and downloaded the ‘IP to city
lite MMDB’. Copy that to /usr/local/share/GeoIP, and then add the following
to the goaccess configuration:
1
2
3
# /etc/goaccess/goaccess.conf# Make sure to update the date to your version.geoip-database /usr/local/share/GeoIP/dbip-city-lite-2024-12.mmdb
Now sudo systemctl restart goaccess and refresh goaccess.curiouscoding.nl.