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_0release, served by Apache withmod_cgid - Two ready-made report configurations:
serverfor this instance's own Apache access log, anddemofor 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.serviceandawstats-update.timeras enabled systemd units- An unauthenticated
/healthzendpoint 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
azureuserand 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 StandardOpen the ports that the reports interface needs:
az vm open-port --resource-group my-resource-group --name my-awstats-vm --port 80 --priority 1001Get the public address of the VM:
az vm show --resource-group my-resource-group --name my-awstats-vm --show-details --query publicIps --output tsvStep 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.timerExpected output:
active activeConfirm the analyzer version and the configuration it uses:
sudo /usr/bin/perl /opt/awstats/wwwroot/cgi-bin/awstats.pl -versionExpected 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.txtThe 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.htpasswdExpected output:
/root/awstats-credentials.txt mode=600 owner=root:root /etc/apache2/awstats.htpasswd mode=640 owner=root:www-dataStep 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 serverThen 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.txtStep 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.confEdit 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.confCreate its data directory and build the first report.
sudo mkdir -p /var/lib/awstats/mysite
sudo /usr/local/bin/awstats-update mysiteThe 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=demoExpected output:
401A 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=demoExpected output:
401The 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/healthzExpected output:
200Browser-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.confExpected output:
AllowToUpdateStatsFromBrowser=0 AllowToUpdateStatsFromBrowser=0To change the reports password yourself, run:
sudo htpasswd -B /etc/apache2/awstats.htpasswd awstatsServer 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.serviceTo manage the log update timer, use:
systemctl list-timers awstats-update.timer
sudo systemctl start awstats-update.serviceTo 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.timerAdding 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.comCertbot 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/awstatsTo 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 serverThis 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.pngExpected output:
200 image/pngChecking the web server logs. Errors from the analyzer appear in the Apache error log:
sudo tail -n 30 /var/log/apache2/awstats-error.logConfirming 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 20Security notes
- Authentication everywhere. The entire reporting site requires authentication. Only
/healthzis 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
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 turns them into a graphical HTML statistics report: visits and unique visitors, pages and hits, bandwidth, entry and exit pages, browsers, operating systems, search engines, referrers, HTTP status codes, file types and robot traffic. Because it processes server logs rather than running a browser tracking script, it needs no cookies and no third-party service, and it reports on every request, not only on visitors who allow client-side analytics.
This image is a complete, ready-to-use log analysis appliance. It runs AWStats behind the Apache web server with mod_cgid on Ubuntu 24.04 LTS. The entire reporting site is protected by HTTP Basic authentication from the moment the instance starts. Two reports are configured: a demonstration report that is populated on first boot, and a server report on the instance's own traffic.
What you get:
- Apache configured to execute the analyzer, with the Perl modules AWStats needs, and the icon and data directories wired up so every graph draws correctly
- A systemd timer that reprocesses this instance's own web server log every ten minutes
- HTTP Basic authentication in front of the whole reporting site, including the report CGI, with a report password generated uniquely on first boot and written to a root-only file, so no shared or default password ships in the image
- A demonstration report that analyzes a synthetic access log, regenerated against the current date on first boot, so it is fully populated and explorable as soon as you sign in
- A server report that analyzes this instance's own
/var/log/apache2/access.log, so the appliance reports on its real traffic immediately and grows as requests arrive
Prerequisites
Before you deploy this image, you need:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region for SSH access to the instance
- A VPC and subnet in the target Region, with a security group that allows inbound port 22 from your management network and inbound ports 80 and 443 from the networks you will view the reports from
- The AWS CLI (version 2) installed locally, if you plan to deploy from the command line
Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service and select Launch instance. Under Application and OS Images, choose AWS Marketplace AMIs and search for AWStats. Select the SecureAnyCloud listing, choose Select, then choose Continue on the subscription summary.
Pick an instance type of m5.large or larger. Choose your EC2 key pair under Key pair (login). Under Network settings, select your VPC and subnet, then create or select a security group that allows inbound port 22 from your management network and inbound ports 80 and 443 from the networks you will view the reports from. Leave the root volume at the default size or larger.
Select Launch instance. First-boot initialization takes a few seconds after the instance state becomes Running and the status checks pass. During that time, the per-instance report password is generated and the demonstration dataset is rebuilt against the current date.
Launch the Instance from the AWS CLI
The following command launches an instance from the SecureAnyCloud AWStats Marketplace AMI into an existing subnet and security group. Replace <ami-id> with the AMI ID shown on the Marketplace listing, <key-name> with your EC2 key pair name and <subnet-id> with your subnet ID. Replace <security-group-id> with a security group that opens ports 22 and 80, plus 443 if you will terminate TLS, as described above.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--metadata-options "HttpTokens=required,HttpEndpoint=enabled" \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=awstats}]'Connecting to Your Instance
Connect over SSH on port 22 with the private key for the EC2 key pair you selected at launch. The login user depends on the operating system variant you launched.
OS variant SSH login user
Ubuntu 24.04 LTS ubuntu
For example, on the Ubuntu variant, run:
ssh -i /path/to/your-key.pem ubuntu@<public-ip>Retrieve Your Report Password
HTTP Basic authentication protects the whole reporting site, with the user name awstats. The password is generated uniquely for your instance on first boot and written to /root/awstats-credentials.txt, which only root can read. Retrieve it over SSH:
sudo cat /root/awstats-credentials.txtThe file contains the reporting URL, the user name awstats and the awstats.web.pass value for this instance. If you see a short note instead of credentials, first boot has not finished. Wait for the instance status checks to pass, then read the file again.
Sign In and View Your Reports
Browse to http://<public-ip>/ and sign in with the user name awstats and the password from the credentials file. You land on a chooser with two reports: This server (statistics for this instance's own Apache access log) and Demonstration report (a fully populated sample dataset).
Open the Demonstration report to explore a complete AWStats report straight away. The summary at the top shows the reported period, unique visitors, number of visits, pages, hits and bandwidth, followed by the monthly history graph.
Scroll down for the full breakdown on a single page: days of the month, days of the week, hourly traffic, the busiest hosts, the most requested pages, visit duration, file types, referrers, search engines and keywords, browsers, operating systems and HTTP status codes. Every bar in every graph is drawn from the analyzer's own icon set, so the report is fully graphical.
The navigation strip at the top of the report links to the detail views. For example, Who > Hosts > Full list opens the complete list of visiting hosts with their pages, hits, bandwidth and last visit.
To read this instance's own traffic instead of the demonstration data, open the This server report, or browse directly to the CGI with the config=server parameter. Because the reports are behind Basic authentication, any request without a valid credential is refused:
# From your workstation, replace the password with awstats.web.pass from the credentials file.
curl -u "awstats:<AWSTATS_WEB_PASSWORD>" "http://<public-ip>/cgi-bin/awstats.pl?config=server"Verify the Services
The reporting stack is Apache serving the AWStats CGI, plus a systemd timer that reprocesses this instance's log every ten minutes. Check that both are healthy and that the report is refused without a credential:
systemctl is-active apache2
systemctl is-active awstats-update.timer curl -s http://127.0.0.1/healthz curl -s -o /dev/null -w 'report without auth: HTTP %{http_code}\n' "http://127.0.0.1/cgi-bin/awstats.pl?config=server" curl -s -o /dev/null -w 'health endpoint: HTTP %{http_code}\n' http://127.0.0.1/healthzThe output should show these results:
apache2andawstats-update.timerreportactive.- The health endpoint returns
okand HTTP 200 without a credential, for load balancer probes. - The report CGI returns HTTP 401 when no credential is supplied.
The Two Reports and Their Configuration
AWStats configurations live in /etc/awstats. The processed history data lives under /var/lib/awstats.
ls -1 /etc/awstats/
sudo ls -1 /var/lib/awstats/ systemctl list-timers awstats-update.timer --no-pagerawstats.server.confanalyzes/var/log/apache2/access.log, this instance's own web server log. Theawstats-update.timerreprocesses it every ten minutes, so the This server report fills in as real traffic arrives.awstats.demo.confanalyzes a synthetic access log regenerated against the current date on first boot, so the Demonstration report is always populated for the current month.
The updater runs only from the root-owned systemd timer. Triggering a log parse from the browser is disabled in both configurations, and the history data directory is not served over HTTP, so a request can never forge or corrupt statistics.
Analyzing Additional Logs
To analyze a different log file or another server, copy one of the shipped configurations and point it at the new log. For example, to add a configuration named mysite:
sudo cp /etc/awstats/awstats.server.conf /etc/awstats/awstats.mysite.conf
sudo sed -i 's#^LogFile=.*#LogFile="/var/log/mysite/access.log"#' /etc/awstats/awstats.mysite.conf
sudo sed -i 's#^SiteDomain=.*#SiteDomain="<your-domain>"#' /etc/awstats/awstats.mysite.conf
sudo /usr/local/bin/awstats-update mysiteThe report is then available at http://<public-ip>/cgi-bin/awstats.pl?config=mysite. Keep the LogType, LogFormat, DirIcons, UseFramesWhenCGI=0 and AllowToUpdateStatsFromBrowser=0 settings from the shipped configuration so the report renders correctly and stays secure. Adjust LogFormat if the new log uses a different format. AWStats supports the common web, FTP and mail log formats.
Enabling HTTPS
The image serves on port 80 so that a load balancer or reverse proxy can terminate TLS in front of it. To terminate TLS on the instance itself, install a certificate with Let's Encrypt. First point a DNS name at the instance's public address, then run:
sudo apt-get update
sudo apt-get install -y certbot python3-certbot-apache
sudo certbot --apache -d your-domain.example.comCertbot obtains a certificate and configures Apache to serve the reports over HTTPS.
Where Things Live
Path Purpose
/opt/awstats The AWStats application tree (root-owned, read-only to the web server)
/etc/awstats The demo and server configurations
/var/lib/awstats Processed history data, one directory per configuration
/var/log/apache2/access.log This instance's own web server log (the server report source)
/etc/apache2/awstats.htpasswd The Basic authentication password file
/root/awstats-credentials.txt The per-instance report password (root only)
/usr/local/bin/awstats-update The log updater run by the systemd timer
As history data grows, confirm that the root disk has enough free space:
df -hT /The Security Model
- The whole reporting site, including the report CGI, sits behind HTTP Basic authentication. Only the
/healthzendpoint is open, so a load balancer can probe the instance without a credential. - The report password is generated uniquely on first boot and stored only in
/root/awstats-credentials.txt(mode 0600). No default or shared password ships in the image. - Log processing runs only from the root-owned systemd timer. It can never be triggered from the browser, and the raw history data is not reachable over HTTP.
- The analyzer is deployed without the extra CGI entry points and the legacy Java applet, and the
configdirCGI parameter is refused, so the historically abused injection paths are closed. - You can change the report password at any time. Update the credentials file to match:
sudo htpasswd -bB /etc/apache2/awstats.htpasswd awstats '<new-password>'
sudo systemctl reload apache2Troubleshooting
- The report page loads but shows nothing. Confirm that the timer has run at least once with
systemctl list-timers awstats-update.timer, and runsudo /usr/local/bin/awstats-update serverto reprocess the log immediately. A brand-new instance has little traffic of its own, so start with the Demonstration report. - A 401 when you expected the report. The site is asking you to authenticate. Read the password with
sudo cat /root/awstats-credentials.txtand sign in asawstats. - The graphs are broken images. This should not happen on the shipped image. If you have edited a configuration, make sure
DirIcons="/awstatsicons"is present so that Apache serves the analyzer's icon set. - Check the Apache error log for CGI problems:
sudo tail -n 30 /var/log/apache2/awstats-error.logSupport
SecureAnyCloud publishes this image with 24/7 technical support 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, report interpretation, access control and version upgrades. Critical issues receive a one-hour average response time.
Deploy on AWS
Launch AWStats on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com