Elixir/Phoenix deployments using Github Actions

Pedro Assunção
Jul 23 · 3 min read
Image for post
Image for post

One of the trickiest parts of getting Elixir services into production is the deployment. Common approaches include using Docker to generate containers that you can then deploy to AWS/Google/Azure, a Kubernetes cluster, or running the creation of the deployment locally (mix releases) and then publishing the finalised version to the target machine.

For my website https://pedroassuncao.com i decided to go with a simpler approach: Instead of building the final product in a local machine, creating a package (container or otherwise), and then deploying it to my host, i chose to do everything in the target system instead, by leveraging Github Actions.

Image for post
Image for post
5 Euro if you can guess what noozo means…

This approach has the following advantages:

  • Migrations don’t require a separate module to run (mix is available in the target system).
  • Deployment is fast due to cached dependencies on the target system and a simple SSH command running everything at once.
  • Slack notifications are super easy to integrate into Github actions and they are a fantastic way to keep track of deployment status.
  • Push and forget strategy for deployment is super easy.
  • No Docker and all its configuration mess.

Here's how i do it:

On my host (a simple Linode node) i installed Elixir, Erlang, NodeJS and the rest of the dependencies for any Elixir/Phoenix project. This has the disadvantage of having to manually upgrade their versions, but i can live with that by using asdf to manage them. I then proceeded to clone my repo into a folder on the host, where i will build, release, and control the service. This is done once, and has the advantage of caching dependencies directly on the target, which speeds up the deployment process.

Then, every commit i push to master (my code lives on Github, obviously), is caught by the following action:

name: Deploy

As you might have noticed, i use Github secrets to inject the Slack webhooks and also the SSH key to connect to my target machine.

I'm pretty happy with this solution so far, however it's not without its flaws:

  • By not using restart the website is down for 5–10 seconds every deployment (there's probably a way around that, but last i tried it didn't work very well when the mix.exs version changes).
  • Elixir/Erlang/NodeJS versions need to be manually upgraded on the target host.

Let me know if there's anything i can improve, would love to hear your thoughts!

Happy Elixir'ing

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store