Help with structuring an umbrella app /w Ecto, Phoenix, and Subdomains

Hi there,

I am working towards porting a Rails app over to Elixir / Phoenix. The site has two reasonably separate sets of functionality, with a few shared pieces of data/logic between the two.

Currently these separate pieces of functionality are routed to separately on the Rails app via subdomains, and share a database. The sub-projects do need to call across to each other to perform a limited set of actions/operations, but they are best kept separate as they have different purposes and authentication mechanisms.

I’d like to organize it as an umbrella project, and had a few additional hopes for a setup that would work. I was hoping someone could tell me if this is possible, and let me know how to set it up properly (I’m basically brand new to Elixir).

What I’m hoping will work is something like the following:

Umbrella Project (Myapp)
|
| —> Functionality A (Myapp.A)
|
| --> Functionality B (Myapp.B)
|
| --> Shared functionality (Myapp.Shared)
|
| --> Shared database repo (Myapp.Repo)

I’d like to somehow get phoenix working in such a way that:

  • If mix phoenix.server is called from myapp/apps/a, I can develop the website for Functionality A on localhost:4000 (i.e. development only)
  • If mix phoenix.server is called from myapp/apps/b, I can develop the website for Functionality B on localhost:4000 (i.e. development only)
  • If mix phoenix.server is called from the umbrella root myapp (i.e. in production), it routes between Myapp.A and Myapp.B based on subdomain.

Is this possible? How would I go about configuring this?

3 Likes

Give a look on this guy. You can give the same look at the whole repo, is a very well organized umbrella project in my opinion. :slight_smile:

EDITED: the repo have the same situation, but every phoenix server have a mapping to its own port, and the default port is mapped to the master_proxy app.

3 Likes

Thank you! I’ll have a look :+1:

An umbrella project itself is not an app, rather it’s a convenience collection of apps that makes it easier to manage common things among apps, like sharing dependencies, configuration, etc.

Without knowing the particulars, I’m not 100% on this, but I think I would structure your project like this:

my_app_umb
|–my_app (MyApp)
|–my_app_web (MyAppWeb)
|–a (A)
|–b (B)

The shared and repo code would go into your MyApp (casing naming conventions) application, unless the repo really is extensive enough to have its own application. And the Myapp.A would just be A, just like in the linked project @kelvinst provided, e.g. Money instead of Bank.Money.

I am unsure of your goals on the development of A vs. B :thinking:, but I think you could create separate config/dev_a.exs and config/dev_b.exs to help you set up your web app to focus on one or the other. :a: :eyes: :b:

It sounds like @bkparso has a single site, so would this be a good design decision as opposed to a single phoenix web application and using routing? :thinking:

I would think that the original design decision of using the master proxy is either that the two web apps (backoffice and bank_web) had to live on separate servers or that they started off as separate web apps and were brought together to a single project and it wasn’t worth it to refactor it into a single web app. What else would be the benefit of the proxy web app approach?

EDIT: Found another thread specifically talking about ExAdmin and one vs. two phoenix apps.

It’s probably better described as two separate web sites, that are linked in terms of like 5% of their functionality.

One site is www.myapp.com (containing the A functionality) and the other is functionality.myapp.com (with the B functionality). They serve two sides of marketplace - the users are separate between the two apps but they need to share data.

I’ve started writing the code for A and B as separate apps, and I think that will work fine (they just need to share a database). I suppose the heart of my question is around if there’s a good way to make this two separate Phoenix apps listening on different ports for dev, but a single port for prod (Heroku). I have a feeling that I might be able to lift the MasterProxy stuff out of the Acme example.

1 Like

Sorry if it’s a downer, but the primary reason to separate backoffice and bank_web was to show that it is possible :wink: (that there isn’t anything special about Phoenix, and you can have many Phoenix apps in an umbrella; and that there isn’t anything special about ExAdmin and that it works in an umbrella by design. Hey it was supposed to be an experimental project after all!)

I think having separate web apps would work best if they’re pretty independent, e.g. in the case of the Bank there could be a separate Support, Investments etc apps - think really independent UIs. I guess in many cases it might be more practical to start with a single web app, and slice it up afterwards if it makes sense. Otherwise, the overhead may not be worth it initially: more complicated deployment and not being able to use routes (*_path etc) across apps, by default)

4 Likes

Well, master_proxy is not a good name for that application. It actually does not redirect to a living server, and yes just call’s the server endpoint in the same server. Here’s the code that does that: https://github.com/wojtekmach/acme_bank/blob/master/apps/master_proxy/lib/master_proxy/plug.ex#L6-L13

1 Like

Of course…naming things is hard! :laughing:

I came across that code as well. I think it’s an interesting example of a “proxy endpoint” and it’s :cool: to know that that style of proxy exists (would have never occurred to me). One of those things I file in the back of my mind in case the need arises. :thinking:

1 Like

what if the web apps are separate in user functionality, but are big (LOC) and share UI constructs (CSS, JS, UX)? What I’m suggesting is that there is ample reason to keep separate web apps, and yet they have shared dependancies (JS, CSS, external libraries - npm?). Does having multiple web apps still make sense?