GoAccess Log File Analysis for Caddy

This setup lets you analyze Caddy access logs with GoAccess and view real-time web stats via webstats.example.com, served directly by your Caddy server. It also supports WebSockets through the same domain.

Components (Docker Images) Used:

  • Caddy web server
  • GoAccess
  • MaxMind GeoIP (optional)

Folder structure:

$PWD
├── caddy
│   ├── config
│   ├── data
│   ├── etc
│   │   └── caddy
│   │       └── Caddyfile
│   ├── logs
│   │   └── access.log
│   └── www
│       └── stats
├── goaccess
│   └── db
└── maxmind

Caddy Docker Compose:

services:
  caddy:
    image: caddy:latest
    container_name: caddy
    volumes:
      - $PWD/caddy/etc/caddy:/etc/caddy:ro
      - $PWD/caddy/config:/config
      - $PWD/caddy/data:/data
      - $PWD/caddy/logs:/logs
      - $PWD/caddy/www:/www:ro
    network_mode: host
    restart: unless-stopped

MaxMind Docker Compose:

services:
  maxmind:
    image: ghcr.io/maxmind/geoipupdate:latest
    container_name: maxmind
    environment:
      - GEOIPUPDATE_ACCOUNT_ID=REDACTED
      - GEOIPUPDATE_LICENSE_KEY=REDACTED
      - 'GEOIPUPDATE_EDITION_IDS=GeoLite2-ASN GeoLite2-City GeoLite2-Country'
      - GEOIPUPDATE_FREQUENCY=72
    volumes:
      - $PWD/maxmind:/usr/share/GeoIP
    restart: unless-stopped

This container automatically keeps the GeoIP databases up to date. If you don’t need Geo location data in GoAccess, you can skip this part. You’ll need to register for a free MaxMind account and provide your own ACCOUNT_ID and LICENSE_KEY.

GoAccess Docker Compose:

services:
  goaccess:
    image: allinurl/goaccess:latest
    container_name: goaccess
    environment:
      - TZ=PST8PDT
    volumes:
      - $PWD/goaccess/db:/db
      - $PWD/caddy/logs:/logs:ro
      - $PWD/caddy/www/stats:/www
      - $PWD/maxmind:/maxmind:ro
    command:
      - '--geoip-database=/maxmind/GeoLite2-City.mmdb'
      - '--log-file=/logs/access.log'
      - '--log-format=CADDY'
      - '--db-path=/db'
      - '--persist'
      - '--restore'
      - '--real-time-html'
      - '--output=/www/index.html'
      - '--ws-url=wss://webstats.example.com:443'
    ports:
      - 127.0.0.1:7890:7890
    restart: unless-stopped

Update the TZ value to your preferred time zone.

GoAccess is bound to the loopback interface only, helping prevent unintended external access.

To check if your GoAccess build supports GeoLocation, run:
goaccess -V

Caddyfile:

webstats.example.com {

	@allowed_ips {
		remote_ip private_ranges
	}
	handle @allowed_ips {
		@websockets {
			header Connection Upgrade
			header Upgrade websocket
		}
		handle @websockets {
			reverse_proxy 127.0.0.1:7890
		}
		handle {
			root * /www/stats/
			file_server
		}
	}
	respond 403
}

This serves the GoAccess stats (including WebSockets) at webstats.example.com, but only allows access from private/local IP ranges.

Tested with:

  • Caddy v2.10.0
  • MaxMind GeoIPUpdate v7.1.0
  • GoAccess v1.9.4
2 Likes