kiora / health-check-bundle
Production-ready Symfony bundle for comprehensive application health checks with database, Redis, S3, and HTTP endpoint monitoring. Security-first design with auto-tagging support.
Installs: 1
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Type:symfony-bundle
pkg:composer/kiora/health-check-bundle
Requires
- php: >=8.3
- symfony/config: ^6.4|^7.0
- symfony/dependency-injection: ^6.4|^7.0
- symfony/framework-bundle: ^6.4|^7.0
- symfony/http-kernel: ^6.4|^7.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- phpro/grumphp: ^2.0
- phpstan/phpstan: ^2.0
- phpstan/phpstan-symfony: ^2.0
- phpunit/phpunit: ^10.0|^11.0
This package is auto-updated.
Last update: 2025-11-06 14:45:56 UTC
README
A Symfony bundle providing comprehensive health check functionality for monitoring application dependencies and services.
Features
- 🔍 Multiple Health Checks: Database, Redis, S3/MinIO, HTTP endpoints
- 🔒 Security First: No sensitive information exposed (versions, paths, credentials)
- ⚡ Performance: Configurable timeouts, non-blocking checks
- 🎯 Flexible: Critical vs non-critical checks, enable/disable per check
- 🛡️ Production Ready: Rate limiting, security headers, generic error messages
- 📊 Standard Format: JSON response with status, duration, and individual check results
Installation
1. Install the bundle
composer require kiora/health-check-bundle
2. Enable the bundle
If Symfony Flex is not installed, manually add the bundle to config/bundles.php:
return [ // ... Kiora\HealthCheckBundle\HealthCheckBundle::class => ['all' => true], ];
3. Import routes
Create config/routes/health_check.yaml:
health_check_bundle: resource: '@HealthCheckBundle/config/routes.php' type: php
4. Configure security access
Add public access to the health check endpoint in config/packages/security.yaml:
access_control: - { path: ^/health, roles: PUBLIC_ACCESS } # ... your other rules
5. (Optional) Configure rate limiting
Create config/packages/rate_limiter.yaml:
framework: rate_limiter: health_check: policy: 'sliding_window' limit: 60 interval: '1 minute'
Install required packages:
composer require symfony/rate-limiter symfony/lock
Configuration
Basic Configuration
Create config/packages/health_check.yaml:
health_check: enabled: true checks: database: enabled: true # Default: true (auto-registered) redis: enabled: false # Default: false (enable only if Redis is available)
Built-in Checks
1. Database Check (Auto-registered)
✅ Automatically enabled - Verifies database connectivity using Doctrine DBAL.
health_check: checks: database: enabled: true # Default: true
No additional configuration needed. Works out of the box with your existing Doctrine configuration.
2. Redis Check (Manual setup)
⚙️ Disabled by default - Only configure if your project uses Redis.
Step 1: Enable in configuration
health_check: checks: redis: enabled: true # Explicitly enable Redis check
Step 2: Configure the service
Create or update config/packages/health_check.yaml:
services: Kiora\HealthCheckBundle\HealthCheck\Checks\RedisHealthCheck: autoconfigure: true # Enables auto-tagging via interface arguments: $host: '%env(REDIS_HOST)%' $port: '%env(int:REDIS_PORT)%' $critical: false # Set to true if Redis failure should return 503
Step 3: Add environment variables
REDIS_HOST=redis REDIS_PORT=6379
3. S3/MinIO Storage Check (Manual setup)
⚙️ Requires manual configuration - Only configure if your project uses S3/MinIO storage.
services: app.health_check.s3_storage: class: Kiora\HealthCheckBundle\HealthCheck\Checks\S3HealthCheck autoconfigure: true # Enables auto-tagging via interface arguments: $filesystem: '@your.flysystem.storage' # Your Flysystem service ID $name: 's3_storage' $critical: false
Example for multiple buckets:
services: # Documents storage app.health_check.s3_documents: class: Kiora\HealthCheckBundle\HealthCheck\Checks\S3HealthCheck autoconfigure: true # Enables auto-tagging via interface arguments: $filesystem: '@documents.storage' $name: 's3_documents' $critical: false # Templates storage app.health_check.s3_templates: class: Kiora\HealthCheckBundle\HealthCheck\Checks\S3HealthCheck autoconfigure: true # Enables auto-tagging via interface arguments: $filesystem: '@templates.storage' $name: 's3_templates' $critical: false
4. HTTP Endpoint Check (Manual setup)
⚙️ For monitoring external dependencies - Configure for each external API you depend on.
services: app.health_check.external_api: class: Kiora\HealthCheckBundle\HealthCheck\Checks\HttpHealthCheck autoconfigure: true # Enables auto-tagging via interface arguments: $url: 'https://api.example.com/health' $name: 'external_api' $timeout: 5 $critical: false $expectedStatusCodes: [200, 401] # 401 = API accessible but auth required
Example: Microsoft Graph API
services: app.health_check.microsoft_graph: class: Kiora\HealthCheckBundle\HealthCheck\Checks\HttpHealthCheck autoconfigure: true # Enables auto-tagging via interface arguments: $url: 'https://graph.microsoft.com/v1.0/me' $name: 'microsoft_graph' $timeout: 5 $critical: false $expectedStatusCodes: [401] # 401 = API accessible, auth required (expected)
Usage
Accessing the Health Check Endpoint
curl http://localhost/health
Response Format
{
"status": "healthy",
"timestamp": "2025-11-05T18:02:20+01:00",
"duration": 0.015,
"checks": [
{
"name": "database",
"status": "healthy",
"message": "Database operational",
"duration": 0.002,
"metadata": []
},
{
"name": "redis",
"status": "healthy",
"message": "Redis operational",
"duration": 0.001,
"metadata": []
}
]
}
Status Codes
- 200 OK: All critical checks passed
- 503 Service Unavailable: One or more critical checks failed
Check Status Values
healthy: Check passed successfullyunhealthy: Check faileddegraded: Check passed with warnings (reserved for future use)
Creating Custom Health Checks
1. Create your check class
Simply implement HealthCheckInterface or extend AbstractHealthCheck. No manual tagging required!
<?php namespace App\HealthCheck; use Kiora\HealthCheckBundle\HealthCheck\AbstractHealthCheck; use Kiora\HealthCheckBundle\HealthCheck\HealthCheckResult; use Kiora\HealthCheckBundle\HealthCheck\HealthCheckStatus; class CustomHealthCheck extends AbstractHealthCheck { public function getName(): string { return 'custom'; } public function getTimeout(): int { return 5; // seconds } public function isCritical(): bool { return false; // Set to true if failure should return 503 } protected function doCheck(): HealthCheckResult { try { // Your health check logic here $isHealthy = true; return new HealthCheckResult( name: $this->getName(), status: $isHealthy ? HealthCheckStatus::HEALTHY : HealthCheckStatus::UNHEALTHY, message: $isHealthy ? 'Custom check passed' : 'Custom check failed', duration: 0.0, metadata: [] // Always empty for security ); } catch (\Exception $e) { return new HealthCheckResult( name: $this->getName(), status: HealthCheckStatus::UNHEALTHY, message: 'Custom check failed', duration: 0.0, metadata: [] ); } } }
2. Register your check
If you have autowire: true and autoconfigure: true in your services.yaml (default in modern Symfony):
services: _defaults: autowire: true autoconfigure: true App\HealthCheck\CustomHealthCheck: ~ # That's it! The service is automatically tagged with 'health_check.checker'
How it works: All classes implementing HealthCheckInterface are automatically tagged with health_check.checker thanks to the #[AutoconfigureTag] attribute on the interface. No manual tagging needed!
Security Considerations
What's Included ✅
- Generic error messages - No stack traces or internal paths
- No version information - Database/Redis versions not exposed
- No connection details - Hostnames, IPs, credentials hidden
- Security headers - X-Robots-Tag, Cache-Control, X-Content-Type-Options
- Rate limiting support - Prevent abuse and DoS attacks
- Empty metadata - No sensitive information in responses
What's NOT Included ❌
- Database names or connection strings
- Server versions or software versions
- File paths or directory structures
- Exception messages with sensitive data
- Response sizes or client counts
- Internal URLs or endpoints
Best Practices
- Enable rate limiting to prevent abuse
- Use IP whitelisting for production environments if possible
- Monitor access logs to detect reconnaissance attempts
- Keep checks non-critical unless absolutely necessary
- Avoid exposing internal service names in check names
Monitoring Integration
Kubernetes Liveness/Readiness Probes
livenessProbe: httpGet: path: /health port: 80 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /health port: 80 initialDelaySeconds: 5 periodSeconds: 5
Docker Healthcheck
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ CMD curl -f http://localhost/health || exit 1
Prometheus/Grafana
The JSON response can be easily parsed and converted to metrics for monitoring dashboards.
Troubleshooting
Health check returns 404
- Verify routes are imported in
config/routes/health_check.yaml - Clear cache:
php bin/console cache:clear - Check bundle is enabled in
config/bundles.php
Check always returns "unhealthy"
- Verify service configuration (host, port, credentials)
- Check Docker network connectivity between services
- Review application logs for connection errors
- Ensure the service is actually running
Rate limiting errors
- Install required packages:
composer require symfony/rate-limiter symfony/lock - Configure rate limiter in
config/packages/rate_limiter.yaml
Redis check not working
- Ensure Redis service is running
- Verify Redis is on the same Docker network as your application
- Check
REDIS_HOSTandREDIS_PORTenvironment variables - Test connection:
docker compose exec php php -r "..."
Requirements
- PHP >= 8.2
- Symfony >= 6.4 or >= 7.0
- Doctrine DBAL (for database check)
Optional Dependencies
ext-redis: For RedisHealthCheck with PHP Redis extensionpredis/predis: Alternative Redis clientleague/flysystem: For S3HealthChecksymfony/http-client: For better HTTP check performancesymfony/rate-limiter: For rate limiting supportsymfony/lock: Required by rate limiter
Configuration Reference
Complete Example
# config/packages/health_check.yaml health_check: enabled: true checks: database: enabled: true # Default: true redis: enabled: true # Default: false - explicitly enable if Redis is available services: # Redis Health Check (only if enabled above) Kiora\HealthCheckBundle\HealthCheck\Checks\RedisHealthCheck: autoconfigure: true arguments: $host: '%env(REDIS_HOST)%' $port: '%env(int:REDIS_PORT)%' $critical: false # S3 Storage Health Check app.health_check.s3: class: Kiora\HealthCheckBundle\HealthCheck\Checks\S3HealthCheck autoconfigure: true arguments: $filesystem: '@documents.storage' $name: 's3_documents' $critical: false # External API Health Check app.health_check.api: class: Kiora\HealthCheckBundle\HealthCheck\Checks\HttpHealthCheck autoconfigure: true arguments: $url: 'https://api.example.com/health' $name: 'external_api' $timeout: 5 $critical: false $expectedStatusCodes: [200]
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Development Setup
git clone https://github.com/kiora-tech/health_check_bundle.git
cd health_check_bundle
composer install
Code Quality
This project uses GrumPHP to ensure code quality. All checks are run automatically before each commit:
# Run all quality checks (PHPStan, PHP-CS-Fixer, PHPUnit) composer qa # Run specific checks composer test # PHPUnit tests composer phpstan # PHPStan static analysis composer cs-check # PHP-CS-Fixer check (dry-run) composer cs-fix # PHP-CS-Fixer fix
Coding Standards
- PSR-12: Follow PSR-12 coding standards
- Strict types: All files must declare
strict_types=1 - Type hints: Use type hints for all method parameters and return types
- PHPStan Level 8: Code must pass PHPStan level 8 analysis
- Tests: Add tests for new features and bug fixes
Support
- Issues: GitHub Issues
- Documentation: README.md
License
This bundle is released under the MIT License.
Credits
Created and maintained by Kiora Tech.
Changelog
1.0.0 (2025-11-06)
- Initial open source release
- Database, Redis, S3, and HTTP health checks
- Security-first design with no sensitive data exposure
- Modern auto-tagging with
#[AutoconfigureTag](Symfony 6.1+) - Rate limiting support
- Configurable timeouts and critical checks
- Enable/disable checks via configuration
- Production-ready with Kubernetes/Docker support