Is there a Phoenix VPS Deployment Guide?

I think my problem is that I still do not quite understand some features of Phoenix components.
Thanks to your suggestion, I just made some search on how not to mount a Phoenix endpoint and I found this blog post that gives me a lot of details on one easy way to implement Routing in Phoenix Umbrella Apps.
it’s a bit outdated, but I should be able to adapt it to Phoenix 1.4 projects.

To quickly sum up the post, I will add a third minimal Phoenix app (proxy_app) to the umbrella project. That app will be the main point of contact to the outside world (or one of the existing app could also play this role as you suggested).

Since this app will be the actual web server, we should disable the server setting in the other two:

# apps/client/config/config.exs
config :client, Client.Web.Endpoint, server: false

# apps/admin/config/config.exs
config :admin, Admin.Web.Endpoint, server: false

# apps/proxy/config/config.exs
config :proxy, Proxy.Endpoint, server: true

The proxy app endpoint will look like following:

defmodule Proxy.Endpoint do
  use Phoenix.Endpoint, otp_app: :proxy

  @base_host_regex ~r|\.?mydomain.*$|
  @subdomains %{
    "admin" => Admin.Web.Endpoint,
    "client" => Client.Web.Endpoint
  @default_host Client.Web.Endpoint

  def init(opts), do: opts

  def call(conn, _) do
    with subdomain <- String.replace(host, @base_host_regex, ""),
         endpoint <- Map.get(@subdomains, subdomain, @default_host) do, endpoint.init())

If anyone think there is any problem with that way of handling the Routing , please let me know. ^^


Looks good to me. :slight_smile:

1 Like

I there an actual tutorial on how to deploy Phoenix using only cowboy?

What do you mean using only cowboy? It uses only cowboy by default, so unless you changed it?

I think @Nvim meant how to deploy a phoenix application without a reverse proxy like nginx in front of it. Hence the “only cowboy”.

Op: I think you should not forgoe setting up a reverse proxy in front of you application. From an ops perspective it is probably much easier to integrate nginx with an automated SSL setup. Also you get things like rate limiting, basic auth, static file handling, etc. out of the box with nginx.

It seem the advice by @gutschilla is solid.

Personally I deploy elixir projects via GitLab CI and some bash-scripts…


yes but how do you set up in a VPS? For instance run mix.phx.server automatically? A complete step by step guide would be helpful.

Usually you don’t, you use releases in a docker instead or bare, and their lifecycle be managed by docker or systemd respectively.

Distillery has documentation for both variants.


I wrote a guide a while back ago as well, which very much uses the stack you desire: Using LetsEncrypt with Phoenix (behind Nginx). How to make this more optimal?

1 Like

I deploy docker’s for my personal projects. At work I deploy into a systemd management full VM, so systemd manages all the launching and so forth. I’ve documented how in PidFile - create and manage a PID file from the BEAM process if curious, but I recommend docker when possible.


Do you have any guide how you are doing your releases with Docker?

I am building an Elixir Docker Stack for development, but I would like to also include a release and deploy command :wink:

No guide but nothing special about it. I just have a builder image that brings in otp/elixir/rust, builds, then copies the compiled release to the main image and run that, nothing special or out of the norm.

Why would you need a release or deploy commands? The ‘release’ is building the image, the deploy is loading the docker image, docker handles it all.

You mean that docker does docker build --tag organization/project:tag .?

So this is what I want to wrap in the Elixir Docker Stack, plus the build arguments. Basically just a simple wrapper around this command, that will use a Docker image in the root of the project or a default one provided by the stack.

When i used the term deploy I was not referring to docker deploy, but instead to a command to deploy the release into the target server.

If I end-up to include the release and deploy commands in the Elixir Docker Stack, they will target only pet projects that we deploy to the likes of Digital Ocean, Linode or similar.

I don’t even make a wrapper because I make a different tag much of the time (so I have a couple old versions around in case I need to switch back to them quickly), it’s simple enough as it is. :slight_smile:

I use docker swarm with docker compose for that, so it’s still docker. ^.^

I mean to deploy into the server, not on the server :wink:

Yes, that’s what Docker Swarm does, it can deploy into remote systems. :slight_smile:
Docker-Compose defines how it is setup and what it links with.
And Docker itself does the containerization handling.
They are all installed with docker itself as they are just other parts of the docker ecosystem. :slight_smile:

1 Like

Oh I was not aware of this bit, but I know about using docker-compose to instruct docker how to do the containerization.

Yep, docker-swarm does the orchestration, it allows you to deploy to many systems at once, a specific system of a specific types, etc… etc… etc… :slight_smile:
It uses docker-compose to actually do the setup on the remote systems after it’s deployed it.
And docker-compose uses docker to containerize.
It’s just a lot of layers, like an onion or an ogre. ^.^


I use Docker a lot for my development workflow, but never to release and deploy to production, thus I have a lot of catch-up to do here :wink:

For now I will keep the Elixir Docker Stack with focus on an easy development workflow, and with the option for compiling Erlang, Elixir and Phoenix from their git repos.

Later I will look if it makes sense to wrap docker swarm and the docker compose file :wink:

1 Like

After running phx.server on detached mode, I can its id using ps command. How do I find phx.server’s id quickly just I need to use kill command o stop it? Also is it better to put phx.server on systemd? Any examples on putting phxserver on systemd?

Use @OvermindDL1’s pid_file.ex for that. Here’s my setup: