Understanding web traffic is critical for assessing server performance and identifying usage patterns. GoAccess is a free, open-source tool you can use to process Nginx logs to generate structured HTML reports and gain basic insights for your website.

TL;DR

  1. Install goaccess
  2. Use zcat to consume nginx access.log files that were compressed by logrotate and pipe them to the goaccess command: zcat /var/log/nginx/access.log.*.gz | goaccess - --log-format=COMBINED -o /your/output/dir/index.html
  3. create a systemd service and timer file to execute the command
  4. Use nginx with http-auth to make the generated report available for viewing in the browser

Automated GoAccess Reports - Step-by-Step Quick-Guide

  1. Install goaccess (Ubuntu): sudo apt install goaccess
  2. Tryout the command manually: zcat /var/log/nginx/access.log.*.gz | goaccess - --log-format=COMBINED -o /your/output/dir/index.html
  3. Create systemd service file: touch /etc/systemd/system/goaccessreport.service

goaccesreport.service content:

[Unit]
Description=GoAccess report generation

[Service]
Type=oneshot
ExecStart=/usr/bin/bash -c 'zcat /var/log/nginx/access.log*.gz | goaccess - --no-progress --log-format=COMBINED -o /your/output/dir/index.html'
User=www-data
Group=www-data

[Install]
WantedBy=multi-user.target
  1. Make sure /your/output/dir is owned by the user www-data (because we run the service as user www-data)
  2. touch /etc/systemd/system/goaccessreport.timer

goaccessreport.timer content:

[Unit]
Description=Run GoAccess service daily at 8 AM

[Timer]
OnCalendar=08:00
Persistent=true

[Install]
WantedBy=timers.target
  1. Reload the daemon: sudo systemctl daemon-reload
  2. Enable the timer: sudo systemctl enable goaccessreport.timer
  3. Start the timer: sudo systemctl start goaccessreport.timer
  4. Check if you see your timer: systemctl list-timers
  5. Tryout your service manually: sudo systemctl start goaccessreport
  6. Configure nginx with http-auth so you can view your report:
location /statistics {
       alias /your/output/dir;
       auth_basic "Admin Area";
       auth_basic_user_file /etc/nginx/.htpasswd;
       }

Systemd Service and Timer

Systemd is an init system and service manager used in many Linux distributions to manage system processes. It provides tools for starting, stopping, and automating services efficiently. You can think of systemd timers as the modern way to schedule a job.

If you run systemctl timers-list you will see timers already defined by the system you are running on. For each .timer file (mostly located at /etc/systemd/system) a matching .service file exists (see also: https://wiki.archlinux.org/title/Systemd/Timers).

A Systemd service is a unit configuration file that defines, how a process should be executed and managed by Systemd. In our case, the service is responsible for running GoAccess to process Nginx logs and generate an HTML report.

Understanding goaccessreport.service:

SectionDirectiveDescription
[Unit]Description=...Provides a short description for the service.
[Service]Type=oneshotSpecifies that the service runs once and exits, rather than staying active like a typical daemon.
ExecStart=...Defines the command to execute when the service starts. It decompresses Nginx log files using zcat, passes them to GoAccess for processing, and saves the output as an HTML report.
User=www-dataRuns the service as the www-data user (commonly used for web services), ensuring appropriate permissions.
Group=www-dataEnsures the process runs within the www-data group for security and access control.
[Install]WantedBy=multi-user.targetTies the service to the multi-user.target, allowing it to be started manually or by other system dependencies.

Understanding our goaccessreport.timer:

SectionDirectiveDescription
[Unit]Description=...Provides a short description for the timer.
[Timer]OnCalendar=08:00Defines the schedule using calendar syntax, meaning the timer triggers the service every day at 8 AM. Alternative formats allow for different scheduling patterns (e.g., weekly, hourly, or specific dates).
Persistent=trueEnsures that if the system was down at the scheduled time, the service will run as soon as possible after the system comes back online. This prevents the task from being skipped due to reboots or downtime.
[Install]WantedBy=timers.targetEnsures the timer is enabled and managed under timers.target, which is systemd’s mechanism for handling scheduled tasks.

Nginx with http-auth

If you are new to Nginx, check out the official beginners guide or this explanatory YT video by TechWorld with Nana. In our use case, Nginx is configured to make the GoAccess reports available via a web interface.

To restrict access, HTTP basic authentication is enabled, requiring users to enter a username and password before viewing the reports. This ensures that sensitive traffic data remains protected while still allowing authorized users to analyze access logs conveniently through their browser.

Setting up http-auth: Generate a .htpasswd file

You can generate the password-file on your server, but you can also generate it locally and upload it. The command needed to generate it is called “htpasswd”. Depending on your OS, it might be included in a different package. For me (using Arch Linux) I had to install “apache”. The official nginx documentation states to use “apache2-utils” for Ubuntu and “httpd-tools” when running on RHEL, CentOS or Oracle Linux.

After you installed the package providing the util, you can run htpasswd -c /your/out/dir/.htpasswd your_user. You will then be asked to enter the password. In the resulting file, you will see an entry like: “your_user:hashed-password-you-just-entered”.

Copy that file to your server. I chose the location /etc/nginx because the file will be used by nginx so that seemed to be a fitting location.

Configure nginx to use the .htpasswd-file

	location /statistics {
		alias /your/output/dir;
		auth_basic "Admin Area";
		auth_basic_user_file /etc/nginx/.htpasswd;
	}

After changing the nginx configuration, you have to reload the service so that changes take effect:
sudo systemctl reload nginx

And with that being done when you access your-blog.domain/statistics you should be asked for the user and password you defined in the .htpasswd file and only be shown the GoAccess HTML report after entering a valid user-password combination.

GoAccess HTML-Report - what insights can I gain?

GoAccess Dashboard with open side menu. The currently active panel is “overall analyzed requests” The report generated by goaccess provides you with basic yet useful insights, such as:

  • crawler requests -> if crawlers cause a lot of load you can identify the most aggressive ones and take actions to block them
  • 404 URLs -> if you migrated from another technology, like I did, you might want to check that you did not forget some redirects
  • time distribution -> analyzing requests over time can give you different valuable insights. Maybe you addressed issues uncovered by the Google Search Console or improved performance and can pinpoint a change in the request volume. Maybe you were the first to write on trending topics and can deduce an increase or decrease in traffic based on when you publish articles and promote them (i.e. on social media)