[pseudo-rant] My Thoughts on Elixir Deployment

TL;DR

I would really like some sort of officially-supported, up-to-date DevOps guide + tooling for deploying Elixir projects, something to fill in the spectrum between “fully custom process” and “do everything for me.” Something that would allow me to grow my DevOps skills with my application development skills. It should be built off the native Mix release features shipped in the past year, because I’d like to support the official tooling. I think improving the story around deployment this way would really help grow the community.

If this already exists somewhere, please tell me I’m wrong and let me know.

Disclaimer

DevOps is hard. I’m no expert. I’ve only been poking around at available options for the last couple months while building my projects. “Poking around” includes reading various blog and forum posts, plus trying out some of the examples.

This pseudo-rant may be inaccurate, since I’m new to all this stuff, so I may be missing things. Please forgive my ignorance and correct me if that’s the case.

The Elixir DevOps Coin

I see DevOps on Elixir as a coin. On one side, you have the fully-customized pipelines that people build. These provide total freedom of choice. It’s Easy to Change. Don’t like AWS’s pricing? Fine, try DigitalOcean, Linode, etc. The price for this freedom is learning how to do DevOps on Elixir. I see this as a worthwhile pursuit, if only I could find the time to study it while building my application’s features against deadlines (I’m the sole developer on my projects).

I feel like many are in the same boat that I am, and that’s why solutions like Render and Gigalixir are so popular. I personally use Render, and I think it’s a great service. These represent the other side of the spectrum: basically, “do everything for me.” You provide the Git remote repository, maybe some environment variables, and that’s (mostly) it. It Just Works. And that’s all many will need. The tradeoff here, of course, is that it’s not very Easy to Change.

Elixir DevOps as a Spectrum

What if I want to expand my knowledge of DevOps through the process of building my application? That is, start with something that’s totally “batteries included”, and gradually move towards a custom system, depending on my application’s needs? And rather than have it happen all at once, have it happen incrementally? What if DevOps was a spectrum rather than a coin?

Existing options

Maybe it is, and I’m just wrong, but if that’s the case I haven’t found what I’m looking for yet.

I’ve looked into various projects along various stages of the spectrum, most notably Distillery. In fact, the Distillery “Deploy to AWS” guide is one of the reasons I’m writing this. This is a great example of what I’m looking for! It lays everything out in code so if you want to change something, it’s not difficult to experiment with. It’s very Easy to Change.

I could just use Distillery – and, indeed, from browsing the forum it seems that many people are still using it – but I think that for my projects, I’d like to support the solutions provided by the language / defacto build tool. That just seems like a good idea to me. I tried to convert the Distillery AWS guide to use mix releases, even asking for Distillery features as part of Mix releases, but stalled out after a few attempts of getting it to work. I had some deadlines and couldn’t afford to keep experimenting. I just decided to use Render and revisit the issue at a later date.

I’ve poked around at other deployment projects, such as the ones found on awesome-elixir, but most of them appear unmaintained or out of date.

The Ideal World

So what am I looking for? An up-to-date, active list of best practices / guides / tools for deployment and DevOps on Elixir. Something that allows me to explore the spectrum of DevOps rather than just the two sides of the coin that I see so often in forum posts. Basically, Pow for DevOps.

An Aside: Why Pow?

Disclaimer: I’m not affiliated with Pow, I’m just a big fan. Thank you, Dan!

I really like Pow for authentication. It comes with batteries included but allows me to swap out parts as application needs grow. It’s Easy to Change.

I understand that deployment is a completely different beast than authentication when it comes to the sheer number of options available, but it does a good job of indicating and encouraging best practices. My comparison to Pow was mainly to provide an example of a solution that was easy to get started with and is Easy to Change.

Official support?

Since Elixir started supporting releases officially, I think they want to have better support for the whole deployment pipeline, right? Maybe there isn’t bandwidth on the team for official support, so we’d need to find a way to keep it up to date as a community.

Features I would want

The Distillery AWS guide I linked above covers almost everything, but I’d like something more specific to the native releases that have been supported for almost a year:

  • Infrastructure as Code for various application parts: database, web server, etc.
  • Creating a project build container + storage bucket for build artifacts (mainly so I don’t need to have build tools installed on the production machines)
  • hooks into GitLab, GitHub, etc. for push-to-deploy
  • how to handle secrets, e.g. API keys
  • integration with industry-standard infrastructure provisioning/configuration tools, like Terraform and Ansible

Summary

I’ve been having a hard time moving my deployments from “do everything for me” towards “custom solution.” I’d like to expand my knowledge of deploying Elixir applications to the VPS provider of my choice. I’d like to learn about things like load balancing, auto-scaling groups, and more, but I’d rather do it gradually. I don’t necessarily have the time to learn all about DevOps while working on my applications.

I really do like Gigalixir and Render, and I think they’ll continue to have a place in elixir application development since they Just Work, but I’d like to gradually grow my DevOps skill set beyond those options while also developing my app.

I think a constantly up-to-date guide/toolset built off the native release features and maintained/funded the core Elixir org would be ideal, but this may be difficult or impossible.

This concludes my rant. If this solution already exists, please let me know. Maybe I’m just being ignorant. If it’s impossible to do, I’ll probably just stick with Render until I can hire someone to build the system I want for me. But I believe this community can build something like this if it doesn’t exist already, and that it would really help us solidify the application development story, from prototype to production.

If you’ve read this far, thanks for hearing me out!

11 Likes

“DevOps” is a pretty broad category. Depending on your organization and definition of what “DevOps” is it could encompass everything from CI/CD, monitoring, logging, and alerting to name a few.

I cover some of these topics on my personal blog:
Logging: https://akoutmos.com/post/elixir-logging-loki/
CI/CD: https://akoutmos.com/post/elixir-cicd/
Monitoring: https://akoutmos.com/post/prometheus-postgis-and-phoenix/ & https://akoutmos.com/post/prometheus-postgis-and-phoenix-two/
Deployment: https://akoutmos.com/post/multipart-docker-and-elixir-1.9-releases/

Are you looking more for an opinionated tutorial (i.e a particular set of tools but a deep dive). Say something like CI/CD with GitLab and deploy to Kubernetes for example?

4 Likes

I actually really like elixirs deployment story, but I can see why it can seem daunting for people new to it.

I like it because it actually gets out of your way quite early in the deployment pipeline. Once you’ve managed to build your release for your target architecture you’re done with (most of the) elixir specific stuff. No version management of runtimes on the server, no needing to put things in some special location so they can be found (unless I managed to create such constraints), …

Need to move the release to prod servers? Choose whatever solution fits.
Need to start up your service on prod servers? Choose whatever solution fits.
Need to scale your service? Choose whatever solution fits (and figure out how to connect the cluster and if you should do it at all)

A solutions here can start with hand written bash script on free GitLab CI and move over simple docker setups to full blown orchestration tools like Kubernetes.

The actually difficult part is what I casually mentioned as

Once you’ve managed to build your release for your target architecture …

Because this requires you to know some things about your application as well as your target servers and possibly knowing how to automate a copy of your target architecture to create the release in. This is especially a problem for your imagined “in between path”, as fully customized solutions are aware of those things and fully managed solutions can control most of those variables for you. There’s not really a middle ground. You either have those variables controlled by someone else or you handle them on your own.

But I feel there can be better tutorials/blog posts out there explaining how to setup the step of building a release for a given system.

2 Likes

If you are talking about Phoenix, there is an official guide on using mix release over here:
https://hexdocs.pm/phoenix/deployment.html.
https://hexdocs.pm/phoenix/releases.html

I have followed these 2 guides and have successfully deployed to DigitalOcean and AWS. I don’t think there should be any differences between other cloud providers.

I have also tried using Docker with these guides, and it has also worked well so far, but you need to have a basic understanding how Docker works.

For slightly more elaborated setup, you may have stuffs like managed DB or VPC. But this is beyond the scope of Elixir deployment I believe.

Recently, I have also used Terraform to deploy my Phoenix project. At this point, I feel it is more about understanding how to use Terraform rather than Elixir.

1 Like

Hi, Alex,

Thanks for the links. Yes, I agree, it’s a broad category, and I’m interested in all of it! For now, though, I’d just like to automate my releases, similar to how the “Deploying on AWS” blog post does it:

  • Deploy and provision infrastructure based on configuration (Infrastructure as Code)
  • Ci/CD to create build artifact
  • copy build artifact to production server(s)
  • switch over running application to new version

As far as Docker/Kubernetes for running the application goes, I’ve read previous threads on the subject and the opinion seems to be mixed. For my project, there may be a need in the future to “hot reload” code, so I’d like to avoid depending on Docker/Kubernetes for now.

I really should have just said I’d like an update to the Distillery guide for Mix releases. :slight_smile:

You mean something like this?

I’ve tried to go through this tutorial, but I suppose I’d like to tie everything together and include the “server setup” part. Make it all automatically generated from Infrastructure as Code. So, yeah, I guess I’d like a more opinionated tutorial for setting everything up and automating it. Like the Deploying to AWS guide I mentioned, but updated for Mix releases. Something that works out of the box and doesn’t hide the details. That way, I can study it and make changes as my needs change.

Sure, what I’m asking goes beyond the scope of Elixir deployment. And there are plenty of tutorials out there for setting up these systems for Python, Node.JS, etc. I’m under the impression that thanks to OTP and the BEAM, the “best practices” for server setup and deploying Elixir projects might be slightly different than for other languages, and I haven’t found a guide out there that covers this.

Maybe this is just a long way of saying “please update the Distillery tutorials to use Mix releases” :smiley:

I guess a good baseline would be: Just skip the language specific parts. If your release is build for your correct server architecture in the first place your server doesn’t need anything specific anymore. Find a way to copy the release data to the server and some tooling for starting it (like any other executable script) / handling it’s lifecycle and you should be fine.

1 Like