DevOps CI/CD/CD for Elixir/Phoenix best practice?

I would go farther and say that you should assume NIFs will be part of your project at some point, and design your build pipeline accordingly. Avoiding NIFs is not really necessary, though one should be careful of how many and how often you use them simply because of the risk of scheduler blockage, but that’s not really a deployment problem.

I generally recommend using Docker or Vagrant for local builds (i.e. set up a an environment to run mix release and produce the release tarball which you can then copy out of the build environment to wherever), and for teams, setting up a dedicated build server running something like Jenkins (or whatever, it could be Travis, CircleCi, just a dedicated build environment). The result of a build should be an artifact (in our case that is the release tarball) which can be copied to some kind of storage (whether that is S3, a file server, or a Docker image being pushed to a registry) or copied directly to the production server (I think holding on to each artifact for easy rollbacks/troubleshooting is worth storing them though). Actually deploying the release then becomes a matter of just copying the tarball to the right place, extracting it, and restarting the release.

Each of those steps can be completely automated, as well as performed by hand, which makes it easy to troubleshoot each step. If you are just getting into setting up a CI/CD pipeline, I’d start by getting the basic pieces in place, performing each step by hand, and then automate each piece until you are mostly just hitting a button to deploy to prod.

Configuration management is a big part of this, but that is heavily dependent on your setup, at the most basic level, environment variables work well, but you can automate things using any kind of config management tool or provisioning step (e.g. ansible/chef/puppet) or by hitting an external config service (e.g. etcd/consul/vault). Distillery 1.x doesn’t make things very easy in this regard, but Distillery 2.x will make it very easy to integrate different configuration providers. That should be coming out in the next couple weeks (by end of the month or first week of April I hope)

Things are different if you are building a product, or are working in an environment where you are at the mercy of another team who doesn’t care about helping you, but for the most part the above is all you really need to keep in mind to figure out an approach that works for you.