Deployment guide

AWStats

Overview

AWStats is a long-established open-source log file analyzer. It reads the logs that a web, FTP or mail server already writes and renders them as a detailed graphical report: visitors and visits, pages and hits, bandwidth, entry and exit pages, browsers, operating systems, search engines, referrers, HTTP status codes and robot traffic. Because it analyzes server logs rather than running a tracking script, it needs no client-side JavaScript, sets no cookies and sends nothing to a third party. It counts every request, including those from clients that block conventional analytics, and the data never leaves the instance.

This SecureAnyCloud image is a complete log analysis appliance. It runs AWStats 8.0 behind the Apache web server with mod_cgid on a hardened Ubuntu 24.04 LTS base, patched at build time. It analyzes its own Apache access log out of the box and ships a fully populated demonstration report, so every chart is available as soon as you sign in.

What you get:

  • AWStats 8.0 (GPL-3.0) deployed from the pinned upstream AWSTATS_8_0 release, served by Apache with mod_cgid
  • Two ready-made report configurations: server for this instance's own Apache access log, and demo for an included demonstration dataset
  • A demonstration dataset regenerated on every first boot against the current date, so the report you land on is always populated rather than an empty month
  • awstats-update.timer, a systemd timer that rebuilds the statistics from your logs every ten minutes
  • HTTP Basic authentication in front of the entire reporting site, with a password generated uniquely on each instance's first boot and recorded in a root-only file
  • No shipped default login: no known or blank credential authenticates. The password is rotated to a discarded random value at build time and regenerated uniquely on first boot
  • Browser-triggered log parsing disabled, so no visitor can make the instance parse a log file
  • Statistics data readable by the web tier but writable only by the scheduled updater, so reports cannot be forged through the web
  • apache2.service and awstats-update.timer as enabled systemd units
  • An unauthenticated /healthz endpoint for Azure Load Balancer health probes
  • 24/7 SecureAnyCloud support

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.

Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting size. Step up to Standard_D2s_v3 if you analyze very large log files or many sites.

Configure the network security group (NSG) to allow inbound 22/tcp from your management network and 80/tcp for the reports interface. Add 443/tcp if you terminate TLS on the VM (see "Adding your own domain and TLS" below).

Step 1 - Deploy from the Azure Marketplace

  • In the Azure Portal, choose Create a resource and search for AWStats on Ubuntu 24.04 LTS by SecureAnyCloud.
  • Select Create, then choose your subscription, resource group and region.
  • Set the VM size to Standard_B2s or larger.
  • Under Administrator account, choose SSH public key, set the username to azureuser and paste your public key.
  • Under Inbound port rules, allow SSH (22) and HTTP (80).
  • Select Review + create, then Create.

Step 2 - Deploy from the Azure CLI

az vm image terms accept --urn sac1647283583153:awstats-ubuntu-24-04:default:latest
az vm create \
  --resource-group my-resource-group \
  --name my-awstats-vm \
  --image sac1647283583153:awstats-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

Open the ports that the reports interface needs:

az vm open-port --resource-group my-resource-group --name my-awstats-vm --port 80 --priority 1001

Get the public address of the VM:

az vm show --resource-group my-resource-group --name my-awstats-vm --show-details --query publicIps --output tsv

Step 3 - Confirm the services are running

Connect over SSH, replacing <vm-ip> with the address from the previous step.

ssh azureuser@<vm-ip>

Check that the web server and the log update timer are both running.

systemctl is-active apache2.service awstats-update.timer

Expected output:

active active

Confirm the analyzer version and the configuration it uses:

sudo /usr/bin/perl /opt/awstats/wwwroot/cgi-bin/awstats.pl -version

Expected output:

awstats 8.0 (build 20240604)

Step 4 - Retrieve the per-VM reports password

HTTP Basic authentication protects the reporting site. Each instance generates its own password on first boot and writes it to a root-only file. Read the file as root:

sudo cat /root/awstats-credentials.txt

The file records the address of the reports site, the user name and the password generated for this instance.

AWSTATS_URL=http://<vm-ip>/ awstats.web.user=awstats awstats.web.pass=<AWSTATS_WEB_PASSWORD>

To confirm that the file and the password database exist with the correct ownership and permissions, without printing any secret, run:

sudo stat -c '%n mode=%a owner=%U:%G' /root/awstats-credentials.txt /etc/apache2/awstats.htpasswd

Expected output:

/root/awstats-credentials.txt mode=600 owner=root:root /etc/apache2/awstats.htpasswd mode=640 owner=root:www-data

Step 5 - Sign in to the reports site

Browse to http://<vm-ip>/. When the browser prompts for HTTP Basic credentials, enter awstats as the user name and the value of awstats.web.pass from the credentials file. The landing page lists the two reports available on the instance.

Step 6 - Read the statistics report

Choose Demonstration report to open a fully populated report. The summary at the top shows the reported period and the headline figures: unique visitors, number of visits, pages, hits and bandwidth, with the average visits per visitor and pages per visit alongside. Robot and worm traffic is counted separately as "Not viewed traffic", so it never inflates your visitor numbers.

The navigation strip below the header jumps to each section of the report. Pages-URL shows which pages were viewed most, with the average page size and the number of times each page was the entry or exit point of a visit.

Browsers breaks the traffic down by browser and version. Operating Systems does the same for platforms.

Use the Reported period selector at the top of the report to move between months, or choose Year for the full-year view.

Step 7 - Report on this server's own traffic

The server configuration analyzes this instance's own Apache access log at /var/log/apache2/access.log. It starts nearly empty on a new VM and fills in as the instance receives traffic. awstats-update.timer rebuilds it every ten minutes. To rebuild it immediately, run:

sudo /usr/local/bin/awstats-update server

Then open This server from the landing page, or go straight to http://<vm-ip>/cgi-bin/awstats.pl?config=server.

To confirm the statistics data on disk, list the history files:

sudo ls /var/lib/awstats/demo/

Each file holds one month of history. Read the visit totals for the current month:

sudo awk '/^TotalVisits|^TotalUnique/{printf "%-14s %s\n", $1, $2}' /var/lib/awstats/demo/awstats$(date -u '+%m%Y').demo.txt

Step 8 - Analyze another site or another server

Each site or log source has one configuration file in /etc/awstats. To add another, copy the shipped server configuration and point it at the log you want to analyze:

sudo cp /etc/awstats/awstats.server.conf /etc/awstats/awstats.mysite.conf

Edit the new file and set at least these three directives.

sudo sed -i 's|^LogFile=.*|LogFile="/var/log/apache2/mysite-access.log"|' /etc/awstats/awstats.mysite.conf
sudo sed -i 's|^SiteDomain=.*|SiteDomain="mysite.example.com"|' /etc/awstats/awstats.mysite.conf
sudo sed -i 's|^DirData=.*|DirData="/var/lib/awstats/mysite"|' /etc/awstats/awstats.mysite.conf

Create its data directory and build the first report.

sudo mkdir -p /var/lib/awstats/mysite
sudo /usr/local/bin/awstats-update mysite

The new configuration is then available at http://<vm-ip>/cgi-bin/awstats.pl?config=mysite. To rebuild it automatically alongside the shipped one, add it to the updater invocation in /etc/systemd/system/awstats-update.service.

If the log is not in the Apache combined format, set LogFormat in the configuration file. AWStats ships predefined values (1 for combined, 2 for the older common format, 3 for IIS) and accepts a custom format string for anything else.

Step 9 - No known or default credentials

The image ships with no usable credential. The reports password is set to a random value during the build, re-randomized to a fresh discarded value during image cleanup, and generated uniquely on the first boot of every instance. The following checks show that the site is genuinely protected.

An unauthenticated request to the report is rejected.

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/cgi-bin/awstats.pl?config=demo

Expected output:

401

A request with the wrong password is also rejected.

curl -s -o /dev/null -w '%{http_code}\n' -u awstats:not-the-password http://127.0.0.1/cgi-bin/awstats.pl?config=demo

Expected output:

401

The health endpoint is deliberately open, so an Azure Load Balancer can probe the instance without a credential.

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/healthz

Expected output:

200

Browser-triggered log parsing is disabled in every shipped configuration, so no visitor can make the instance parse a log file.

grep -h '^AllowToUpdateStatsFromBrowser=' /etc/awstats/awstats.demo.conf /etc/awstats/awstats.server.conf

Expected output:

AllowToUpdateStatsFromBrowser=0 AllowToUpdateStatsFromBrowser=0

To change the reports password yourself, run:

sudo htpasswd -B /etc/apache2/awstats.htpasswd awstats

Server components

Component Version Purpose

AWStats 8.0 (build 20240604) Log file analyzer and HTML report generator

Apache HTTP Server 2.4.58 (Ubuntu) Serves the reports and executes the analyzer as a CGI

Perl 5.38.2 Runtime for the analyzer

Ubuntu 24.04 LTS Operating system

Filesystem layout

Path Size Purpose

/ 29 GB Root filesystem

/boot 881 MB Operating system kernel files

/mnt 7.8 GB Azure temporary resource disk

Key directories:

Path Purpose

/opt/awstats The AWStats application, root owned and never writable by the web server

/opt/awstats/wwwroot/cgi-bin/awstats.pl The analyzer and report generator

/opt/awstats/wwwroot/icon Report graph and marker images, served at /awstatsicons

/opt/awstats/docs/LICENSE.TXT The GNU General Public License version 3

/etc/awstats One configuration file per site or log source

/var/lib/awstats/demo History data for the demonstration report

/var/lib/awstats/server History data for this instance's own report

/var/log/apache2/access.log The log the server configuration analyses

/root/awstats-credentials.txt Per-VM reports password, root only

Managing the services

sudo systemctl status apache2.service
sudo systemctl restart apache2.service

To manage the log update timer, use:

systemctl list-timers awstats-update.timer
sudo systemctl start awstats-update.service

To change how often statistics are rebuilt, edit OnUnitActiveSec in /etc/systemd/system/awstats-update.timer, then reload:

sudo systemctl daemon-reload
sudo systemctl restart awstats-update.timer

Adding your own domain and TLS

The image serves plain HTTP on port 80. To put your own hostname and a certificate in front of it, point a DNS A record at the public address of the VM, then run:

sudo apt-get update
sudo apt-get install -y certbot python3-certbot-apache
sudo certbot --apache -d stats.example.com

Certbot rewrites the shipped virtual host to serve HTTPS and installs a renewal timer. Afterward, restrict port 80 in the NSG to the ranges you need, or leave it open so Certbot can complete future HTTP challenges.

Backing up

Back up the statistics history and the configuration:

sudo tar czf awstats-backup.tar.gz /etc/awstats /var/lib/awstats

To restore, extract the archive back over /etc/awstats and /var/lib/awstats, then run sudo /usr/local/bin/awstats-update server.

Troubleshooting

The browser keeps asking for a password. The user name is awstats, not your Azure user. Read the current password with sudo cat /root/awstats-credentials.txt, or set a new one with sudo htpasswd -B /etc/apache2/awstats.htpasswd awstats.

The report says "Never updated". No statistics have been built for the period you are viewing. Build them, then reload the page:

sudo /usr/local/bin/awstats-update server

This server's report is nearly empty. This is expected on a new instance. The server configuration analyzes this VM's own access log, which fills only as the instance receives traffic. The demonstration report is populated immediately, so use it to explore the interface.

The report loads but the graphs are missing. The graph bars are images served from /awstatsicons. Confirm that they are reachable:

curl -s -o /dev/null -w '%{http_code} %{content_type}\n' http://127.0.0.1/awstatsicons/other/hh.png

Expected output:

200 image/png

Checking the web server logs. Errors from the analyzer appear in the Apache error log:

sudo tail -n 30 /var/log/apache2/awstats-error.log

Confirming the first-boot service ran. It generates the password and the demonstration dataset:

systemctl is-active awstats-firstboot.service
sudo journalctl -u awstats-firstboot.service --no-pager -n 20

Security notes

  • Authentication everywhere. The entire reporting site requires authentication. Only /healthz is open, and it returns a fixed string with no instance detail.
  • Per-instance password. The reports password is unique to every instance, generated on first boot and stored in a root-only file. No known or blank credential ships in the image.
  • No browser-triggered parsing. Browser-triggered log parsing is disabled in every shipped configuration, so a visitor can never cause the instance to parse a file. Statistics are rebuilt only by the root-owned scheduled updater.
  • Protected data. The statistics data directory is readable by the web server but writable only by the updater, so reports cannot be altered through the web tier.
  • Fixed configuration path. The analyzer reads configuration only from /etc/awstats. The upstream protection that refuses a caller-supplied configuration directory is left in place.
  • Encrypt web traffic. HTTP Basic credentials are sent with every request. Put TLS in front of the site before exposing it to the internet, and restrict port 80 in the NSG to the networks that need the reports.
  • Keep the VM patched. The base image receives unattended security updates.

Support

SecureAnyCloud provides 24/7 technical support for this product by email at sales@secureanycloud.com and through live chat. We can help with AWStats deployment and configuration, log format definitions for web, FTP and mail server logs, additional sites and log sources, scheduling and troubleshooting log processing, report interpretation, access control and version upgrades. Critical issues receive a one-hour average response time.

AWStats is licensed under the GNU General Public License version 3. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.

Deploy on Azure

Launch AWStats on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure