Deploy Phoenix 1.6 / Elixir 1.3 on Render.com: A Working Guide
Spent almost a week fixing errors after errors trying to deploy my Phoenix/Elixir App on render.com. So I decided to write my journey to hopefully help noobs like me.
Note that this blog is for noobs (like me), so I had to really tell what needs to be done (dumb down things), kinda like what I want some blogs to be written, for me to understand it well enough so I don’t have to experience this again 😂 . If you think you’re too smart for this, I’m sorry and if there’s anything wrong with how I understand things, feel free to correct and enlighten me 🙏. Anyways, let’s get started.
Preparing your Phoenix/Elixir App for Deployment
You can follow this tutorial: Deploy a Phoenix App with Mix Releases and if everything works, you can skip this portion.
BUT if it doesn't (Just like mine) there are things I needed to change to make it work.
- First is the
build.sh, here’s mine:
#!/usr/bin/env bash# exit on error
set -o errexit# Initial setup
mix deps.get --only prod
MIX_ENV=prod mix compile# Compile assets
npm install --prefix ./assets
MIX_ENV=prod mix assets.deploy# Build the release and overwrite the existing release directory
MIX_ENV=prod mix release --overwrite# Run migrations
_build/prod/rel/alvin_and_eloisa/bin/alvin_and_eloisa eval "Release.migrate"# Run seeds
MIX_ENV=prod mix run priv/repo/seeds.exs
As you notice, I'm compiling my assets using both npm and mix, For some reason, when using
mix assets.deploy alone, esbuild is not compiling my
app.csson production, and when I'm using
npm my JS is not compiling, So I figured I can use both to compile both and when I tried it, It worked! 😂
Also, you may want to comment the
Run seed block after running it successfully the first time, to avoid duplicate data on your production database.
- Next is
defp aliases do
setup: ["deps.get", "ecto.setup", "cmd --cd assets npm install"],
"ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
"ecto.reset": ["ecto.drop", "ecto.setup"],
test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
"cmd --cd assets npm run deploy",
"esbuild default --minify",
Had to edit my alias for
assets.deploy to do
npm run deploy which will run the deploy script on our package.json below.
package.json, add the
scriptsblock to compile my app.css, I’m using TailwindCSS by the way.
"deploy": "NODE_ENV=prod tailwindcss --postcss --input=css/app.css --output=../priv/static/assets/app.css --minify"
Creating Database and Web Service on Render
There's not much I can tell about this process, it's pretty easy to do and I have not encountered any problems doing this.
Setting up Environment Variables
On the render dashboard, select the web service you just created and go to the Environment tab and click the
Add Environment Variablebutton to add environment variables.
Create a variable named
DATABASE_URL, then go to the database service you created, and copy the
Internal Connection String and paste it on the
Secret Key Base
Create a variable named
SECRET_KEY_BASE , then in your terminal, run
mix phx.gen.secret , copy the result and paste it on the
Customizing Elixir and Erlang/OTP versions
You can check here for the list of Elixir and Erlang versions supported by render, mine are:
You need to make sure your versions are correct and ideally equal to your local setup, I’ve had issues with these when deploying my app on production not realizing that the default elixir version on render is 1.9.4.
Adding Custom Domain with hostinger
Once you got your domain on hostinger, go to your web service settings (on render) and click
Add Custom Domain. Input the domain you bought and after that will something like this below:
It is basically telling you to add these DNS records pointing your domain to the render web server, so let's do that. Inside your hostinger account, go to the
DNS/Nameservers tab of the domain you just bought and add a DNS record.
Hostinger doesn’t have ANAME and ALIAS records so I ended up adding just these three below. After you are done, go back to the settings page of your web service (on render) and click verify, it may take a couple of minutes to verify but if for some reason it fails (like mine), delete the record on hostinger and add it again (that’s what I did).
Types Name Pointing to
CNAME www yourwebsite.onrender.com
CNAME * yourwebsite.onrender.com
A @ 126.96.36.199
NOTE: When your custom domain was added to your web service make sure to also add it to your
config :your_app, YourAppWeb.Endpoint,
url: [host: System.get_env("RENDER_EXTERNAL_HOSTNAME") || "localhost", port: 80],
this will prevent you from having some WebSocket issues and DB Connection errors like this ⬇️
Considering that this is the first time I’ve deployed a Phoenix/Elixir App, I can’t say that I enjoyed it BUT it’s a great experience and it is sure as hell a satisfying one, especially when you figured all things out and you see your website working properly, I had a blast!!
You can check the issues I’ve encountered here and feel my pain throughout the whole process.