Releases is a fantastic new feature in Elixir 1.9, but it comes with one important caveat:
Once a release is assembled, it can be packaged and deployed to a target, as long as the target runs on the same operating system (OS) distribution and version as the machine running the
mix release
command.
If your dev machine is not running the same Linux distro and version than your server then chances are that you won’t be able to start your service because the packaged ERTS will probably be dynamically linked with different versions of libc, ncurses, or openssl. The solution I believe most people are currently using is to create a Docker container to build the release and then generate an image with the app or just match the target OS.
There were some recent discussions about the possibility of generating universal statically linked fat binaries, but here there is maybe an (hacky) alternative: just modify the ELF interpreter location and add a runpath with the same library versions used by your dev machine to all the Erlang distribution binaries included in the release.
Here is how one can achieve this with NixOS’s patchelf; let’s say we already have the release package (built in Arch Linux) in our target machine running Debian Buster:
$ cd myapp/erts-10.5/bin
$ ./beam.smp
./beam.smp: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by ./beam.smp)
$ file beam.smp
beam.smp: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=eb7be73353afbb0bc4962b81bd427aed7ce66dcd, for GNU/Linux 3.2.0, stripped
$ ldd -v beam.smp
./beam.smp: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by ./beam.smp)
[...]
Version information:
./beam.smp:
[...]
libm.so.6 (GLIBC_2.29) => not found
[...]
So now we need to provide the glibc package used by our local dev machine to the target system, extract it somewhere, and finally modify the ERTS binaries to look for these libraries (I will skip the scp or curl part):
$ cd
$ tar xf glibc-2.29.tar
$ patchelf --debug --set-interpreter /home/user/glibc-2.29/lib64/ld-linux-x86-64.so.2 --set-rpath /home/user/glibc-2.29/lib/x86_64-linux-gnu/ myapp/erts-10.5/bin/beam.smp
(we probably want to do this with the rest of the ELF files: ct_run, dialyzer, dyn_erl, epmd, erl_child_setup, erlc, erlexec, escript, heart, inet_gethost, run_erl, to_erl, typer)
At this point BEAM should be able to run and your minimal Elixir application should be able to start.
Don’t do this at work!