waypointer-digital / health-laravel
Kanbino Health endpoint for Laravel — emits stack profile + extensible probes for uptime + security advisory matching
Package info
github.com/Waypointer-Digital/health-laravel
pkg:composer/waypointer-digital/health-laravel
Requires
- php: ^8.2
- illuminate/http: ^11.0|^12.0
- illuminate/routing: ^11.0|^12.0
- illuminate/support: ^11.0|^12.0
Suggests
- laravel/horizon: Required for HorizonProbe (^5.0)
README
A drop-in /health endpoint for Laravel apps that emits:
status—healthyordegradedbased on probe outcomes (HTTP 200 / 503).checks— per-probe results (database, redis, queue, plus your own).stack— auto-collected OS profile (id/version/codename), kernel, PHP version, and dpkg package versions for a configured allowlist.
Kanbino's uptime monitor consumes the stack section to match your servers against Ubuntu Security Notices and oss-security advisories.
Install
composer require waypointer-digital/health-laravel php artisan vendor:publish --tag=kanbino-health-config
The route GET /health is registered automatically. Override the path in config/kanbino-health.php or via KANBINO_HEALTH_PATH=/internal/health.
Response shape
{
"status": "healthy",
"checks": {
"database": { "ok": true, "ms": 4 },
"redis": { "ok": true, "ms": 1 },
"queue": { "ok": true, "depth": 3 }
},
"stack": {
"os": { "id": "ubuntu", "version": "24.04", "codename": "noble", "name": "Ubuntu 24.04 LTS" },
"kernel": "6.8.0-49-generic",
"php": "8.5.1",
"packages": {
"nginx": "1.24.0-2ubuntu7.1",
"postgresql": "16.4-0ubuntu0.24.04.1",
"redis-server": "5:7.0.15-1ubuntu0.1"
}
}
}
Configuration
config/kanbino-health.php:
return [ 'enabled' => env('KANBINO_HEALTH_ENABLED', true), 'path' => env('KANBINO_HEALTH_PATH', '/health'), 'middleware' => ['web'], 'token' => env('KANBINO_HEALTH_TOKEN'), 'stack' => [ 'enabled' => true, 'packages' => ['nginx', 'postgresql', 'redis-server', 'php8.5-fpm', /* ... */], 'cache_seconds' => 3600, ], 'probes' => [ \Kanbino\Health\Probes\DatabaseProbe::class, \Kanbino\Health\Probes\RedisProbe::class, \Kanbino\Health\Probes\QueueProbe::class, // Opt-in system probes: // \Kanbino\Health\Probes\HorizonProbe::class, // requires laravel/horizon // \Kanbino\Health\Probes\DiskProbe::class, // \Kanbino\Health\Probes\MemoryProbe::class, // \Kanbino\Health\Probes\CpuProbe::class, ], ];
Built-in probes
| Probe | What it checks | Default | Notes |
|---|---|---|---|
DatabaseProbe |
SELECT 1 on default connection |
enabled | Reports ms |
RedisProbe |
PING on default Redis connection |
enabled | Reports ms |
QueueProbe |
Reads queue size on default connection | enabled | Reports depth (the queue backend, not the workers) |
HorizonProbe |
Active Horizon master supervisors | opt-in | Requires laravel/horizon. Catches "Redis up, but Horizon dead and jobs piling up" — different signal than QueueProbe |
DiskProbe |
Disk usage on a path | opt-in | Constructor: path, failAtPercent (default /, 95%) |
MemoryProbe |
Used memory from /proc/meminfo |
opt-in | Constructor: failAtPercent (default 95%). Returns OK with note on macOS where /proc isn't available |
CpuProbe |
Load avg vs core count | opt-in | Constructor: failAtPercent (default 150%, i.e. 1.5× core saturation). Cores read from /proc/cpuinfo, no shell_exec |
To override default thresholds or paths, bind in your AppServiceProvider:
$this->app->bind(\Kanbino\Health\Probes\DiskProbe::class, fn () => new \Kanbino\Health\Probes\DiskProbe('/var/www', 90.0)); $this->app->bind(\Kanbino\Health\Probes\CpuProbe::class, fn () => new \Kanbino\Health\Probes\CpuProbe(120.0));
Auth
If KANBINO_HEALTH_TOKEN is set, requests must send Authorization: Bearer <token>. The Kanbino monitor sends the configured token automatically.
Custom probes
Implement Kanbino\Health\Probes\HealthProbe and add it to the probes config array:
namespace App\Health; use Kanbino\Health\Probes\HealthProbe; use Kanbino\Health\Probes\ProbeResult; class ScalewayReachableProbe implements HealthProbe { public function name(): string { return 'scaleway'; } public function run(): ProbeResult { $ok = @fsockopen('s3.nl-ams.scw.cloud', 443, $err, $errstr, 2) !== false; return $ok ? ProbeResult::ok() : ProbeResult::fail($errstr ?: 'unreachable'); } }
// config/kanbino-health.php 'probes' => [ \Kanbino\Health\Probes\DatabaseProbe::class, \Kanbino\Health\Probes\RedisProbe::class, \Kanbino\Health\Probes\QueueProbe::class, \App\Health\ScalewayReachableProbe::class, // your project-specific check ],
A failing probe flips status to degraded and the endpoint returns HTTP 503 — Kanbino's monitor will mark the service as degraded.
Stack package detection
Stack package versions are read from /var/lib/dpkg/status (Debian/Ubuntu only, no shell exec). On non-dpkg systems (macOS, Alpine), the packages block will be empty but OS/kernel/PHP detection still works where possible.
The OS is detected from /etc/os-release — ID, VERSION_ID, VERSION_CODENAME. Codename matching (noble, jammy, …) is what Kanbino uses to filter Ubuntu Security Notices for your release.
Manual usage
If you don't want the auto-registered route, set enabled => false and use HealthResponse from your own controller:
use Kanbino\Health\HealthResponse; Route::get('/my-health', function (HealthResponse $response) { return response()->json($response->build()); });