GoAccess on Ubuntu 24.04 on Azure User Guide
Overview
GoAccess is a fast, open source real-time web-log analyzer. It parses your nginx, Apache or CDN access logs and renders an interactive HTML dashboard - unique visitors, requested files, HTTP status codes, referrers, operating systems, browsers, geo location and bandwidth - that updates live in the browser over a WebSocket as new requests arrive. The cloudimg image compiles the pinned GoAccess 1.10.2 from its official source release, runs it as a dedicated goaccess system user under systemd, and fronts the generated report on port 80 with an nginx reverse proxy that adds a per-VM HTTP Basic Auth gate and proxies the live-update WebSocket. Out of the box it analyzes the box's own nginx access log so the dashboard is populated the moment you sign in; repointing it at your real logs is a one-line change. The persisted parse database, the generated report and the per-VM password file all live on a dedicated Azure data disk, and a unique dashboard password is generated on the first boot of every VM. Backed by 24/7 cloudimg support.
What is included:
- GoAccess 1.10.2 compiled from source (UTF-8, GeoIP2 and OpenSSL support) running as the
goaccesssystemd service - A live-updating HTML dashboard on
:80, fronted by nginx with the GoAccess WebSocket proxied for real-time updates - Per-VM HTTP Basic Auth (user
admin) protecting the dashboard, with a unique password generated on first boot - The dashboard ships analyzing this box's own nginx access log so it is populated on first view
- A dedicated Azure data disk at
/var/lib/goaccessholding the persisted parse database, the report and the password file goaccess.service+nginx.serviceas systemd units, enabled and active- An unauthenticated
/healthzendpoint for Azure Load Balancer health probes - 24/7 cloudimg support
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet + subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a comfortable starting point; GoAccess is light on resources. NSG inbound: allow 22/tcp from your management network, 80/tcp for the dashboard, and 443/tcp if you add TLS. GoAccess serves plain HTTP on port 80; for production use, terminate TLS in front of it with your own domain and switch the live-update WebSocket to secure wss (see Maintenance).
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for GoAccess by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22) and HTTP (80). Review the dedicated data disk on the Disks tab, then Review + create -> Create.
Step 2 - Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name goaccess \
--image <marketplace-image-urn> \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name goaccess --port 80 --priority 1010
Step 3 - Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 - Confirm the services are running
systemctl is-active goaccess.service nginx.service
Both report active. GoAccess parses the log and serves its live-update WebSocket on the loopback connector 127.0.0.1:7890; nginx fronts the HTML report on port 80, adds the per-VM HTTP Basic Auth gate, and proxies the WebSocket at /ws. GoAccess's persisted parse database and the generated report live on the dedicated Azure data disk mounted at /var/lib/goaccess.

Step 5 - Retrieve your dashboard password
nginx protects the GoAccess dashboard with HTTP Basic Auth. The username is admin and a unique password is generated on the first boot of your VM and written to a root-only file:
sudo cat /root/goaccess-credentials.txt
This file contains GOACCESS_USERNAME, GOACCESS_PASSWORD and the GOACCESS_URL to open in a browser. The password is stored on disk only as a bcrypt hash in /var/lib/goaccess/.htpasswd, so no plaintext password ships in the image. Store the password somewhere safe.

Step 6 - Confirm the health endpoint
nginx serves an unauthenticated health endpoint for load balancers and probes:
curl -s http://localhost/healthz
It returns ok. This endpoint never requires authentication, so it is safe for an Azure Load Balancer health probe.
Step 7 - Confirm authentication and the live-update WebSocket
Because a password is set on first boot, an unauthenticated request to the dashboard returns HTTP 401, so nobody reaches your analytics without the password. The following reads the per-VM password from the credentials file and proves the round-trip - unauthenticated is rejected, the correct password authenticates, and the live-update WebSocket upgrades:
PW=$(sudo grep '^GOACCESS_PASSWORD=' /root/goaccess-credentials.txt | cut -d= -f2-)
echo "unauth : $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/)"
echo "authed : $(curl -s -o /dev/null -w '%{http_code}' -u admin:$PW http://127.0.0.1/)"
echo "ws : $(curl -s -m 5 -o /dev/null -w '%{http_code}' -H 'Connection: Upgrade' -H 'Upgrade: websocket' -H 'Sec-WebSocket-Version: 13' -H "Sec-WebSocket-Key: $(openssl rand -base64 16)" http://127.0.0.1/ws)"
It prints unauth : 401, then authed : 200, then ws : 101 (the WebSocket handshake succeeds). The /ws endpoint carries only the incremental parse data that drives the live update; the report page itself stays behind the password.

Step 8 - Sign in to the dashboard
Browse to http://<vm-public-ip>/. Your browser prompts for a username and password: enter admin and the password from Step 5. GoAccess opens on the overview - the General Statistics summary at the top (total requests, valid requests, unique visitors, requested files, referrers, not-found URLs, bandwidth and processing time) followed by each analysis panel. Because the image ships analyzing the box's own nginx log, the dashboard is already populated, and it updates live as new requests arrive.

Step 9 - Read the requests and static-files panels
Scroll down to the Requested Files and Static Requests panels. Each shows the top URLs by hits and visitors, the HTTP method and protocol, the bytes served and the percentage of traffic - the fastest way to see what is actually being requested from your site.

Step 10 - Read the visitor hostnames and operating-system panels
Further down, the Visitor Hostnames and IPs and Operating Systems panels break your traffic down by client IP and by platform (Windows, Linux, macOS, Android, iOS, crawlers), so you can see who is reaching your site and from what. The Browsers panel just below does the same by user agent (Safari, Chrome, Edge, Firefox and more).

Step 11 - Read the referrers and HTTP status-code panels
The Referring Sites panel shows where your traffic comes from, and the HTTP Status Codes panel groups requests by response code (2xx success, 3xx redirection, 4xx client errors, 5xx server errors) so you can spot error spikes at a glance. Add a GeoLite2 database (see Maintenance) to populate the Geo Location panel and map visitors by country.

Step 12 - Repoint GoAccess at your own logs
Out of the box GoAccess analyzes this VM's own nginx access log at /var/log/nginx/access.log. To analyze your real site's logs, edit the log path on the ExecStart line of the service unit and restart:
sudo systemctl edit --full goaccess.service # change the log path on the ExecStart line
sudo systemctl restart goaccess.service
GoAccess reads standard COMBINED log format by default (nginx and Apache both emit it). For a different format, add a matching --log-format to the ExecStart line. You can also point GoAccess at several log files at once by listing them on the command line.
Step 13 - Confirm data lives on the dedicated disk
GoAccess's persisted parse database, the generated report and the per-VM password file are kept under /var/lib/goaccess on the dedicated Azure data disk, so your analytics survive OS changes and the disk can be resized independently:
findmnt /var/lib/goaccess
The mount is backed by a separate Azure data disk captured into the image and re-provisioned on every VM.

Maintenance
- Password: the dashboard password is set on first boot and stored as a bcrypt entry in
/var/lib/goaccess/.htpasswd. To change it, runsudo htpasswd -B /var/lib/goaccess/.htpasswd adminand thensudo systemctl reload nginx. - Your own logs: repoint GoAccess at your real nginx, Apache or CDN access logs by editing the log path on the
ExecStartline ofgoaccess.service(Step 12). The persisted parse database under/var/lib/goaccesskeeps historical data across restarts via--persist/--restore. - GeoIP: the binary is built with GeoIP2 support, but no GeoLite2 database ships (MaxMind's licence is not redistributable). Download a GeoLite2-Country or GeoLite2-City
.mmdbfrom MaxMind and add--geoip-database /path/to/GeoLite2-City.mmdbto theExecStartline to populate the geo panel. - TLS and secure WebSocket: GoAccess serves plain HTTP on port 80 with a
ws://live-update WebSocket. For production, front it with TLS (for example certbot with your own domain), then set the report's--ws-urltowss://<your-domain>/wsand proxy/wsover:443so live updates flow over a secure WebSocket. - Real-time WebSocket URL: GoAccess bakes the WebSocket URL into the report on first boot from the VM's public IP. If the VM's public IP changes, re-run first boot (
sudo rm /var/lib/cloudimg/goaccess-firstboot.done && sudo systemctl start goaccess-firstboot.service) or edit/etc/goaccess/goaccess.envand restartgoaccess.service. - Storage: all GoAccess state lives under
/var/lib/goaccesson the data disk; back up that volume to protect your persisted analytics. - Security patches: unattended-upgrades remains enabled so the OS continues to receive security updates automatically.
Support
cloudimg provides 24/7 expert support for this image. Contact support@cloudimg.co.uk.