Deployment of a Phoenix umbrella application (listening on different ports) to PaaS

Hi folks,

I’m currently working on a Phoenix umbrella application which has two Phoenix applications “under the umbrella”. Each application is configured to listen on a different port:

my_application      # -> Ecto and database stuff
my_appliaction_web  # -> Frontend application listening on port 4000
my_application_api  # -> API application listening on port 5000

As the time comes closer, where I have to deploy the application I wonder how/where to deploy this kind of application. All PaaS providers I have looked at just show examples of deploying a “simple” Phoenix application which just listens on one port. I know the approach of a “master proxy” which is often mentioned when deploying an umbrella application to Heroku, but I think this is not the way I prefer, because I’d like the API under the subdomain api.my_application.com and the frontend under the subdomain www.my_application.com.

Since I’m impressed by Nanobox, I’ve read their docs which describe a way to add additional routing through their boxfile.yml, but I can’t figure it out how to configure it correctly for my setup.

Do you have recommendations for other PaaS providers, which are able to run Phoenix umbrella applications? Configuration examples for e.g. AWS, Heroku etc. are also welcome. :wink:

Many thanks in advance

I’m not sure if they allow more than one port open, but have you checked gigalexir? It is a PaaS specialised to elixir, also it advertises itself with “no connection limits”, whatever they mean with that.

1 Like

I haven’t deployed an umbrella with multiple phoenix apps but on EC2 an umbrella with one phoenix app and nginx, following this tutorial - and adjusted for EC2, so I imagine something like this would work (crude version):

/phoenix_app/config/prod.exs

config :web_app, WebAppWeb.Endpoint,
  http: [port: 4000],
  url: [host: "my_application.com", port: 80],
  cache_static_manifest: "priv/static/cache_manifest.json"

Then
/api_phoenix/config/prod.exs

 config :web_app, WebAppWeb.Endpoint,
      http: [port: 5000],
      url: [host: "api.my_application.com", port: 80],
      cache_static_manifest: "priv/static/cache_manifest.json"

(you might need to tweak these… )

And then on the nginx site file you probably could use something as:

upstream web_app {
  server 127.0.0.1:4000;
}

upstream api {
  server 127.0.0.1:5000;
}

server {
  listen 80;
  server_name api.my_application.com;
  location / {
include proxy_params;
    proxy_redirect off;
    proxy_pass http://api;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade; 
  }
}

server {
  listen 80;
  server_name www.my_application.com my_application.com;
  location / {
    include proxy_params;
    proxy_redirect off;
    proxy_pass http://web_app;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
  }
}

(this is untested though, and isn’t ready for ssl…)

4 Likes

Many thanks for this configuration example :thumbsup:

I think you’re right, a partly manual configuration would be the best option in order to cope with this setup.

In case it’s helpful to anyone, I created a library to help make this easier.

3 Likes