Search by

concept-image / laravel-checks

concept-image

Laravel Checks: Spatie Laravel Health with extra checks (public/index.php, unexpected files, exposed files, SMTP), a publishable health configuration and a publishable service provider registering the production health checks.

Package info

gitlab.com/concept-image-public/laravel-checks/

Issues

pkg:composer/concept-image/laravel-checks

Statistics

Installs: 14

Dependents: 0

Suggesters: 0

Stars: 0

1.2.0 2026-11-13 16:04 UTC

This package is auto-updated.

Last update: 2026-11-13 15:04:24 UTC


README

Latest Version on Packagist License

Extra Spatie Laravel Health checks for production Laravel applications, and an install command that publishes a ChecksServiceProvider registering the usual production checks. Each project then adds, removes or tweaks its checks in PHP.

Requirements

  • PHP 8.3 or higher
  • Laravel 12 or 13

The package installs spatie/laravel-health and spatie/security-advisories-health-check: don't require them in the application.

Installation

composer require concept-image/laravel-checks
php artisan laravel-checks:install

The install command publishes config/health.php and app/Providers/ChecksServiceProvider.php, and adds the provider to bootstrap/providers.php. Files that already exist are kept. To publish one of them only:

php artisan vendor:publish --tag=laravel-checks-config
php artisan vendor:publish --tag=laravel-checks-provider

Health configuration

config/health.php is the Spatie Laravel Health configuration with these defaults:

  • results kept in memory (InMemoryHealthResultStore): nothing is stored in the database;
  • the Oh Dear endpoint enabled, running the checks on each call (always_send_fresh_results);
  • notifications off (HEALTH_NOTIFICATIONS_ENABLED): Oh Dear alerts instead.

Set these variables in .env:

VariableMeaning
OH_DEAR_HEALTH_CHECK_SECRETSecret shown in the Application Health settings of Oh Dear
OH_DEAR_HEALTH_CHECK_URLEndpoint path to enter in Oh Dear (default /oh-dear-health-check-results); use a hard-to-guess path
HEALTH_NOTIFICATIONS_ENABLED, HEALTH_TO_ADDRESSOptional mail notifications

The package itself registers no check: the published provider owns the list.

Published provider

final class ChecksServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Health::checks([
            CacheCheck::new(),
            DebugModeCheck::new(),
            EnvironmentCheck::new()->expectEnvironment('production'),
            // \Spatie\Health\Checks\Checks\HorizonCheck::new(),
            OptimizedAppCheck::new(),
            // \Spatie\Health\Checks\Checks\RedisCheck::new(),
            SecurityAdvisoriesCheck::new(),
            IndexCheck::new(),
            ExposedFilesCheck::new(),
            SmtpCheck::new(),
            UnexpectedFilesCheck::new(),
        ]);
    }
}

Uncomment Horizon (requires laravel/horizon) and Redis when the project uses them, and use the fluent options of each check, for example SmtpCheck::new()->mailer('ses-smtp').

Checks shipped by the package

CheckFails when
IndexCheckpublic/index.php differs from the Laravel skeleton file of the installed major version (warning when it cannot be fetched)
ExposedFilesCheck.env, .htaccess, artisan, auth.json, composer.json or composer.lock is served by APP_URL (warning when it cannot be reached)
SmtpCheckthe mailer (the default one, or ->mailer()) is not an SMTP mailer, or cannot connect and authenticate to its server
UnexpectedFilesCheckthe project root or public/ contains a file or directory outside the allowed lists, or the project contains any *.sql* file

SmtpCheck opens an SMTP session (connection, EHLO, TLS, authentication) and closes it: no email is sent.

ExposedFilesCheck requests each path on APP_URL (or ->baseUrl()) without following redirects: a file is exposed when it answers with a 2xx status and a non-HTML body, so catch-all routes and HTML error pages are not reported. Change the list with ->paths([...]) or ->addPaths([...]).

UnexpectedFilesCheck compares the entries of the project root and of public/, hidden ones included, with allowlists:

LocationFilesDirectories
project root.env, artisan, auth.json, composer.json, composer.lockapp, bootstrap, config, database, lang, public, resources, routes, storage, vendor
public/.htaccess, apple-touch-icon.png, favicon.ico, favicon.svg, index.php, robots.txtbuild, css, fonts, js, storage

Anything else (tests/, .git/, package.json, public/hot, public/info.php…) is reported. Allow more entries with ->allowRootFiles([...]), ->allowRootDirectories([...]), ->allowPublicFiles([...]) and ->allowPublicDirectories([...]), for example a REVISION file written by the deployment tool.

It also fails on any SQL file at any depth (.sql, .sql.gz, .sql.zip…, whatever the case), symbolic links followed so a shared storage/ is scanned: SQL files are never deployed, so one found on the server is a dump left behind, possibly holding personal data. vendor/ and node_modules/ are skipped; exclude more directories with ->excludeFromSqlScan([...]).

Testing

composer ci

Changelog

See CHANGELOG.

License

The MIT License (MIT). See License File.