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 Gigalixir
Short guide on how to deploy a Phoenix app to Gigalixir.
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.
Deploying to Gigalixir’s free tier
This is the easiest way to get your app up and running.
It’s basically a zero config approach and it just works.
Create a new account on Gigalixir’s website.
Then let’s switch to the CLI tool for everything else.
Install the Gigalixir CLI tool:
sudo pip install gigalixir
After the installation is done, log in.
This will get your API key saved to ~/.netrc
:
gigalixir login
# Email: your@email.goes.here
# Password:
# Would you like us to save your api key to your ~/.netrc file? [Y/n]: Y
# Logged in as your@email.goes.here.
Add your SSH public key so you can do migrations and other operations:
gigalixir account:ssh_keys:add "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC2rhfcHmCLw6DkTHBtMjJi+RRHLFkIOojZ78L4hDToRLOZlTNEnxbWYQCECVMd2meemTiVT7Lbd6hjr4dTHo/+HTE01wOxjtZdS2soDylVV2GH4WyMxTmlfFCMsBsWCoHCUV15sTshrZNgHUpM3RdgvyV0awFZ9OIjUXKJi0ReBusWlcvK32mls+ccVEwf8wtslsB0350G25I8Na+9WMwpupUJT+2QM9gqYvch/ptSE6zUOzqe94vlIlXmBlCrbRbtpjS7soGSYKT2jBVWTGBLqW4LQDRJ+s7Q8B3+tilU2C49r2Yeg8Xn4GS6S8y2KsrXZHeSL/GdxQnS2sVGYtMKsQFKAxkAE/J5eXGeTcZwiuCkmAZTm1E9AqwhDbxDNG2uyT/kQJBbcQmAnRLoIVngYdqXcgWtg1iUI+ta4opt6imgtsv99mWFilfIQvisxxBxgyOaciexh3Feeoupn/tLG5wywjN7sEl9SvYABi9Pii15JeVfP1P5bHbdWoiW3APD1WEAyC70O2fanNwgA30PUG2j/zDm14DRMkQ7wpcJxdRGsY/vqYS7o1HwPBTAn8+8uedCDm24KIi2stZvShOTrduIRJzaEduSPlq4pR1nIZSIjdUP9WFJff/mLgbTxOLUtNlboWfJx305dnsVEXFpBKvrx13QcPYywFGoc62spQ== some@user"
Create a new app
cd
into your Phoenix project and now let’s create an app and DB for it:
cd my-phoenix-json-api
gigalixir create
gigalixir pg:create --free
Some useful status commands
To see the list of all the apps you have access to:
gigalixir apps
[
{
"cloud": "gcp",
"region": "v2018-us-central1",
"replicas": 0,
"size": 0.3,
"stack": "gigalixir-18",
"unique_name": "square-brilliant-diplodocus",
"version": 2
}
]
Show current app status:
gigalixir ps
{
"cloud": "gcp",
"pods": [],
"region": "v2018-us-central1",
"replicas_desired": 0,
"replicas_running": 0,
"size": 0.3,
"stack": "gigalixir-18",
"unique_name": "square-brilliant-diplodocus"
}
List all DBs for current app:
gigalixir pg
[
{
"app_name": "square-brilliant-diplodocus",
"database": "9a75bce2-fbf8-4a1b-80b2-115541025078",
"host": "postgres-free-tier-1.gigalixir.com",
"id": "9a75bce2-fbf8-4a1b-80b2-115541025078",
"limited_at": null,
"password": "pw-93c493e4-aba0-4f0d-b134-f66e0a73ca91",
"port": 5432,
"state": "AVAILABLE",
"tier": "FREE",
"url": "postgresql://9a75bce2-fbf8-4a1b-80b2-115541025078-user:pw-93c493e4-aba0-4f0d-b134-f66e0a73ca91@postgres-free-tier-1.gigalixir.com:5432/9a75bce2-fbf8-4a1b-80b2-115541025078",
"username": "9a75bce2-fbf8-4a1b-80b2-115541025078-user"
}
]
Delete an app
If you want to get rid of the app and start afresh, you need to delete the DB first.
gigalixir pg:destroy -d 5d62c4a9-37a4-4104-a19e-187b8221e322 # this is the dataabase id
Then delete the app itself:
gigalixir apps:destroy -a green-trusty-coqui # this is the app name
To see all available commands just type gigalixir
.
The deploy process
Open config/prod.exs
and change the host URL to your app name
plus .gigalixirapp.com
. Like this:
config :my_app, MyAppWeb.Endpoint,
url: [host: "square-brilliant-diplodocus.gigalixirapp.com", port: 80],
cache_static_manifest: "priv/static/cache_manifest.json"
Then create an elixir_buildpack.config
file in your project’s
root directory and add the versions you used for your project:
elixir_version=1.10.4
erlang_version=23.0.3
Commit your changes on git, then to deploy just:
git push gigalixir main
To run any existing migrations:
gigalixir ps:migrate
If you are using an identity file different from id_rsa
—say
lobotuerto
and lobotuerto.pub
, you can pass SSH options to the
command like this:
gigalixir ps:migrate -o "ssh -i ~/.ssh/lobotuerto"
Take a look at your current app status:
gigalixir ps
{
"cloud": "gcp",
"pods": [
{
"lastState": {},
"name": "square-brilliant-diplodocus-765fc6f7c8-zpdbw",
"sha": "426a17f47d10b751b53fc96f8f23e0298ac9bfdc",
"status": "Healthy",
"version": "1"
}
],
"region": "v2018-us-central1",
"replicas_desired": 1,
"replicas_running": 1,
"size": 0.3,
"stack": "gigalixir-18",
"unique_name": "square-brilliant-diplodocus"
}
The "status": "Healthy"
part signals that your app is ready
to receive requests.
The remote console
Let’s log into the remote console and create a user so we can test our endpoints.
gigalixir ps:remote_console
If using a different identity file, you might tweak your command to:
gigalixir ps:remote_console -o "-i ~/.ssh/lobotuerto"
Notice the subtle change to what’s inside the quotes,
this time you need to remove the ssh
we were using
in the ps:migrate
command.
When the remote console opens, enter the following:
MyApp.Account.create_user(%{email: "asd@asd.com", password: "qwerty"})
Then close it with a double CTRL-C
.
Running the seeds file
Let’s add the following code to the priv/repo/seeds.exs
file:
IO.puts("Adding a couple of users...")
MyApp.Auth.create_user(%{email: "user1@email.com", password: "qwerty"})
MyApp.Auth.create_user(%{email: "user2@email.com", password: "asdfgh"})
Commit the changes then push to the gigalixir
remote and run the seeds with:
git push gigalixir master
gigalixir run -- mix run priv/repo/seeds.exs
You can have a look at the server logs with:
gigalixir logs
Now, you can try the curl commands against a live application in production!
curl -H "Content-Type: application/json" -X GET \
http://square-brilliant-diplodocus.gigalixirapp.com/api/users \
-c cookies.txt -b cookies.txt -i
# HTTP/1.1 401 Unauthorized
# Server: nginx/1.17.7
# Content-Type: application/json; charset=utf-8
# Content-Length: 44
# cache-control: max-age=0, private, must-revalidate
# x-request-id: a8f2421075d1bc52248bfe0a088e328e
#
# {"errors":{"detail":"Unauthenticated user"}}
curl -H "Content-Type: application/json" -X POST \
-d '{"email":"asd@asd.com","password":"qwerty"}' \
http://square-brilliant-diplodocus.gigalixirapp.com/api/users/sign_in \
-c cookies.txt -b cookies.txt -i
# HTTP/1.1 200 OK
# Server: nginx/1.17.7
# Content-Type: application/json; charset=utf-8
# Content-Length: 85
# cache-control: max-age=0, private, must-revalidate
# x-request-id: 77d6a6af461823d883e45fb5d2c7a177
#
# {"data":{"user":{"email":"asd@asd.com","id":"5d91bef4-94b2-437a-8e6a-d8db7ea1b376"}}}
curl -H "Content-Type: application/json" -X GET \
http://square-brilliant-diplodocus.gigalixirapp.com/api/users \
-c cookies.txt -b cookies.txt -i
# HTTP/1.1 200 OK
# Server: nginx/1.17.7
# Date: Sun, 26 Jul 2020 02:04:10 GMT
# Content-Type: application/json; charset=utf-8
# Content-Length: 276
# Vary: Accept-Encoding
# cache-control: max-age=0, private, must-revalidate
# x-request-id: 7ec40e0e453d6df5d00f47b15243e99f
# Via: 1.1 google
#
# {"data":[{"email":"asd@asd.com","id":"5d91bef4-94b2-437a-8e6a-d8db7ea1b376","is_active":false},{"email":"user1@email.com","id":"cb6fce2d-a264-4d92-a2ba-a224b15d541f","is_active":false},{"email":"user2@email.com","id":"35e627ed-e7d2-40d8-9597-a09ee7caa0a3","is_active":false}]}
That was fun, wasn’t it? :D