solution-forest / filament-goaccess
A Filament plugin that renders GoAccess web-log analytics as a native, live dashboard inside the Filament admin panel.
Package info
github.com/solutionforest/filament-goaccess
pkg:composer/solution-forest/filament-goaccess
Requires
- php: ^8.2
- filament/filament: ^4.0|^5.0
- illuminate/contracts: ^11.0|^12.0|^13.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^2.9|^3.0
- orchestra/testbench: ^9.0|^10.0
- pestphp/pest: ^3.0
- pestphp/pest-plugin-laravel: ^3.0
README
A standalone Filament plugin that turns GoAccess web-log analytics into a native, live dashboard inside your admin panel — stat tiles, a traffic chart, a status-code breakdown, and ranked tables for requests, 404s, hosts, referrers, browsers and operating systems.
Instead of embedding GoAccess's own HTML report in an iframe, the plugin parses GoAccess JSON and renders native Filament widgets, so the dashboard matches your panel's theme and dark mode, and stays "live" through Livewire polling — no WebSocket server or reverse-proxy plumbing required.
- ✅ Native Filament widgets (Filament v4 & v5)
- ✅ Managed mode (the plugin runs
goaccessfor you) or external mode (read a JSON file produced by any pipeline) - ✅ No application database — GoAccess JSON is the source of truth (optional GoAccess incremental on-disk DB for persistence)
- ✅ Date-range filter (Today / 7d / 30d / All / custom) and multi-site switcher
- ✅ Live via Livewire polling — configurable interval
Screenshots
| Light | Dark |
|---|---|
![]() |
![]() |
Stat tiles, a traffic-over-time chart, a status-code doughnut, and ranked tables — all native Filament components that follow your panel's theme. Rendered from the demo app in playground/.
Requirements
| PHP | ^8.2 |
| Laravel | ^11.0 or ^12.0 |
| Filament | ^4.0 or ^5.0 |
| GoAccess binary | Only for managed mode (install docs) |
Installing GoAccess
Only needed for managed mode (skip it for external mode). GoAccess is a single native binary — install it from your OS package manager or goaccess.io/download.
| OS / distro | Command |
|---|---|
| Ubuntu / Debian | sudo apt install goaccess |
| Fedora / RHEL / CentOS | sudo dnf install goaccess |
| Alpine | apk add goaccess |
| Arch | sudo pacman -S goaccess |
| macOS (Homebrew) | brew install goaccess |
| Windows | via WSL + one of the above, or Chocolatey: choco install goaccess |
| Docker | docker run --rm allinurl/goaccess (image) |
The distro packages are often older. For the latest release use the official APT repo or build from source — see goaccess.io/download and the get-started guide.
Verify the install and note the path:
goaccess --version # e.g. "GoAccess - 1.11." command -v goaccess # absolute path — set as GOACCESS_BINARY if not on PATH
- Docs: goaccess.io · Man page: goaccess.io/man · Source: github.com/allinurl/goaccess
Installation
composer require solution-forest/filament-goaccess
Publish the config file:
php artisan vendor:publish --tag="filament-goaccess-config"
Register the plugin on your panel (e.g. app/Providers/Filament/AdminPanelProvider.php):
use SolutionForest\FilamentGoAccess\GoAccessPlugin; public function panel(Panel $panel): Panel { return $panel // ... ->plugin(GoAccessPlugin::make()); }
A GoAccess page now appears in the navigation (under the Analytics group by default).
Configuration
Everything lives in config/filament-goaccess.php. The most important choice is the mode.
Mode 1 — Managed (recommended)
The plugin runs the goaccess binary for you and writes the JSON that the dashboard reads.
-
Install GoAccess on the server (
apt install goaccess,brew install goaccess, …). -
Point a site at your access log(s):
'mode' => 'managed', 'sites' => [ 'default' => [ 'label' => 'My site', 'log_paths' => ['/var/log/nginx/access.log'], 'json_path' => storage_path('app/goaccess/default.json'), 'db_path' => storage_path('app/goaccess/default-db'), 'log_format'=> 'COMBINED', // or null to inherit the global log_format ], ],
-
Generate the report — run it once to verify:
php artisan goaccess:generate
-
Keep it fresh on a schedule (
routes/console.phpon Laravel 11/12):use Illuminate\Support\Facades\Schedule; Schedule::command('goaccess:generate')->everyMinute()->withoutOverlapping();
With
'persist' => true(default), GoAccess keeps a cumulative on-disk database (--persist/--restore), so totals survive log rotation without re-parsing the whole log every run.
Mode 2 — External
Some other pipeline (a cron job, a container sidecar, a CI step) produces the JSON; the plugin only reads it.
'mode' => 'external', 'sites' => [ 'default' => [ 'label' => 'My site', 'json_path' => storage_path('app/goaccess/default.json'), ], ],
Example external cron that writes the JSON the dashboard reads:
* * * * * goaccess /var/log/nginx/access.log \ --log-format=COMBINED -o /path/to/storage/app/goaccess/default.json \ --json-pretty-print --no-global-config
Multiple sites
Add more entries under sites — a Site dropdown appears automatically in the dashboard toolbar when more than one is configured. Picking a site live-swaps every widget (tiles, charts, tables) to that site's data; the date-range filter applies on top. With a single site the dropdown is hidden.
'sites' => [ 'marketing' => ['label' => 'Marketing', 'log_paths' => ['/var/log/nginx/marketing.log'], 'json_path' => storage_path('app/goaccess/marketing.json')], 'app' => ['label' => 'App', 'log_paths' => ['/var/log/nginx/app.log'], 'json_path' => storage_path('app/goaccess/app.json')], ],
Generate one site or all:
php artisan goaccess:generate app # just the "app" site php artisan goaccess:generate # every site
Other options
| Key | Default | Purpose |
|---|---|---|
log_format |
COMBINED |
Any GoAccess predefined format (VCOMBINED, COMMON, W3C, CLOUDFRONT, CADDY, …) or a custom format string. |
polling_interval |
10s |
How often widgets re-read the JSON. null disables polling. |
default_range |
7d |
Initial dashboard window: today | 7d | 30d | all. |
extra_args |
['--no-global-config', '--ignore-crawlers'] |
Extra goaccess args applied to every site (managed mode). |
persist |
true |
Use GoAccess's cumulative on-disk DB across runs. |
navigation |
group: Analytics |
Navigation group / sort / icon. Overridable via the plugin (below). |
Override navigation per panel:
GoAccessPlugin::make() ->navigationGroup('Reports') ->navigationSort(20) ->navigationIcon('heroicon-o-globe-alt');
GeoIP (optional)
Add a MaxMind database via extra_args to enable GoAccess geolocation:
'extra_args' => ['--no-global-config', '--geoip-database=/usr/share/GeoIP/GeoLite2-City.mmdb'],
How the date filter works
GoAccess JSON is a pre-aggregated snapshot, so the filter behaves in two layers:
-
Time-series & summary tiles are re-sliced instantly from the parsed JSON for the selected window (works in both modes).
-
For exact windowed tables in managed mode you can regenerate a scoped report:
php artisan goaccess:generate default --from=2024-01-01 --to=2024-01-31
Troubleshooting
| Symptom | Fix |
|---|---|
Widgets say "No data — run goaccess:generate" |
The json_path file doesn't exist yet. Run the command (managed) or check your pipeline (external). |
goaccess: command not found |
Install the GoAccess binary, or set GOACCESS_BINARY / binary to its absolute path. |
| Empty / wrong numbers | Your log_format doesn't match the log. Try the matching preset (VCOMBINED, CLOUDFRONT, …) or a custom format. |
| 404 tile shows 0 | GoAccess 1.11 omits not_found from the general panel; the plugin derives it from the Not Found panel automatically — make sure your log actually has 404s. |
Testing / Contributing
The suite is Pest + Orchestra Testbench. Logic, parsing, the filter, and empty-state handling run without any binary; one integration test exercises the real goaccess binary (skipped automatically when it isn't installed).
composer install
composer test
Docker (real goaccess, no host install)
A ready-made image bundles PHP 8.3 + the goaccess binary, so the managed-mode
integration test runs against a real binary without installing anything on your host:
docker compose build docker compose run --rm tests # composer install + full Pest suite (incl. real goaccess) docker compose run --rm tests bash # shell in to poke around
This runs the package test suite, not a full Laravel app. To see the dashboard
in a browser, use the demo app in playground/.
Credits
- Solution Forest
- Built on the excellent GoAccess by Gerardo Orellana.
License
The MIT License (MIT). See LICENSE.md.


