GithubHelp home page GithubHelp logo

tenancy / multi-tenant Goto Github PK

View Code? Open in Web Editor NEW
2.5K 87.0 387.0 1.55 MB

Run multiple websites using the same Laravel installation while keeping tenant specific data separated for fully independent multi-domain setups, previously github.com/hyn/multi-tenant

Home Page: https://tenancy.dev

License: MIT License

PHP 98.53% Shell 0.58% Blade 0.88%
laravel multi-tenancy multi-domain tenancy multi-tenant tenant saas hacktoberfest

multi-tenant's Introduction

Packagist build status codecov Packagist Codacy Badge Join our Discord server Mentioned in Awesome Laravel

The unobtrusive Laravel package that makes your app multi tenant. Serving multiple websites, each with one or more hostnames from the same codebase. But with clear separation of assets, database and the ability to override logic per tenant.

Suitable for marketing companies that like to re-use functionality for different clients or start-ups building the next software as a service.


Offers:

  • Integration with the awesome Laravel framework.
  • Event driven, extensible architecture.
  • Close - optional - integration into the web server.
  • The ability to add tenant specific configs, code, routes etc.

Database separation methods:

  • One system database and separated tenant databases (default).
  • Table prefixed in the system database.
  • Or .. manually, the way you want, by listening to an event.

Complete documentation covers more than just the installation and configuration.

Requirements, recommended environment

  • Laravel 9.0+.
  • PHP 8.0+
  • Apache or Nginx.
  • MySQL, MariaDB, or PostgreSQL.

Please read the full requirements in the documentation.

Installation

composer require hyn/multi-tenant

Automatic service registration

Using auto discovery, the tenancy package will be auto detected by Laravel automatically.

Manual service registration

In case you want to disable webserver integration or prefer manual integration, set the dont-discover in your application composer.json, like so:

{
    "extra": {
        "laravel": {
            "dont-discover": [
                "hyn/multi-tenant"
            ]
        }
    }
}

If you disable auto discovery you are able to configure the providers by yourself.

Register the service provider in your config/app.php:

    'providers' => [
        // [..]
        // Hyn multi tenancy.
        Hyn\Tenancy\Providers\TenancyProvider::class,
        // Hyn multi tenancy webserver integration.
        Hyn\Tenancy\Providers\WebserverProvider::class,
    ],

Deploy configuration

First publish the configuration and migration files so you can modify it to your needs:

php artisan vendor:publish --tag tenancy

Open the config/tenancy.php and config/webserver.php file and modify to your needs.

Make sure your system connection has been configured in database.php. In case you didn't override the system connection name the default connection is used.

Now run:

php artisan migrate --database=system

This will run the required system database migrations.


Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

Contributors


License and contributing

This package is offered under the MIT license. In case you're interested at contributing, make sure to read the contributing guidelines.

Testing

Run tests using:

vendor/bin/phpunit

If using MySQL, use:

LIMIT_UUID_LENGTH_32=1 vendor/bin/phpunit

Please be warned running tests will reset your current application completely, dropping tenant and system databases and removing the tenancy.json file inside the Laravel directory.

Changes

All changes are covered in the changelog.

Contact

Get in touch personally using;

multi-tenant's People

Contributors

ametad avatar arlonantonius avatar awebartisan avatar bastien-phi avatar bkintanar avatar deltoss avatar drbyte avatar fabmade avatar fletch3555 avatar ianlchapman avatar janiskelemen avatar jazo avatar joshjacks avatar londoh avatar luceos avatar mikebronner avatar mintunitish avatar mnapoli avatar monkeywithacupcake avatar nzulfigarov avatar plytas avatar pouler avatar sebastianschoeps avatar stancl avatar sti3bas avatar styxyk avatar therour avatar thijmen avatar tnovalis avatar vpratfr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

multi-tenant's Issues

[webserver] unique users need to be created

In order to assign the correct user rights, we need to be able to create the unix users, assign them to a specified group and set them in the specific server configurations.

document the flow of the tenancy system

How is the tenant decided, what effect has the middleware.. etc

  • how is the tenant decided upon
  • what is the middleware doing
  • document how global vs localized works

webserver config not picked up when creating website

@vik0803 has reported the following backtrace:

User configuration saved.
Starting publishing vendor assets.
Copied Directory [/vendor/cartalyst/sentinel/src/migrations] To [/database/migrations]
Copied Directory [/vendor/hyn/multi-tenant/database/migrations] To [/database/migrations]
Copied Directory [/vendor/laracasts/flash/src/views] To [/resources/views/vendor/flash]
Copied Directory [/vendor/laraflock/dashboard/src/Resources/views] To [/resources/views/vendor/dashboard]
Copied Directory [/vendor/laraflock/dashboard/src/Database/Migrations] To [/database/migrations]
Copied Directory [/vendor/laraflock/dashboard/src/Resources/assets] To [/public/vendor/laraflock]
Copied Directory [/vendor/hyn/management-interface/resources/views] To [/resources/views/hyn/management-interface]
Copied Directory [/vendor/hyn/webserver/database/migrations] To [/database/migrations]
Publishing complete for tag []!
Publishing vendor assets finished.
Original Auth removed! Enjoy your fresh start.
Starting database migrations.
No running tenancy migration, falling back on native laravel migrate command due to missing tenant option.
Migration table created successfully.
Migrated: 2014_07_02_230147_migration_cartalyst_sentinel
Migrated: 2015_05_01_111209_hmt_tenants_table
Migrated: 2015_05_01_111210_hmt_websites_table
Migrated: 2015_05_01_111211_hmt_hostnames_table
Migrated: 2015_05_19_000000_hws_ssl_certificates_table
Migrated: 2015_05_19_000001_hws_ssl_hostnames_table
Migrated: 2015_05_19_000002_hws_ssl_hostnames_drop_hostname_id
Migrated: 2015_06_26_031155_create_permissions_table
Database migrations finished.
Setup is complete. Keep coding!
First off, migrations for the packages will run.
No running tenancy migration, falling back on native laravel migrate command due to missing tenant option.
Nothing to migrate.


  [ErrorException]                         
  Invalid argument supplied for foreach()  


Exception trace:
 () at /vendor/hyn/webserver/src/Helpers/ServerConfigurationHelper.php:28
 Illuminate\Foundation\Bootstrap\HandleExceptions->handleError() at /vendor/hyn/webserver/src/Helpers/ServerConfigurationHelper.php:28
 Hyn\Webserver\Helpers\ServerConfigurationHelper->createDirectories() at /vendor/hyn/multi-tenant/src/Commands/SetupCommand.php:126
 Hyn\MultiTenant\Commands\SetupCommand->handle() at n/a:n/a
 call_user_func_array() at /vendor/laravel/framework/src/Il

cannot delete website

Failing presenter:

Call to a member function present() on null

management-interface/­src/­Http/­Controllers/­HostnameController.php48

return (new HostnameValidator())->catchFormRequest($hostname, redirect()->route('management-interface.website.read', $hostname->website->present()->urlArguments));

Option to set website identifier during setup

I need to create two tenants:

  • customer-foo.example.com
  • customer-far.example.com

as the identifier is currently based on the first 10 characters of the domain name, both website ids will be customer-f
This will cause the setup to fail as the websites->identifier is a unique key in the database.

It would be nice if you could set an identifier during setup.

document how to scale

  • what is the effect of the continuous 2 db connections
  • how can you optimize the webserver to allow for one system connection and one tenant connection, add that to the installer too
  • any ideas how to seperate tenancy over multiple machines

[webserver] SSL generation uncertain

Generating SSL certificate files in storage seems not to be working, also this functionality is hardly finished. In order to fully test this, hyn/management-interface must be extended to include adding certificates. Hostnames are automatically parsed from the certificate.

[webserver] onCreate not called correctly

As reported by @thijsvdanker; it seems the onCreate is called without hostnames and therefor returns void. Once a hostname is added the website is touched and so onCreate should again be called from within onUpdate, but this is not (always) the case.

In order to solve this at least:

  • create a unit test that proves files are generated for nginx, apache etc (if enabled)
  • see what the process is during create, update
  • ensure files are generated

Bash installation error

Hi again.

Sorry but when I use or bash installer.sh on Ubuntu I get an error on final setup.

I install supervisorand beanstalk also.

Laravel log:

[2016-05-13 11:09:43] production.ERROR: ErrorException: Array to string conversion in /var/www/vendor/pda/pheanstalk/src/Command/UseCommand.php:40
Stack trace:
#0 /var/www/vendor/pda/pheanstalk/src/Command/UseCommand.php(40): Illuminate\Foundation\Bootstrap\HandleExceptions->handleError(8, 'Array to string...', '/var/www/vendor...', 40, Array)
#1 /var/www/vendor/pda/pheanstalk/src/Connection.php(100): Pheanstalk\Command\UseCommand->getCommandLine()
#2 /var/www/vendor/pda/pheanstalk/src/Pheanstalk.php(396): Pheanstalk\Connection->dispatchCommand(Object(Pheanstalk\Command\UseCommand))
#3 /var/www/vendor/pda/pheanstalk/src/Pheanstalk.php(347): Pheanstalk\Pheanstalk->_dispatch(Object(Pheanstalk\Command\UseCommand))
#4 /var/www/vendor/laravel/framework/src/Illuminate/Queue/BeanstalkdQueue.php(71): Pheanstalk\Pheanstalk->useTube(Array)
#5 /var/www/vendor/laravel/framework/src/Illuminate/Queue/BeanstalkdQueue.php(58): Illuminate\Queue\BeanstalkdQueue->pushRaw('{"job":"Illumin...', Array)
#6 /var/www/vendor/laravel/framework/src/Illuminate/Queue/Queue.php(33): Illuminate\Queue\BeanstalkdQueue->push(Object(Hyn\Webserver\Commands\WebserverCommand), '', Array)
#7 /var/www/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php(261): Illuminate\Queue\Queue->pushOn(Array, Object(Hyn\Webserver\Commands\WebserverCommand))
#8 /var/www/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php(243): Illuminate\Bus\Dispatcher->pushCommandToQueue(Object(Illuminate\Queue\BeanstalkdQueue), Object(Hyn\Webserver\Commands\WebserverCommand))
#9 /var/www/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php(175): Illuminate\Bus\Dispatcher->dispatchToQueue(Object(Hyn\Webserver\Commands\WebserverCommand))
#10 /var/www/vendor/laravel/framework/src/Illuminate/Foundation/Bus/DispatchesJobs.php(17): Illuminate\Bus\Dispatcher->dispatch(Object(Hyn\Webserver\Commands\WebserverCommand))
#11 /var/www/vendor/hyn/webserver/src/Observers/WebsiteObserver.php(15): Hyn\Webserver\Observers\WebsiteObserver->dispatch(Object(Hyn\Webserver\Commands\WebserverCommand))
#12 [internal function]: Hyn\Webserver\Observers\WebsiteObserver->created(Object(Hyn\MultiTenant\Models\Website))
#13 /var/www/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(347): call_user_func_array(Array, Array)
#14 [internal function]: Illuminate\Events\Dispatcher->Illuminate\Events\{closure}(Object(Hyn\MultiTenant\Models\Website))
#15 /var/www/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(221): call_user_func_array(Object(Closure), Array)
#16 /var/www/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php(1650): Illuminate\Events\Dispatcher->fire('eloquent.create...', Array)
#17 /var/www/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php(1578): Illuminate\Database\Eloquent\Model->fireModelEvent('eloquent.create...', false)
#18 /var/www/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php(1452): Illuminate\Database\Eloquent\Model->performInsert(Object(Illuminate\Database\Eloquent\Builder), Array)
#19 /var/www/vendor/hyn/framework/src/Models/AbstractModel.php(96): Illuminate\Database\Eloquent\Model->save(Array)
#20 /var/www/vendor/hyn/framework/src/Repositories/BaseRepository.php(47): Hyn\Framework\Models\AbstractModel->save()
#21 /var/www/vendor/hyn/multi-tenant/src/Commands/SetupCommand.php(145): Hyn\Framework\Repositories\BaseRepository->create(Array)
#22 [internal function]: Hyn\MultiTenant\Commands\SetupCommand->handle()
#23 /var/www/vendor/laravel/framework/src/Illuminate/Container/Container.php(507): call_user_func_array(Array, Array)
#24 /var/www/vendor/laravel/framework/src/Illuminate/Console/Command.php(150): Illuminate\Container\Container->call(Array)
#25 /var/www/vendor/symfony/console/Command/Command.php(256): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#26 /var/www/vendor/laravel/framework/src/Illuminate/Console/Command.php(136): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#27 /var/www/vendor/symfony/console/Application.php(841): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#28 /var/www/vendor/symfony/console/Application.php(189): Symfony\Component\Console\Application->doRunCommand(Object(Hyn\MultiTenant\Commands\SetupCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#29 /var/www/vendor/symfony/console/Application.php(120): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#30 /var/www/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(107): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#31 /var/www/artisan(35): Illuminate\Foundation\Console\Kernel->handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#32 {main}  

How to fix?

Thanks

Persist session across subdomain

In order to make multi-tenancy to work with multiple subdomain, remember to configure config/session.php domain attribute to your domain name.

config/session.php

'domain' => '.lvh.me'

drop tenant terminology from code

and clean up documentation.

Tenant can have multiple interpretations:

  • the customer (in use)
  • the website

Let's rename all references to the current Tenant to a Customer.

Media alias not working on localhost Mamp

Hi, I'm just testing your awesome package, but get some problems to run on localhost with MAMP on my MAC.

I follow all instructions, and tenant connection with DB is working right. But mediafolder alias doesn't work.

I have this structure on storage/sites:

* site1
  * media
    * image.jpg
* site2
  * media
    * image.jpg

And this is my apache webserver conf for site 1:

#
#   Auto generated Apache configuration
#       @time: 15:20:16 12-05-2016
#       @author: hyn-me/webserver
#       @website: 1 "starter-on"
#

#
#   Hostnames with certificate
#

#
#   Hostnames without certificate
#
    <VirtualHost *:80>
            ServerAdmin [email protected]

                                        ServerName starter.on

    # public path, serving content
    DocumentRoot /Applications/MAMP/htdocs/tenant/public
    # default document handling
    DirectoryIndex index.html index.php


            # media directory
        alias "/media/" "/Applications/MAMP/htdocs/tenant/storage/sites/1-starter-on/media/"

    # allow cross domain loading of resources
    Header set Access-Control-Allow-Origin "*"

    # logging
    ErrorLog /Applications/MAMP/htdocs/tenant/storage/logs/apache-1-starter-on.error.log
    CustomLog /Applications/MAMP/htdocs/tenant/storage/logs/apache-1-starter-on.access.log combined
</VirtualHost>




<Directory "/Applications/MAMP/htdocs/tenant">
    Options Indexes Includes FollowSymLinks  
    AllowOverride All
    Order allow,deny
    Allow from all
</Directory>

And this is for site2:

#
#   Auto generated Apache configuration
#       @time: 15:20:16 12-05-2016
#       @author: hyn-me/webserver
#       @website: 2 "prueba"
#

#
#   Hostnames with certificate
#

#
#   Hostnames without certificate
#
    <VirtualHost *:80>
            ServerAdmin [email protected]

                                        ServerName prueba.on

    # public path, serving content
    DocumentRoot /Applications/MAMP/htdocs/tenant/public
    # default document handling
    DirectoryIndex index.html index.php


            # media directory
        alias "/media/" "/Applications/MAMP/htdocs/tenant/storage/sites/2-prueba/media/"

    # allow cross domain loading of resources
    Header set Access-Control-Allow-Origin "*"

    # logging
    ErrorLog /Applications/MAMP/htdocs/tenant/storage/logs/apache-2-prueba.error.log
    CustomLog /Applications/MAMP/htdocs/tenant/storage/logs/apache-2-prueba.access.log combined
</VirtualHost>




<Directory "/Applications/MAMP/htdocs/tenant">
    Options Indexes Includes FollowSymLinks  
    AllowOverride All
    Order allow,deny
    Allow from all
</Directory>

The problem is that always get first media alias.

If I visit: http://starter.on/media/a.jpg I get first site photo. This is ok.

But if I visit http://prueba.on/media/a.jpgit returns same photo of site1.

Please, how can I fix it?

Thanks

put back the transactions, fi used in SetupCommand

The observable events for models are fired before the transaction is committed. In order to make this work again we can;

  • create a custom event to listen to
  • put the observable post-(not pre-) events for these models in a pool to be fired once the transaction is committed

hyn/lets-encrypt

Create a package that wraps the let's encrypt api into PHP for use in the hyn multi tenancy package. The package should be generic in the sense that it should be usable by other parties. Close integration with the hyn/multi-tenant package is not a requirement, because this package will be used by a new package hyn/ssl in the future.

Multiple Host Names

After going through the documentation, I found it quite easy to implement but I have a few issues which I don't understand.

1st one is what is the purpose of the user created in first step? Should that user be my client who will own the host-name? What else functionality is provided by that specific user table? Or should I do not care at all about that?

2nd one, for multiple host-name configurations, should I use the same user's tenant->id ? and also in other tables, should i derive the tenant id from the user i created in the first step or should I get the id from host-name

Thanks in advance :)

Artisan multi-tenant:setup with Interface always setup

Hi again.

I found maybe a bug on multi-tenant:setup command.

If you create users with cliinstead a controller and you have ManagementInterface installed, always runs the ManagementInterface setup. I think that is ok if you don't have a user. But if you have a administrator user should not run setup again.

Is that ok?

Thanks

Events on specific actions

Eg for:

  • customer created/modified/deleted
  • website created/modified/deleted
  • hostname created/modified/deleted
  • webserver vhost config rebuild triggered

etc..

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.