GoAccess for Caddy

My current web server setup kinda grew based on my WordPress setup years back. Due to Ansible, I can redeploy it quickly but, in reality, it’s just a bunch of stuff thrown together because I needed it at one time or other. Add to that me running multiple websites on the same server and you have a bit of a mess. First step to cut through all that mess was placing it all behind load balancer running behind docker.

I won’t go too deep into why exactly I opted for Caddy. I suspect nginx would do nicely. Even Apache might have worked as well. But, after a bit of testing and playing with CertBot integration, I decided Caddy was best match for me.

The next step was to ensure I have some visibility into what was going on and there I found GoAccess. But guides I found didn’t really work. Some had issues with log format, some had issues with web sockets, some even had issues with syntax.

After a bit of twiddling, I ended up with the following compose.yaml.

services:
  caddy:
    image: caddy:latest
    container_name: caddy
    restart: unless-stopped
    cap_add:
      - NET_ADMIN
    ports:
      - 80:80
      - 443:443
      - 443:443/udp
    volumes:
      - ./config/:/etc/caddy/
      - ./logs/:/var/log/caddy/
      - ./stats/:/var/www/goaccess/:ro

  stats:
    image: allinurl/goaccess:latest
    container_name: stats
    volumes:
      - ./logs/:/var/log/caddy/:ro
      - ./stats/:/var/www/goaccess/
    ports:
      - 7890:7890
    command: "/var/log/caddy/access.log --log-format=CADDY -o /var/www/goaccess/index.html --real-time-html --ws-url=wss://stats.example.com:443/ws --port=7890"

Caddy setup is quite straight-forward. It will use three volumes: one for config, one for output logs, and the last one for viewing stats (read-only).

Stats themselves are setup similarly too, this time with only two volumes needed. Logs are read from logs (read-only) and the web pages are written into stats. Command being ran is one allowing for real-time monitoring. And that requires websocket support.

Caddy configuration would look something like this:

example.com {
    log {
        output file /var/log/caddy/access.log
        format json
    }
    respond "Hello World!"
}

stats.example.com {
    root * /var/www/goaccess
    file_server
    reverse_proxy /ws stats:7890
}

And this setup will allow you to see stats as they come.