Preparing to embark on deployment adventure

The websites I’ve hosted so far run with a MySQL database via PHP (FastCGI) behind a webserver. (Hiawatha, which is security-focused and lightweight.) I’m about to start trying to deploy My First Phoenix site, which is just a test site, and thought I might jot down what I’m thinking here to see if I have a valid approach in mind.

I’m planning to use an Ubuntu 16.04LTS VPS, 64-bit. (Probably Linode.) While I could install Erlang and Elixir on the VPS, I’m thinking I may as well try “releases” as I like the idea of deploying via one archive and not having to manage software versions on the server. Am I right in thinking that if different Phoenix sites on the same server were ever to require different versions of Erlang/Elixir, releases would allow for this?

My workstation is running Ubuntu 16.10 (64-bit), so should I be able to build releases locally and use them on the VPS? If not, very roughly, what kind of stress and build time would a simple Phoenix project being built on a VPS server represent, and what kind of spec would be required?

Based on what I’ve found/read so far, I’m thinking the process/setup could be:

  • edeliver and Distillery to build locally and upload to production
  • Hiawatha webserver to serve static assets, handle TLS termination and reverse proxy to the Elixir (Phoenix) app at localhost:4000.
  • When another Phoenix site is added to the server, set it to use a different port, e.g. 4001 so that Hiawatha can proxy to it based on the request’s hostname.

Alternatively, what are people’s thoughts on using Cowboy without another webserver in between? Is it considered a fast and secure option that’s easy to configure/maintain? I’m hesitant to move away from Hiawatha if I don’t have to as I have relatively high confidence in its security, I’m comfortable with it and it’s simple to configure.

Many thanks.

5 Likes

Yes. The ERTS (Erlang Run-Time System) will be bundled on the same tar package of the release, so it will be self-contained.

Since the versions are different, my first guess is that you can’t (seeing as Erlang Solutions download page separates the packages for different versions of Ubuntu). However, you can always test it on a VM, or better utilize local VMs or Docker to build your release. It will give you more guarantee that it will run as expected.

Those points seem reasonable. I guess that’s a pretty standard setup :slight_smile:

Hmm, I personally wouldn’t go for that. Having it behind a reverse proxy lets you (1) have multiple instances listening on different ports on the same machine, and the webserver on 80/443, and (2) easier in case you want to do rolling upgrades. I think that option will make sense if you have server clusters where taking down an app means taking down a whole server (and you have the reverse proxy on a dedicated server).

2 Likes

Thanks very much for answering those questions. I’ll go ahead based on using a webserver as a reverse proxy then. :sweat_smile:

After a few hours of reading, configuring and smoothing a couple of bumps related to edeliver SSH’ing into ‘localhost’ to build locally on my workstation, I have a release built! :grinning:


I built in Ubuntu 16.10 and deployed it onto a local Ubuntu 14.04 server I have running on my home network. When using mix edeliver commands to query/start, I get:

/srv/www/app_name/project/app_name/erts-8.1/bin/beam.smp: /lib/x86_64-linux-gnu/libtinfo.so.5: no version information available (required by /srv/www/app_name/project/app_name/erts-8.1/bin/beam.smp)

Both my workstation and server have /lib/x86_64-linux-gnu/libtinfo.so.5. Is this the kind of issue that can be caused by building on a different version of Ubuntu? Both environments are Linux 64-bit.

Edit: Due to the messages shown when using mix edeliver to query the staging server, I assumed that the app wasn’t running. But I’ve just checked running processes in htop, and there is a .../app_name/erts-8.1/bin/epmd -daemon process running. Does that mean that the Erlang app is actually running? I’ll try reverse proxying to it…

Edit 2: reverse proxying to it doesn’t seem to work. I’ll continue with the database config tomorrow and try again. :slight_smile:


Also, the release doesn’t seem to include a static directory for assets. I’m thinking I should remove /priv/static from .gitignore so that generated assets are included in the Git repo and subsequent release build - is that right?

It’s hard to tell, I’ve never actually built on different distributions before. However, googling for the error (“libtinfo no version information available”) I came across this which suggests that yeah it’s an outdated version problem, the dynamically linked library’s version of the compiled app doesn’t match the library on the host’s version.

If epmd is the only one running, then no, your app is not running. EPMD is Erlang Port Mapper Daemon, used if you’re building a distributed Erlang system. If the app is running, you should also see something like /app/erts-8.1/bin/beam with lots of flags and arguments.

It shouldn’t be necessary. /priv/static should be in gitignore since it can be regenerated. Have you run MIX_ENV=prod mix phoenix.digest before releasing?

Also, do you have any source of the steps you’re using to deploy (probably tutorials, docs, etc.)? Probably it will give more insight to the errors.

Many thanks for the info and pointers, @bobbypriambodo. Progress has been made…

I’ll write up what I found and the steps I took in full another time, but in brief, I’ve:

  • switched to using my workstation as “staging” to remove any potential OS-version-differing issues;
  • corrected my production port and database settings;
  • added asset building to the edeliver config (the assets needed to be built and digested as part of the edeliver release task on the “build server” rather than in my dev installation before the release task).

The instructions I’ve been following:

And now the app is running via a release in “staging”, complete with assets served from the release’s lib/app_name-0.0.1+x-xxxxxxx/priv/static directory. :smile_cat:

Just one problem that I’ve spotted so far: my CRUD Create operation is not working in the release, though it is in dev.

21:27:49.820 request_id=pm89nebr8omjjfgmdudm5qe5g07f7ctq [info] POST /admin/products/materials
21:27:49.820 request_id=pm89nebr8omjjfgmdudm5qe5g07f7ctq [info] Sent 500 in 396µs
21:27:49.821 [error] #PID<0.1343.0> running AppName.Endpoint terminated
Server: mydomain.com:80 (http)
Request: POST /admin/products/materials
** (exit) an exception was raised:
    ** (UndefinedFunctionError) function Money.Ecto.Type.cast/1 is undefined (module Money.Ecto.Type is not available)
        Money.Ecto.Type.cast("3")
        (ecto) lib/ecto/type.ex:564: Ecto.Type.cast/2
        (ecto) lib/ecto/changeset.ex:464: Ecto.Changeset.cast_field/8
        (ecto) lib/ecto/changeset.ex:423: Ecto.Changeset.process_param/8
        (elixir) lib/enum.ex:1247: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
        (elixir) lib/enum.ex:1247: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
        (ecto) lib/ecto/changeset.ex:391: Ecto.Changeset.do_cast/7
        (app_name) web/models/product/material.ex:16: AppName.Product.Material.changeset/2

Money is in deps() in mix.exs:

  defp deps, do: [
    {:phoenix, "~> 1.2.1"},
    {:phoenix_pubsub, "~> 1.0"},
    {:phoenix_ecto, "~> 3.0"},
    {:postgrex, ">= 0.0.0"},
    {:phoenix_html, "~> 2.6"},
    {:phoenix_live_reload, "~> 1.0", only: :dev},
    {:gettext, "~> 0.11"},
    {:cowboy, "~> 1.0"},
    {:money, "~> 1.2.0"},
    {:edeliver, ">= 1.4.0"},
    {:distillery, ">= 0.10.0", warn_missing: false}
  ]

There is a money directory in the deps directory in the temporary build location.

grep’ing the release version of the app:

$ grep -r "money" ./*
./erl_crash.dump:money
./erl_crash.dump:format_money
Binary file ./lib/app_name-0.0.1+23-3e90aeb/ebin/Elixir.AppName.Api.BannerPriceController.beam matches
Binary file ./lib/app_name-0.0.1+29-5fa1c81/ebin/Elixir.AppName.Api.BannerPriceController.beam matches
Binary file ./lib/app_name-0.0.1+22-10ad675/ebin/Elixir.AppName.Api.BannerPriceController.beam matches
Binary file ./lib/app_name-0.0.1+26-273b832/ebin/Elixir.AppName.Api.BannerPriceController.beam matches
Binary file ./lib/app_name-0.0.1+27-5cdbf9f/ebin/Elixir.AppName.Api.BannerPriceController.beam matches
Binary file ./lib/app_name-0.0.1+21-efda081/ebin/Elixir.AppName.Api.BannerPriceController.beam matches
Binary file ./lib/app_name-0.0.1+25-4a3c61c/ebin/Elixir.AppName.Api.BannerPriceController.beam matches
Binary file ./lib/app_name-0.0.1+30-9ebded0/ebin/Elixir.AppName.Api.BannerPriceController.beam matches
Binary file ./lib/app_name-0.0.1+24-a0d8d13/ebin/Elixir.AppName.Api.BannerPriceController.beam matches
./releases/0.0.1+25-4a3c61c/sys.config: {money,
./releases/0.0.1+29-5fa1c81/sys.config: {money,
./releases/0.0.1+30-9ebded0/sys.config: {money,
./releases/0.0.1+24-a0d8d13/sys.config: {money,
./releases/0.0.1+21-efda081/sys.config: {money,
./releases/0.0.1+27-5cdbf9f/sys.config: {money,
./releases/0.0.1+22-10ad675/sys.config: {money,
./releases/0.0.1+23-3e90aeb/sys.config: {money,
./releases/0.0.1+26-273b832/sys.config: {money,
./var/sys.config: {money,

I believe this is the module not being found. Could it be to do with the if Code.ensure_compiled?(Ecto.Type) do? Because staging is using a release, is the Erlang VM running in embedded mode instead of interactive?

I now feel well out of my depth - any ideas on how to go about looking into or fixing this would be appreciated. Perhaps I should create an issue at the Money repo?

What is in your application list in your mix.exs file? It seems like Money or Ecto or something is not listed. Any library that needs to be released (an application or not) must be in the application list (I think this is more automatic in Elixir 1.4, though I’m unsure if Elixir 1.4 adds dependencies of dependencies to the list).

1 Like

@OvermindDL1, thank you - that was it. :slight_smile: So far I’ve only been able to find reference to this requirement in exrm’s/exrm-related docs, not Distillery’s; maybe I should submit a pull request to the docs if that’s not too presumptuous coming from a novice.

I’m pleased to have got a release working behind the webserver. Thanks again for all of the guidance.

One other thing I’ve noticed is that after stopping and starting the app (I haven’t tried upgrades yet), the app crashes on startup and logs the following:

{"could not start kernel pid",application_controller,"error in config file \"/var/www/app_name/project/app_name/var/sys.config\" (none): configuration file must contain ONE list ended by <dot>"}

After another few starts (or perhaps after waiting a few/several seconds - I’ll test further), the application successfully launches. Perhaps this is due to a file stat/cache period?

Also, when successfully starting the following is logged in erlang.log.1, which seems strange:

[info] Running AppName.Endpoint with Cowboy using http://localhost:4010 Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help) iex(app_name@127.0.0.1)1>

Then other normal log entries continue to be logged as the app is accessed.

You definitely should submit an issue and/or pull request! :slight_smile:

Huh, that would happen if sys.config was not in the erlang format, but I’d think distillery should output it correct (I’ve never seen the issue in exrm, I’m still on exrm because I require windows support). If it ran successfully after a few tries then that does point to a race condition possibly on the file system, but that should not matter as distillery should flush everything out before it exits when making a release, and it would only be an issue the few seconds after making a release too…

If you can make a reproducible minimal test-case and submit it to distillery as an Issue that might help. :slight_smile: