waypointer-digital/health-laravel

Kanbino Health endpoint for Laravel — emits stack profile + extensible probes for uptime + security advisory matching

Maintainers

Package info

github.com/Waypointer-Digital/health-laravel

pkg:composer/waypointer-digital/health-laravel

Statistics

Installs: 40

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.2.1 2026-05-08 13:11 UTC

This package is auto-updated.

Last update: 2026-05-08 13:13:48 UTC


README

A drop-in /health endpoint for Laravel apps that emits:

  1. statushealthy or degraded based on probe outcomes (HTTP 200 / 503).
  2. checks — per-probe results (database, redis, queue, plus your own).
  3. 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-releaseID, 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());
});