# Deli

[![Build Status](](

Provides a simple deployment solution for Elixir applications, using a couple of [`edeliver`]( [tasks]( under the hood.

Releases are built with [`distillery`](, locally, through docker.

Git tags are autogenerated, and `deli` will ask you to bump app version, if there are new commits since last version bump.

You can configure a different release / versioning strategy if you want to.

## Getting Started

Minimal versions required: Elixir 1.8+, OTP 20+.

Add `deli` to your deps:

def deps do
    # ...
    {:deli, "~> 0.2.0-rc.6", runtime: false}

You don't need to add `edeliver` or `distillery`, as they're already included.

No need for edeliver config (for basic scenario). You will need to [setup distillery](

Then add some configuration in your `config/config.exs`:

config :deli,
  hosts: [
    staging: [
    prod: [

See [`lib/deli/config.ex`]( for all configuration options (and their defaults).

## Main task

$ mix deli

The task above does full cycle deploy:

- Creates a local docker build env
- Builds a new release in this env
- Deploys release to target env hosts
- Restarts each app in target hosts, and checks their status

It will assume `staging` environment by default.

To target `prod` environment, do:

$ mix deli -t prod

It will ask for confirmation after release is built, before deploy.
If you don't want that extra step, pass `-y` when calling this task.

### Other tasks provided by deli

# Starts all hosts for target prod
$ mix deli.start -t prod

# Stops all hosts for target prod, without confirmation
$ mix deli.stop -t prod -y

# Restarts all hosts for target staging that match ~r/02/
$ mix deli.restart -h 02

# Cleans autogenerated config files
$ mix deli.clean

# Does only release build phase
$ mix deli.release

# Does only deploy/restart/check (release should be available)
$ mix deli.deploy

# Checks status in all prod hosts
$ mix deli.status -t prod

# Pings all staging hosts (bin ping)
$ mix

# Checks version in all staging hosts that match ~r/01/
$ mix deli.version -h 01

# Checks local version
$ mix deli.version -t dev

# Compares local version with all prod hosts
$ mix deli.version -c -t prod

# Opens a IEx remote console from local machine
$ eval $(mix

# Opens a local observer connected to remote node
$ eval $(mix -o)

# When there are more than one host for target,
# eval will just work if you filter it to just return one host
$ eval $(mix -h 01)

# If you don't know yet how to filter, use it without eval,
# and it will do the port forwarding and print out the command to connect,
# but before, it lets you choose the host:
$ mix
Choose a number: 0
iex --name local@ --cookie awesome_cookie --remsh myapp@

### Run mix tasks (locally) in remote nodes

By using [`Deli.Command`](, you can have this:

# runs locally
$ mix --arg_example=1

# runs in all prod hosts
$ mix --arg_example=1 -t prod

# runs in prod hosts matching ~r/03/
$ mix --arg_example=1 -t prod -h 03

#### Edeliver and Distillery

Releases should be configured in your application with [`distillery`](

You don't need to think about edeliver with `deli` (unless you want to).
Deli generates any config needed for edeliver, and adds them to your gitignore by default.
If you want to maintain a custom version, just remove from .gitignore, and also remove the comment line saying `autogenerated by deli`.
Edeliver mix commands are available to you. But if you use the systemctl controller, avoid using edeliver admin commands (start / stop / ...)

At the moment, this package exists for reusing among similarly configured apps. It might not be flexible enough for your needs yet.

### Advanced configuration

Checkout [Release configuration]( for more options.

## Potential future work

- Add more documentation
- Remove edeliver dependency, replacing its steps by local code
- See about using elixir releases instead of distillery (1.9+)
- Concurrent restarts / checks / ...
- Retry / rollback strategy
- Upgrades
- Accept host labels in config, and filter by it in commands
- Associate labels with different build targets (first label wins)
- Configure a custom deploy strategy
- Plugin behaviour to allow custom hooks and integrations (e.g. slack notification)
- Use github releases as release store
- Allow production to be default target if there's no staging
- mix deli.eval
- Allow developers to create custom docker build hooks, by checking paths: `.deli/docker_build_hooks/{(before_|after)(build|setup|setup_(otp|elixir|rebar3))}/script.(sh|exs)`
- Allow to change target path to something else than `/opt/APP`
- Autogenerated files with version and checksums for expiration
- Integrate with a terminal-based observer
- Do rebar3 checksum in docker build images
- Allow to specify hex version in docker build images
- Configure a remote docker host
- Provide common release service assets (nginx, systemd, logrotate etc)
- Provision/setup new target hosts (with hooks for custom setup)
- Use s3 as release store
- Use a scp release store (allows CI to build releases for all build targets upfront)