We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
2020 / 07 / 27
Deploy a Phoenix application to a VPS
Short guide on how to deploy a Phoenix app to Linode/DigitalOcean by hand.
Prerequisites
First, we need a Phoenix app.
The application we’ll be deploying is the one from:
Building a JSON API in Elixir with Phoenix.
I’ll show the steps needed to have this app available at:
http://lobotuerto.com:4000
We’ll go with Ubuntu for the OS.
Also, we should have a domain already configured on that machine.
So, when trying something like this, it should respond as expected:
curl -H "Content-Type: application/json" -X POST \
-d '{"email":"asd@asd.com","password":"qwerty"}' \
http://lobotuerto.com:4000/api/users/sign_in \
-c cookies.txt -b cookies.txt -i
OK, SSH into your VPS then follow the steps below.
Configure the firewall
sudo ufw enable
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
Install PostgreSQL on the VPS
Follow this guide: How to install PostgreSQL in Linux.
Make sure to create a DB user for your app —it’s on the guide.
In this example the DB user will be called deployer
and will have a
password deployer123
.
Install dependencies for Erlang and Elixir
sudo apt install build-essential autoconf m4 libncurses5-dev libwxgtk3.0-dev \
libgl1-mesa-dev libglu1-mesa-dev libpng-dev libssh-dev unixodbc-dev
Create a user for deployment
sudo adduser deployer
Install Erlang and Elixir
Impersonate the user with:
sudo su deployer -l
This is done so the deployer
user have access to the Elixir executable.
Follow this guide: How to install Elixir in Linux.
Clone your app repo
Or transfer the code using scp
.
git clone https://github.com/lobo-tuerto/my-phoenix-json-api
Install the app dependencies
cd my-phoenix-json-api
mix deps.get
Adjust the config files
Comment out this code in config/prod.exs
:
-config :my_app, MyAppWeb.Endpoint,
- url: [host: "example.com", port: 80],
- cache_static_manifest: "priv/static/cache_manifest.json"
+
+# config :my_app, MyAppWeb.Endpoint,
+# url: [host: "example.com", port: 80],
+# cache_static_manifest: "priv/static/cache_manifest.json"
Uncomment this code from config/prod.secret.exs
:
-# config :my_app, MyAppWeb.Endpoint, server: true
+config :my_app, MyAppWeb.Endpoint, server: true
Setup the DB
Execute the following three commands:
SECRET_KEY_BASE="`mix phx.gen.secret`" \
DATABASE_URL="ecto://deployer:deployer123@localhost/myapp_prod" \
MIX_ENV=prod mix ecto.create
SECRET_KEY_BASE="`mix phx.gen.secret`" \
DATABASE_URL="ecto://deployer:deployer123@localhost/myapp_prod" \
MIX_ENV=prod mix ecto.migrate
SECRET_KEY_BASE="`mix phx.gen.secret`" \
DATABASE_URL="ecto://deployer:deployer123@localhost/myapp_prod" \
MIX_ENV=prod mix release
Let’s create a couple of users to try it out.
_build/prod/rel/my_app/bin/my_app start_iex
iex> MyApp.Account.create_user(%{email: "asd@asd.com", password: "qwerty"})
iex> MyApp.Account.create_user(%{email: "some@email.com", password: "some password"})
This could have been done using the priv/repo/seeds.exs
file too,
but I wanted to showcase how to open an IEx session on the production app.
Now, without exiting that IEx session, go ahead and try this:
curl -H "Content-Type: application/json" -X POST \
-d '{"email":"asd@asd.com","password":"qwerty"}' \
http://lobotuerto.com:4000/api/users/sign_in \
-c cookies.txt -b cookies.txt -i
You should see:
HTTP/1.1 200 OK
cache-control: max-age=0, private, must-revalidate
content-length: 48
content-type: application/json; charset=utf-8
date: Mon, 29 Jul 2019 22:15:13 GMT
server: Cowboy
x-request-id: FbYAie3B0hrQ5-gAAAPF
set-cookie: _my_app_key=SFMyNTY.RgcVe-7fJ-NqSO5DQL; path=/; HttpOnly
{"data":{"user":{"email":"asd@asd.com","id":1}}}
Awesome! :tada: