Install & Deploy Phoenix Apps on Centos7 or RHEL with edeliver
The original gist can be found here
Sometimes you find yourself with a set of requirements that lead in a direction that take you out of your comfort zone. Recently I was tasked with setting up deployment for a Phoenix app on a RHEL server that I wouldn’t be able to directly access for security/compliance reasons. Normally I would use Docker in a situation like this and pass off the credentials and a working Dockerfile, but the ops team on the other end “doesn’t do Docker”. Remembering that Erlang/OTP releases are a great feature of the ecosystem, I decided it was time to learn how to use edeliver, and Distillery.
What follows is adapted slightly from a set of instructions I sent to the ops people responsible for deploying this particular Phoenix app. As such, the formatting and typesetting (can you call it that on the web?) is not great. The instructions are presented mostly as is, and without a lot of explanation. If you’re following along, feel free to email me, or check out the Elixir Forum thread where I was first stumbling through this. Also, if you find any mistakes, let me know so I can fix this post.
Set the environment variables
Install nano(or not if you intend to use vi)
yum install -y nano
Open ~/.profile
with nano ~/.profile
and add the following:
export ERLANG_VERSION="19.1.5"
export ELIXIR_VERSION="1.4.0"
export PHOENIX_VERSION="1.2.1"
export LANG="en_US.UTF-8"
export LANGUAGE="en_US.en"
export LC_ALL="en_US.UTF-8"
export PORT=4000
export HOSTNAME="YOUR HOSTNAME HERE"
export GUARDIAN_SECRET="ADD A SECRET FOR GUARDIAN IF YOU USE IT"
This is a good time to set up you ENV vars in general.
Use cmd-shift-o
to save and cmd-shift-x
to quit nano.
Run source ~/.profile
and check env
to make sure everything is set.
Begin installing required packages
yum -y install --setopt=tsflags=nodocs epel-release wget unzip uuid less bzip2 git-core inotify-tools gcc
Install Erlang
yum -y install https://packages.erlang-solutions.com/erlang/esl-erlang/FLAVOUR_1_general/esl-erlang_${ERLANG_VERSION}~centos~7_amd64.rpm && \
yum -y install esl-erlang-${ERLANG_VERSION} && \
yum -y update && \
yum -y reinstall glibc-common glibc
Install Nodejs and Yarn
curl --silent --location https://rpm.nodesource.com/setup_7.x | bash -
wget https://dl.yarnpkg.com/rpm/yarn.repo -O /etc/yum.repos.d/yarn.repo
yum -y install nodejs
yum clean all
yum install yarn
Download and Install Elixir
cd /tmp && \
wget https://github.com/elixir-lang/elixir/releases/download/v${ELIXIR_VERSION}/Precompiled.zip && \
unzip -d /usr/local/elixir -x Precompiled.zip && \
rm -f /tmp/Precompiled.zip
Set Elixir on the path
Open ~/.bashrc
with nano ~/.bashrc
and add the following:
export PATH="$PATH:/usr/local/elixir/bin"
Then reload the profile
with source ~/.profile
.
Test the install by running iex
.
If it works enter ctrl-c
twice to exit.
Install Hex and Phoenix
Run the following:
yes | mix local.hex
yes | mix archive.install https://github.com/phoenixframework/archives/raw/master/phoenix_new-$PHOENIX_VERSION.ez
Exit the ssh session
Enter ctrl-d
to return to you system’s terminal.
Clone the Repo
In you desired directory run:
git clone [email protected]:YOUR_REPO/YOUR_APP.git
If necessary also install Elixir, Erlang, and Phoenix locally following these instructions.
Get and compile the dependencies
mix deps.get
Check the edeliver config
Make sure edeliver is configured correctly.
open .deliver/config
Check the following:
BUILD_HOST="server ip address goes here"
BUILD_USER="server user name for deployment goes here"
If they have are not correct, set them to the values for the desired server.
Generate a new secret key
Run mix phoenix.gen.secret
and copy the output for the next step.
SSH back into the server
Create a production secrets file at
/home/$BUILD_USER/build_files/prod.secret.exs
$BUILD_USER
is the server’s deployment user.
The file should contain the following
use Mix.Config
config :your_app, YourApp.Endpoint,
secret_key_base: "THE PRODUCTION KEY FROM THE PREVIOUS STEP GOES HERE"
# Configure your database
config :your_app, YourApp.Repo,
adapter: Ecto.Adapters.Postgres,
username: "DATABASE USERNAME",
password: "DATABASE PASSWORD",
database: "your_app_prod",
hostname: "DATABASE HOST ADDRESS?NAME,
port: "5432",
pool_size: 20
Exit the server
exit
Build the First Release
Run the following:
mix edeliver build release [--revision=<git-revision>|--tag=<git-tag>] [--branch=<git-branch>]
In my case for staging I run:
mix edeliver build release --branch=develop --verbose
Use --branch=develop
to deploy staging, master
is the default.
Visit the edeliver github to view issues and the docs.
I also use a script called deploy
for this which looks like:
#!/bin/bash -ex
BRANCH=${1:-develop}; #arg 1 or develop
ENV=${2:-staging}; #arg2 or staging
mix edeliver build release --branch=$BRANCH --verbose
mix edeliver deploy release to $ENV --verbose
mix edeliver start $ENV
mix edeliver migrate $ENV up --verbose
mix edeliver ping $ENV
It can take one, two, or no arguments. Make sure to runchmod +x deploy
so you can run it.
./deploy # this defaults to the branch develop and the env of staging
./deploy master production # will deploy master to production
Deploy Your App!
Run the following:
./deploy
The last result should look like:
EDELIVER BEACON WITH PING COMMAND
-----> pinging staging servers
staging node:
user : YOUR_USER
host : YOUR HOST
path : YOUR DEPLOY PATH
response: pong
PING DONE!
If it does, you’re all set! Otherwise, head over to the Elixir Forum thread mentioned at the beginning, and hit us with a question.