Quick Reference

Cheatsheets

Practical command references for Linux, networking, servers, containers, databases, and more.

Cheatsheet#goaccess

GoAccess

goaccess is an open-source real-time web log analyzer and interactive viewer that runs in a terminal or serves live HTML reports via WebSockets. It parses web server logs (Nginx, Apache, Caddy, Cloudflare, AWS CloudFront) fast with minimal CPU/RAM overhead.


Installation

# Debian / Ubuntu (Official repository for latest version)
wget -O - https://deb.goaccess.io/gnupg.key | gpg --dearmor | sudo tee /usr/share/keyrings/goaccess.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/goaccess.gpg arch=$(dpkg --print-architecture)] https://deb.goaccess.io/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/goaccess.list
sudo apt update && sudo apt install goaccess -y
 
# RHEL / Rocky Linux / AlmaLinux (EPEL)
sudo dnf install epel-release -y
sudo dnf install goaccess -y
 
# Alpine Linux
apk add goaccess
 
# Docker
docker run --rm -it -v "/var/log/nginx:/var/log/nginx" allinurl/goaccess:latest \
  -f /var/log/nginx/access.log --log-format=COMBINED

Quick Start & Basic Usage

# Interactive TUI mode (prompts for log format if not specified)
goaccess /var/log/nginx/access.log
 
# Interactive TUI mode with predefined COMBINED format
goaccess /var/log/nginx/access.log --log-format=COMBINED
 
# Generate a static HTML report
goaccess /var/log/nginx/access.log -o /var/www/html/report.html --log-format=COMBINED
 
# Generate JSON or CSV report
goaccess /var/log/nginx/access.log -o report.json --log-format=COMBINED
goaccess /var/log/nginx/access.log -o report.csv --log-format=COMBINED

Interactive Terminal UI (TUI) Keybindings

When running goaccess directly in the terminal:

KeyAction
F1 / hOpen main help menu
F5Redraw / refresh dashboard
qQuit GoAccess or close current expanded module
0 - 9Expand / zoom into module 1 through 10
Shift + 0Expand module 10
Tab / Shift + TabNavigate forward / backward through modules
sOpen sort options dialog for active module
/Search within active module (supports regex)
nJump to next search match
cOpen / change color scheme palette
o / EnterExpand / collapse selected module

Log Formats & Predefined Presets

GoAccess supports built-in presets via --log-format=<NAME>:

  • COMBINED : Standard Nginx / Apache combined log format.
  • VCOMBINED : Combined format prefixed with Virtual Host ($host).
  • COMMON : Common Log Format (CLF).
  • CADDY : Caddy web server standard logs.
  • CLOUDFRONT : Amazon CloudFront distributions.
  • CLOUDFLARE : Cloudflare raw log exports.
  • SQUID : Squid proxy native log format.
  • AWS_ALB : AWS Application Load Balancer access logs.

Custom Log Format Specifiers

When your web server uses a custom log_format, match it using these specifiers:

SpecifierDescription
%hRemote client host (IP address / hostname)
%dDate matching --date-format (e.g. %d/%b/%Y)
%tTime matching --time-format (e.g. %H:%M:%S)
%rRequest line (GET /index.html HTTP/1.1)
%mRequest method only (GET, POST)
%URequested URL path (without query string)
%qQuery string (e.g. ?id=123)
%HRequest protocol (HTTP/1.1, HTTP/2.0)
%sHTTP status code (200, 404, 502)
%bSize of response in bytes sent to client
%RHTTP Referer header
%uUser-Agent string
%vVirtual host name (server_name / $host)
%TRequest execution time in seconds (with ms resolution)
%DRequest execution time in microseconds
%^Ignore this field / token

1. Standard Nginx Combined + Request Time

If your Nginx log has $request_time appended to the end:

# Nginx nginx.conf
log_format custom '$remote_addr - $remote_user [$time_local] '
                  '"$request" $status $body_bytes_sent '
                  '"$http_referer" "$http_user_agent" $request_time';

Parse it with GoAccess:

goaccess /var/log/nginx/access.log \
  --log-format='%h - %^ [%d:%t %^] "%r" %s %b "%R" "%u" %T' \
  --date-format='%d/%b/%Y' \
  --time-format='%H:%M:%S'

2. Cloudflare Proxy Logs (CF-Connecting-IP)

When Nginx sits behind Cloudflare, the first IP is Cloudflare's proxy IP, while the real visitor IP is in $http_cf_connecting_ip:

# Nginx log_format with Cloudflare real IP
log_format cloudflare '$http_cf_connecting_ip - $remote_user [$time_local] '
                      '"$request" $status $body_bytes_sent '
                      '"$http_referer" "$http_user_agent"';

Parse using:

goaccess /var/log/nginx/access.log \
  --log-format='%h - %^ [%d:%t %^] "%r" %s %b "%R" "%u"' \
  --date-format='%d/%b/%Y' \
  --time-format='%H:%M:%S'

Real-Time HTML Dashboard (WebSockets)

GoAccess can run an embedded WebSocket server that updates the browser dashboard live as incoming log lines are written.

goaccess /var/log/nginx/access.log \
  -o /var/www/html/report.html \
  --log-format=COMBINED \
  --real-time-html \
  --ws-url=wss://analytics.example.com:443/ws \
  --port=7890

Nginx Reverse Proxy for Secure WebSocket (wss://)

Proxy both the HTML report and the WebSocket port (7890) through Nginx with SSL termination:

server {
    listen 443 ssl http2;
    server_name analytics.example.com;
 
    ssl_certificate /etc/letsencrypt/live/analytics.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/analytics.example.com/privkey.pem;
 
    # Protect dashboard with basic authentication or IP allowlist
    auth_basic "Protected Analytics";
    auth_basic_user_file /etc/nginx/.htpasswd;
 
    # Serve static HTML report generated by GoAccess
    location / {
        root /var/www/html;
        index report.html;
    }
 
    # Proxy WebSocket updates to GoAccess daemon
    location /ws {
        proxy_pass http://127.0.0.1:7890;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_read_timeout 86400s;
        proxy_send_timeout 86400s;
    }
}

Processing Multiple & Compressed Logs

Analyze rotated .gz logs together with the current active log:

# Decompress and feed all rotated logs into GoAccess via pipe
zcat -f /var/log/nginx/access.log* | goaccess - -o /var/www/html/report.html --log-format=COMBINED
 
# Read multiple uncompressed files directly
goaccess /var/log/nginx/access.log /var/log/nginx/access.log.1 -o report.html --log-format=COMBINED
 
# Analyze remote logs live via SSH without downloading the file
ssh [email protected] "cat /var/log/nginx/access.log" | goaccess - --log-format=COMBINED

Filtering, Privacy & Performance Tuning

# Exclude office / monitoring IP addresses from metrics
goaccess access.log --exclude-ip=192.168.1.50 --exclude-ip=10.0.0.0/8
 
# Anonymize client IP addresses (GDPR compliance: masks last octet for IPv4)
goaccess access.log --anonymize-ip --log-format=COMBINED
 
# Ignore web crawlers, bots, and spiders
goaccess access.log --ignore-crawlers --log-format=COMBINED
 
# Ignore specific HTTP status codes (e.g. ignore 301/302 redirects)
goaccess access.log --ignore-status=301 --ignore-status=302
 
# Filter logs by date range before processing
sed -n '/01\/Aug\/2026/,/08\/Sep\/2026/p' access.log | goaccess - --log-format=COMBINED
 
# Track only specific virtual host from multi-site log
goaccess access.log --log-format=VCOMBINED | grep 'example.com' | goaccess -

Data Persistence (On-Disk Storage)

By default, GoAccess holds data in RAM. For large logs over long periods, use on-disk persistence:

# Store incremental data to disk
goaccess access.log --persist --db-path=/var/lib/goaccess/ --log-format=COMBINED
 
# Restore previous data and append new log lines
goaccess access.log --restore --persist --db-path=/var/lib/goaccess/ --log-format=COMBINED
 
# Keep only the last N days of data in database
goaccess access.log --persist --restore --db-path=/var/lib/goaccess/ --keep-last=30

Systemd Service for Live Background Daemon

Create /etc/systemd/system/goaccess.service to keep real-time reporting running continuously in the background:

[Unit]
Description=GoAccess Real-Time Web Log Analyzer
After=network.target nginx.service
 
[Service]
Type=simple
User=www-data
Group=www-data
ExecStart=/usr/bin/goaccess /var/log/nginx/access.log \
  -o /var/www/html/report.html \
  --log-format=COMBINED \
  --real-time-html \
  --addr=127.0.0.1 \
  --port=7890 \
  --ws-url=wss://analytics.example.com/ws
Restart=always
RestartSec=5s
 
[Install]
WantedBy=multi-user.target

Enable and start the service:

sudo systemctl daemon-reload
sudo systemctl enable --now goaccess
sudo systemctl status goaccess

Automated Daily Reports via Cronjob

If you prefer static snapshots rather than running a constant WebSocket daemon:

# Edit crontab
sudo crontab -e
 
# Generate fresh report daily at midnight
0 0 * * * zcat -f /var/log/nginx/access.log* | goaccess - -o /var/www/html/report.html --log-format=COMBINED >/dev/null 2>&1