Getting the (Big) picture on Multi-tenant applications

60 views
Skip to first unread message

miguel

unread,
May 22, 2017, 9:00:16 AM5/22/17
to web2py-users
I've only worked with intranet apps so far, but I'm seriously thinking about starting a SaaS webapp. However I'm largely ignorant of the workings of the wild wide web, so please bear with me.

My idea is to get a big picture of the issue of multi-tenancy, some aspects have to do with web2py, others (perhaps most, do not). Web2py is however, my platform of choice, and I would like to have understand how the involved pieces fit together. Hopefully the answers to this post are helpful not just for me but for others evaluating or treading the same route.

My idea is to achieve multi-tenancy using the common:

customername.mydomain.com

where customername changes for each customer. This is quite common and can be observed in webapps such as unfuddle, basecamp and many many others.

My understanding is that this implies:

1. a DNS registration with a wildcard subdomain:
So I will have www.myawesomeapp.com and *.myawesomeapp.com registrations

2. SSL certificates for both www.myawesomeapp.com and *.myawesomeapp.com

3. The server: Apache, Nginx, ... will have some configuration in order to send requests in the form of *.myawesomeapp.com/... to web2py
Is this that "simple"? is this all that is needed so that web2py will start receiving requests with customerXsubdomain.myawesomeapp.com?
(be patient... I've only ever used the built in webserver, a part from a single production site I did long long ago)

4. Lastly, the customer calling can be checked by web2py using request.env.http_host which will hold something like:
fireworksltd.myawesomeapp.com for client connections from customer fireworksltd

so if, has suggested in the book, we use:

db._common_fields.append(Field('request_tenant',
                               default=request.env.http_host,
                               writable=False))

That is it, this is the extent of fiddling in web2py. There is no need fr extra fiddling with db.table.request_tenant.default in function controllers?

And, would it be possible or does it make any sense to somehow make request_tenant default to an integer id? Or is my feeling of reducing record size, senseless knit-picking here?

5. Is it possible to somehow test this feature on localhost? How?

Is my overall picture correct or am I missing anything?

Txs,
Miguel


Massimo Di Pierro

unread,
May 29, 2017, 6:58:40 PM5/29/17
to web2py-users
On Monday, 22 May 2017 08:00:16 UTC-5, miguel wrote:
I've only worked with intranet apps so far, but I'm seriously thinking about starting a SaaS webapp. However I'm largely ignorant of the workings of the wild wide web, so please bear with me.

My idea is to get a big picture of the issue of multi-tenancy, some aspects have to do with web2py, others (perhaps most, do not). Web2py is however, my platform of choice, and I would like to have understand how the involved pieces fit together. Hopefully the answers to this post are helpful not just for me but for others evaluating or treading the same route.

My idea is to achieve multi-tenancy using the common:

customername.mydomain.com

where customername changes for each customer. This is quite common and can be observed in webapps such as unfuddle, basecamp and many many others.

My understanding is that this implies:

1. a DNS registration with a wildcard subdomain:
So I will have www.myawesomeapp.com and *.myawesomeapp.com registrations

2. SSL certificates for both www.myawesomeapp.com and *.myawesomeapp.com

3. The server: Apache, Nginx, ... will have some configuration in order to send requests in the form of *.myawesomeapp.com/... to web2py
Is this that "simple"? is this all that is needed so that web2py will start receiving requests with customerXsubdomain.myawesomeapp.com?
(be patient... I've only ever used the built in webserver, a part from a single production site I did long long ago)

yes. it is that simple.
 

4. Lastly, the customer calling can be checked by web2py using request.env.http_host which will hold something like:
fireworksltd.myawesomeapp.com for client connections from customer fireworksltd

so if, has suggested in the book, we use:

db._common_fields.append(Field('request_tenant',
                               default=request.env.http_host,
                               writable=False)) 

That is it, this is the extent of fiddling in web2py. There is no need fr extra fiddling with db.table.request_tenant.default in function controllers?

That is correct. The only issue is that this many not be the most efficient solution. This is a good solution if you have many domains but not many records for each domain. If you have many domains with many records each you may prefer to simply make a different URI for different domains (something that web2py also allows you to do).

You may have to be careful with sessions. You should have some code like this:

if not session.host: session.host = request.env.http_host
elif session.host != request.env.http_host: raise HTTP(400)

without this code you may be vulnerable to an attack where one tenant can steal his own session and use it with another domain.
Reply all
Reply to author
Forward
0 new messages