angelitosystems / filament-tenancy
Tenancy package for Filament - multi-database tenants + central support
Installs: 2
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 0
Forks: 0
Open Issues: 1
pkg:composer/angelitosystems/filament-tenancy
Requires
- php: ^8.1|^8.2|^8.3
- barryvdh/laravel-dompdf: ^3.1
- filament/filament: ^4.0
- filament/forms: ^4.0
- filament/tables: ^4.0
- laravel/framework: ^11.0|^12.0
Requires (Dev)
- orchestra/testbench: ^9.0
- phpunit/phpunit: ^11.0
This package is auto-updated.
Last update: 2025-11-07 00:33:17 UTC
README
A comprehensive multi-tenancy package for Filament with support for multiple databases, central management, advanced logging, and performance monitoring.
Features
- ๐ Easy Installation - Interactive installer with automatic setup
- ๐ฅ User Management - Create and manage tenant users with roles and permissions
- ๐ Roles & Permissions - Complete Spatie-like RBAC system for tenant access control
- ๐ฆ Asset Sharing - Share Livewire, Filament, and custom assets from central to tenants
- ๐ฅ Admin User Creation - Interactive admin user creation during installation
- ๐๏ธ Multi-database tenancy - Complete isolation between tenants
- ๐๏ธ Central tenant management - Unified control panel for all tenants
- โก Automatic database creation and migration - Seamless tenant provisioning
- ๐ Tenant-aware middleware - Automatic context switching
- ๐จ Filament integration - Native Filament admin panel support
- ๐ Secure credential management - Encrypted credential storage with rotation
- ๐ Enhanced Debug Logging - Environment-aware logging with production-safe output
- ๐ Performance monitoring - Real-time metrics and connection monitoring
- ๐ Connection pooling - Optimized database connection management
- ๐ณ Plans & Subscriptions - Built-in plan and subscription management
- ๐ณ PayPal Integration - Complete PayPal payment integration with webhooks support
- ๐ก๏ธ Database compatibility check - Automatic validation of database requirements
- ๐งน Smart error handling - Automatic retry and cleanup on connection errors
- ๐ APP_DOMAIN Auto-Detection - Automatic domain detection from APP_URL for subdomain tenancy
- ๐ง Enhanced Tenant Creation - Interactive wizard with automatic domain configuration
- ๐จ Custom 404 Page - Beautiful personalized 404 page for tenant not found errors with Livewire component support
- โ๏ธ License-Based - Future licensing model for commercial use (currently public access)
Installation
Quick Install
The easiest way to install Filament Tenancy is using the interactive installer:
composer require angelitosystems/filament-tenancy php artisan filament-tenancy:install
The installer will:
- โ Check if Filament is installed and install it if needed
- โ Verify database compatibility (MySQL/PostgreSQL required)
- โ Configure database connection interactively if needed
- โ Publish configuration files
- โ Run migrations automatically
- โ Create default plans automatically (Basic, Premium, Enterprise)
- โ Register the ServiceProvider automatically
- โ
Register middlewares automatically in
bootstrap/app.php(Laravel 11) or via ServiceProvider (Laravel 10) - โ Configure custom 404 page - Ask if you want to publish components and views for tenant not found errors
Manual Installation
If you prefer manual installation:
# Install the package composer require angelitosystems/filament-tenancy # Publish the configuration file php artisan vendor:publish --tag="filament-tenancy-config" # Publish seeders (now includes central and tenant seeders) php artisan vendor:publish --tag="filament-tenancy-seeders" php artisan vendor:publish --tag="filament-tenancy-tenant-seeders" # Publish custom 404 page components and views (optional) php artisan vendor:publish --tag="filament-tenancy-views" php artisan vendor:publish --tag="filament-tenancy-components" # Run the migrations php artisan migrate # Seed default plans (or they will be seeded automatically during installation) php artisan db:seed --class=Database\Seeders\PlanSeeder # Setup central database (required for landlord administration) php artisan filament-tenancy:setup-central --create-admin
Central Database Setup
After installation, you need to set up the central database with roles and permissions for the landlord/central administration:
# Complete central database setup (recommended) php artisan filament-tenancy:setup-central --create-admin # Or step by step: php artisan migrate --path="packages/filament-tenancy/database/migrations" php artisan filament-tenancy:seed-central php artisan filament-tenancy:create-central-admin
The central database setup includes:
- ๐๏ธ Central Roles & Permissions: Separate permission system for central administration
- ๐ Super Admin Role: Complete access to all central features
- ๐ก๏ธ Landlord Admin Role: Manage tenants, plans, and subscriptions
- ๐ง Support Role: Read-only access for support staff
- ๐ค Central Admin User: Automatically created with Super Admin role
Central Permissions Available:
manage tenants- Create, edit, delete tenantsmanage plans- Manage subscription plansmanage subscriptions- Handle tenant subscriptionsmanage central users- Manage central admin usersmanage central roles- Manage central roles and permissionsview central dashboard- Access central dashboardmanage system settings- Configure system-wide settingsaccess landlord panel- Access landlord administration panelmanage tenant databases- Manage tenant database operations
Requirements
- PHP: 8.1 or higher
- Laravel: 10.x or 11.x
- Filament: ^4.0
- Database: MySQL 5.7+ or PostgreSQL 10+ (SQLite is not supported for multi-database tenancy)
Configuration
The package configuration is located at config/filament-tenancy.php. Key configuration options include:
Tenant Resolution
// How tenants are resolved from requests 'resolver' => env('TENANCY_RESOLVER', 'domain'), // 'domain', 'subdomain', 'path' // Central domains that won't be resolved as tenants 'central_domains' => [ 'app.dental.test', 'localhost', env('APP_DOMAIN', 'localhost'), ],
Note: The package now supports APP_DOMAIN environment variable for subdomain-based tenancy. When creating tenants with subdomains, the package will automatically detect and suggest configuring APP_DOMAIN from your APP_URL if it's not already set.
Database Configuration
'database' => [ 'default_connection' => env('DB_CONNECTION', 'mysql'), 'tenants_connection_template' => [ 'driver' => env('TENANT_DB_DRIVER', 'mysql'), 'host' => env('TENANT_DB_HOST', '127.0.0.1'), 'port' => env('TENANT_DB_PORT', '3306'), 'username' => env('TENANT_DB_USERNAME', 'root'), 'password' => env('TENANT_DB_PASSWORD', ''), // ... other database options ], 'auto_create_tenant_database' => env('TENANCY_AUTO_CREATE_DB', true), 'auto_delete_tenant_database' => env('TENANCY_AUTO_DELETE_DB', false), ],
Environment Variables
The package uses the following environment variables:
# Base domain for subdomain-based tenancy (auto-detected from APP_URL) APP_DOMAIN=hola.test # Tenant resolution strategy TENANCY_RESOLVER=domain # Database configuration (optional, uses DB_* by default) TENANT_DB_DRIVER=mysql TENANT_DB_HOST=127.0.0.1 TENANT_DB_PORT=3306 TENANT_DB_USERNAME=root TENANT_DB_PASSWORD= # Tenancy settings TENANCY_AUTO_CREATE_DB=true TENANCY_AUTO_DELETE_DB=false
APP_DOMAIN: This variable is automatically detected and configured when creating tenants. If your APP_URL contains a valid domain (e.g., http://hola.test), the package will ask if you want to use it as APP_DOMAIN. This is essential for subdomain-based tenancy.
Central Domains: APP_DOMAIN is automatically considered a central domain and will not resolve tenants. Additional domains can be configured in central_domains config array. Central domains typically host the admin panel for managing tenants. The middleware automatically allows access to these domains without tenant resolution.
Security: The middleware automatically:
- Returns 404 for domains/subdomains that don't match any tenant
- Only resolves active tenants (
is_active = trueand not expired) - Protects central domains from tenant resolution
- Validates tenant status before allowing access
Filament Integration
'filament' => [ 'auto_register_plugins' => true, 'landlord_panel_id' => 'admin', 'tenant_panel_id' => 'tenant', 'tenant_panel_path' => '/admin', ],
Usage
Creating Tenants
Using Artisan Commands (Interactive)
The easiest way to create tenants is using the interactive command:
# Interactive tenant creation
php artisan tenancy:create
The command will guide you through:
- APP_DOMAIN Detection: Automatically detects and configures
APP_DOMAINfromAPP_URLif needed - Tenant name and slug
- Domain or subdomain configuration (subdomains use
APP_DOMAINautomatically) - Database name (auto-generated if not provided)
- Plan selection: Shows plans from database with prices and billing cycles (Basic, Premium, Enterprise)
- Active status and expiration date
- Automatic subscription creation: Creates an active subscription when a plan is selected
APP_DOMAIN Auto-Configuration:
- Valid Domain Detection: If
APP_URLcontains a valid domain (e.g.,http://hola.test), the command will detect it and ask if you want to use it asAPP_DOMAIN - Localhost/Port Detection: If
APP_URLis localhost or has a port (e.g.,http://localhost:8000), you'll be prompted to configureAPP_DOMAINmanually - Automatic .env Updates: The
APP_DOMAINvariable is automatically added or updated in your.envfile - Subdomain Support: When using subdomains, the full domain is automatically constructed using
APP_DOMAIN(e.g.,tenant.APP_DOMAIN)
Creating Tenant Users
Create users for specific tenants with roles and permissions:
# Interactive mode php artisan tenant:user-create # Non-interactive mode php artisan tenant:user-create \ --tenant="my-tenant" \ --name="John Doe" \ --email="john@example.com" \ --role="admin" \ --permissions="manage users,view dashboard" # List available options php artisan tenant:user-create --list-tenants php artisan tenant:user-create --tenant="my-tenant" --list-roles php artisan tenant:user-create --tenant="my-tenant" --list-permissions
Features:
- Interactive tenant selection with numbered options
- Automatic password generation
- Role and permission assignment
- Email validation
- Comprehensive user information display
Using Artisan Commands (Non-Interactive)
# Create a new tenant with all options (plan slug must exist in database) php artisan tenancy:create "Acme Corp" \ --subdomain="acme" \ --database="acme_db" \ --plan="premium" \ --active \ --expires="2025-12-31" # Create with domain php artisan tenancy:create "Acme Corp" --domain="acme.com" # Create with subdomain php artisan tenancy:create "Acme Corp" --subdomain="acme"
Note: When using --plan, the plan slug must exist in the tenancy_plans table. If a plan is provided, a subscription will be automatically created for the tenant.
Programmatically
use AngelitoSystems\FilamentTenancy\Facades\Tenancy; // Create a new tenant $tenant = Tenancy::createTenant([ 'name' => 'Acme Corporation', 'slug' => 'acme-corp', 'domain' => 'acme.com', 'is_active' => true, ]); // Switch to tenant context Tenancy::switchToTenant($tenant); // Run code in tenant context Tenancy::runForTenant($tenant, function () { // This code runs in the tenant's database context User::create(['name' => 'John Doe', 'email' => 'john@acme.com']); }); // Switch back to central context Tenancy::switchToCentral();
Working with Models
User Model with Roles & Permissions
Add the HasRoles trait to your User model to enable role-based access control:
<?php namespace App\Models; use AngelitoSystems\FilamentTenancy\Concerns\HasRoles; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use HasRoles; // Your model code... }
Using Roles and Permissions
// Assign roles $user->assignRole('admin'); $user->syncRoles(['admin', 'editor']); // Check roles $user->hasRole('admin'); $user->hasAnyRole(['admin', 'editor']); // Assign permissions $user->givePermissionTo('manage users'); $user->syncPermissions(['manage users', 'view dashboard']); // Check permissions $user->hasPermissionTo('manage users'); $user->hasAnyPermission(['manage users', 'edit posts']);
Asset Sharing
Use the tenant_asset() helper to access shared assets:
<!-- In Blade templates --> <link href="{{ tenant_asset('css/app.css') }}" rel="stylesheet"> <script src="{{ tenant_asset('livewire/livewire.js') }}" defer></script> <link href="{{ tenant_asset('filament/assets/app.css') }}" rel="stylesheet">
The helper automatically:
- Checks for the asset in the tenant's storage disk
- Falls back to the central storage disk if not found
- Uses Laravel's
asset()helper as final fallback
Tenant Models
For models that belong to tenants, use the BelongsToTenant trait:
use AngelitoSystems\FilamentTenancy\Concerns\BelongsToTenant; use Illuminate\Database\Eloquent\Model; class User extends Model { use BelongsToTenant; // Your model code... }
Central/Landlord Models
For models that should always use the central database, use the UsesLandlordConnection trait:
use AngelitoSystems\FilamentTenancy\Concerns\UsesLandlordConnection; use Illuminate\Database\Eloquent\Model; class Plan extends Model { use UsesLandlordConnection; // Your model code... }
Filament Panel Configuration
Landlord Panel
Create a landlord panel for managing tenants:
// app/Providers/Filament/AdminPanelProvider.php use AngelitoSystems\FilamentTenancy\FilamentPlugins\TenancyLandlordPlugin; public function panel(Panel $panel): Panel { return $panel ->id('admin') ->path('/admin') ->plugin(TenancyLandlordPlugin::make()) // ... other panel configuration }
Tenant Panel
Create a tenant panel:
// app/Providers/Filament/TenantPanelProvider.php use AngelitoSystems\FilamentTenancy\FilamentPlugins\TenancyTenantPlugin; public function panel(Panel $panel): Panel { return $panel ->id('tenant') ->path('/admin') ->plugin(TenancyTenantPlugin::make()) // ... other panel configuration }
Middleware
The package provides several middleware for tenant management:
-
InitializeTenancy:- Automatically resolves tenant from domain/subdomain
- Returns custom 404 page if tenant is not found (if published, otherwise standard 404)
- Verifies tenant is active before allowing access
- Allows access to landlord/admin routes even with inactive tenants (configurable)
- Registered globally by default (can be disabled in config)
-
EnsureTenantAccess:- Ensures a tenant is present and active
- Returns 404 if no tenant is found
- Returns 403 if tenant is inactive or expired
-
PreventAccessFromCentralDomains: Prevents tenant access from central domains
Custom 404 Page
The package includes a beautiful, personalized 404 page for tenant not found errors. During installation, you'll be asked if you want to publish the components and views for customization.
Publishing Components
# Publish views (Blade templates) php artisan vendor:publish --tag="filament-tenancy-views" # Publish Livewire component (optional, requires Livewire) php artisan vendor:publish --tag="filament-tenancy-components"
Published Files
If you choose to publish during installation:
- Views:
resources/views/vendor/filament-tenancy/errors/tenant-not-found.blade.php - Livewire Component:
app/Livewire/TenantNotFound.php(if Livewire is available)
Customization
Once published, you can fully customize:
- Blade View: Edit
resources/views/vendor/filament-tenancy/errors/tenant-not-found.blade.phpto change the design, colors, layout, or content - Livewire Component: Edit
app/Livewire/TenantNotFound.phpto add dynamic functionality or interactivity
Automatic Registration
The installer automatically registers the custom 404 page in bootstrap/app.php (Laravel 11) for handling tenant not found errors. The page will:
- Display a beautiful error message
- Show request details (domain, resolver, APP_DOMAIN)
- Provide a link back to the homepage
- Work without Livewire if not published
Without Publishing
If you choose not to publish, the package will use its internal views and components. The 404 page will still work, but you won't be able to customize it.
Database Migrations
Running Tenant Migrations
# Run migrations for all tenants php artisan tenant:migrate # Run migrations for a specific tenant php artisan tenant:migrate --tenant=1 # Run fresh migrations with seeding php artisan tenant:migrate --fresh --seed
Creating Tenant-Specific Migrations
Place tenant-specific migrations in database/migrations/tenant/:
php artisan make:migration create_tenant_users_table --path=database/migrations/tenant
Events
The package dispatches several events:
TenantCreated: When a new tenant is createdTenantDeleted: When a tenant is deletedTenantSwitched: When switching between tenants
use AngelitoSystems\FilamentTenancy\Events\TenantCreated; Event::listen(TenantCreated::class, function (TenantCreated $event) { // Handle tenant creation $tenant = $event->tenant; });
Advanced Usage
Custom Tenant Resolution
You can extend the tenant resolver for custom logic:
use AngelitoSystems\FilamentTenancy\Support\TenantResolver; class CustomTenantResolver extends TenantResolver { public function resolve(Request $request): ?Tenant { // Your custom resolution logic return parent::resolve($request); } } // Register in a service provider $this->app->bind(TenantResolver::class, CustomTenantResolver::class);
Custom Database Configuration
Override database configuration per tenant:
$tenant = Tenant::find(1); $tenant->update([ 'database_host' => 'custom-host.com', 'database_name' => 'custom_database', 'database_username' => 'custom_user', 'database_password' => 'custom_password', ]);
Tenant Data Storage
Store additional tenant data using the JSON data column:
$tenant->data = [ 'settings' => [ 'theme' => 'dark', 'timezone' => 'UTC', ], 'features' => ['feature1', 'feature2'], ]; $tenant->save(); // Access data $theme = $tenant->data['settings']['theme'] ?? 'light';
APP_DOMAIN Configuration
The APP_DOMAIN environment variable is used for subdomain-based tenancy. It's automatically detected and configured during tenant creation:
Automatic Detection:
- When running
php artisan tenancy:create, the package checks yourAPP_URL - If
APP_URLcontains a valid domain (e.g.,http://hola.test), it suggests using it asAPP_DOMAIN - If
APP_URLis localhost or has a port, you'll be prompted to configureAPP_DOMAINmanually
Manual Configuration:
APP_DOMAIN=hola.test
Usage:
- When creating tenants with subdomains, the full domain is automatically constructed:
{subdomain}.{APP_DOMAIN} - For example, if
APP_DOMAIN=hola.testand subdomain isacme, the full domain becomesacme.hola.test - The
Tenant::getFullDomain()method usesAPP_DOMAINwhen available, falling back tocentral_domainsconfiguration
Example:
// With APP_DOMAIN=hola.test configured $tenant = Tenant::create([ 'name' => 'Acme Corp', 'subdomain' => 'acme', ]); echo $tenant->getFullDomain(); // Output: acme.hola.test echo $tenant->getUrl(); // Output: http://acme.hola.test
Testing
Run the package tests:
composer test
Debug Logging
The package includes enhanced debug logging that is environment-aware:
DebugHelper Class
The DebugHelper class provides environment-aware logging:
use AngelitoSystems\FilamentTenancy\Support\DebugHelper; // Only logs when APP_ENV=local AND APP_DEBUG=true DebugHelper::info('Tenant created', ['tenant_id' => $tenant->id]); DebugHelper::debug('Connection details', $connectionData); DebugHelper::warning('Potential issue detected', $context); // Always logs regardless of environment DebugHelper::error('Critical error occurred', $errorData); DebugHelper::critical('System failure', $criticalData);
Environment Configuration
# Enable debug logging APP_ENV=local APP_DEBUG=true # Production settings (logs only errors/criticals) APP_ENV=production APP_DEBUG=false
Log Behavior
- Development (APP_ENV=local, APP_DEBUG=true): All logs are visible
- Production (APP_ENV=production OR APP_DEBUG=false): Only errors and criticals are logged
- Debug/Info/Warning: Only shown in development environment
- Error/Critical: Always logged regardless of environment
Security
This package includes several security features:
- Cross-tenant isolation: Prevents data leakage between tenants
- Domain validation: Ensures tenants can only be accessed from their domains
- Database separation: Each tenant has its own database
- Middleware protection: Automatic tenant context validation
- Automatic 404 for invalid domains: Domains/subdomains that don't match any tenant automatically return a beautiful custom 404 page
- Customizable 404 page: Personalized error page with request details and optional Livewire component support
- Active tenant verification: Only active tenants can be accessed (checks
is_activeandexpires_at) - Central domain protection: Central domains are protected from tenant resolution
Contributing
Please see CONTRIBUTING.md for details.
License
This package is currently available for public use, but will transition to a license-based distribution model in the future.
โ๏ธ License Terms & Usage Rights
Current Status: Public Access (Temporary)
- โ You CAN: Use this software in your projects (personal, commercial, educational)
- โ You CAN: Install and use the package via Composer
- โ You CAN: Customize configurations and extend functionality
- โ You CANNOT: Create replicas, forks, or copies of this package
- โ You CANNOT: Redistribute this package as your own
- โ You CANNOT: Remove or modify license headers
- โ You CANNOT: Use this package to create competing multi-tenancy solutions
๐ฎ Future Licensing Model
Important: This package will transition to a paid license model in the future. Users who adopt the package now will receive preferential treatment when licensing becomes available.
- License-based distribution (coming soon)
- Commercial use will require a valid license
- Enterprise features will be license-gated
- Early adopters will have migration paths to licensed versions
โ ๏ธ What Happens If You Violate the License?
Legal Consequences:
- You may be subject to legal action for copyright infringement
- Distribution of unauthorized copies may result in cease and desist orders
- Commercial use without proper licensing will be pursued legally
- Creation of replicas or competing solutions will be treated as intellectual property theft
Technical Consequences:
- Package updates may include license validation
- Unauthorized usage may be detected and blocked
- Support will not be provided to unlicensed users
- Access to future versions may be restricted
๐ License Compliance
To ensure compliance:
- โ Use the package via official Composer repository only
- โ Do not copy, fork, or replicate the source code
- โ Respect intellectual property rights
- โ Contact us for licensing inquiries: angelitosystems@gmail.com
Current License: MIT License (subject to above restrictions)
For complete license terms, please read the LICENSE file.
Available Commands
Central Database Commands
# Complete central database setup with admin creation php artisan filament-tenancy:setup-central --create-admin # Seed central database with roles and permissions php artisan filament-tenancy:seed-central # Create central admin user with Super Admin role php artisan filament-tenancy:create-central-admin
Tenant Management Commands
# Interactive tenant creation php artisan tenancy:create # List all tenants php artisan tenancy:list # Delete a tenant php artisan tenancy:delete # Create tenant user with roles php artisan tenant:user-create
Migration Commands
# Run migrations for specific tenant php artisan tenant:migrate # Rollback tenant migrations php artisan tenant:rollback # Fresh tenant database php artisan tenant:fresh
Monitoring Commands
# Monitor tenant connections
php artisan filament-tenancy:monitor-connections
Documentation
Additional Guides
- PayPal Configuration Guide - Complete guide for setting up PayPal payment integration, including webhooks, credentials, and troubleshooting.
Credits
Support
For support, please open an issue on GitHub or contact us at angelitosystems@gmail.com.