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