Google Analytics tells you what it wants you to see. Your Apache access log already knows every bot, every slow page, and every weird 404 someone hammered at 3 a.m. Most teams never look at it because `tail -f` is not a dashboard.
GoAccess is the small tool that fixes that gap. ~21k GitHub stars, MIT license, written in C by Gerardo Orellana and contributors. Point it at an nginx or Apache log (or CloudFront, ALB, Caddy JSON, Traefik, and a pile of other formats) and you get live stats in the terminal or a self-contained HTML report that updates over WebSockets. No tracking pixel on your site, no third-party cookie banner for analytics alone.
What it actually does
GoAccess is a log analyzer, not a tag manager. It reads what your web server already wrote: hits, unique visitors, bandwidth, status codes, referrers, user agents, virtual hosts, response times, UTM parameters pulled from URLs, and TLS cipher details when your log format includes them.
Two modes matter in practice:
- Terminal UI — ncurses dashboard over SSH when you need answers in thirty seconds during an incident.
- HTML / JSON / CSV — batch or real-time reports; the live HTML view refreshes about once a second and ships its own WebSocket stack (gwsocket) so you are not wiring Node just to watch traffic.
Recent releases lean into ops and security: bot and AI-crawler classification, ASN mapping with --exclude-asn to drop noisy networks as logs parse, JWT auth on WebSocket connections, and on-disk persistence so you can incrementally process huge logs without re-reading from byte zero every time.
Dependencies stay minimal — build with GeoIP (MaxMind DB) for country maps, zlib for compression, and you are done. Docker images exist if you would rather mount /var/log/nginx and a config file than compile on the host.
Why self-host log analytics?
Privacy by architecture. Visitor IPs and URLs stay on your box. For Canadian sites handling personal data in query strings or logged paths, keeping analytics in the same jurisdiction as the web root is simpler than exporting events to a US SaaS.
It works when JavaScript fails. Ad blockers do not strip server logs. API traffic, static assets, and old browsers still show up.
Cost and retention. There is no per-seat fee. Keep twelve months of rolled logs on disk and replay them; GA4 export will not give you that nostalgia trip for free.
Incident response. Spikes, scan patterns, brute-force probes, and "why is this one PHP script slow" show up in response-time panels while the log is still hot — not after tomorrow's warehouse job.
GoAccess complements privacy-first JS analytics (Plausible, Matomo, etc.) rather than replacing them: logs see every request; tag-based tools see configured page views. Many teams run both; some run only logs because that is enough.
What running it takes
On a typical Swift Host stack — Apache or nginx on Ubuntu — install from the official deb repo if distro packages lag, or pull the release tarball. Basic flow:
- Pick log format (
COMBINEDfor nginx/apache combined logs is the usual default). - Run once:
goaccess /var/log/nginx/access.log -o report.html --log-format=COMBINED - For live HTML: enable real-time output and WebSocket settings in
goaccess.conf, bind behind nginx with TLS, and restrict the dashboard (basic auth, VPN, or JWT as documented).
Resource use is modest compared to ELK or ClickHouse — GoAccess uses in-memory hash tables tuned for single-host analysis. Very large logs benefit from persistence flags and log rotation discipline; do not point it at an unrotated multi-terabyte file on a 1 GB VM and expect joy.
GeoIP needs a current MaxMind (or compatible) database on disk. Map outlines in the HTML report use Natural Earth; country totals still come from GeoIP lookup, not the map artwork.
Who it's for (and who should skip it)
Good fit: solo developers, agencies hosting client sites on VPS, anyone who SSHs into servers and wants traffic without opening another SaaS tab, security-minded shops watching crawlers and ASN noise.
Maybe skip it: if you need funnel analysis, cohort retention, and marketing integrations, a product analytics suite will hurt less. Multi-tenant SaaS with centralized log pipelines already in Loki or Datadog may duplicate effort. If nobody will lock down the HTML dashboard, exposing live logs to the public internet is worse than no dashboard.
Hosting it in Canada
GoAccess often runs on the same Canadian VPS that serves the site — read local logs, publish the HTML report on an admin-only vhost, no cross-border analytics export required.
Ask us about log rotation, a private stats subdomain, and TLS in front of the WebSocket port if you want a setup checklist without shipping logs to a vendor.
Want traffic visibility without another subscription? Talk with Swift Host — we are in St. Albert and actually answer the phone.