Railyard

Railyard combines infrastructure as code and config management as a library within your Elixir application. It uses a Chef-like syntax to define resources within modules, which can be "shipped" (see Railyard.ship/2) to cloud providers, SaaS APIs, local configuration, etc.

Installation

Railyard can be installed by adding railyard to your list of dependencies in mix.exs:

def deps do
  [
    {:railyard, "~> 0.1.0"}
  ]
end

Run mix deps.get to pull down the latest dependencies.

Distillery Plugin

Once installed, you may want to take advantage of the Distillery plugin to automatically provision cloud instances with your build.

First, make sure that you've defined a Railyard.Distillery resource in your infrastructure:

defmodule MyApp.Infrastructure
  use Railyard.Dsl

  resource :distillery, Railyard.Distillery do
    # The Railyard.Distillery module docs describe how to set up this resource
  end
end

Install the plugin into an environment in your rel/config.exs file, and specify the Distillery resource that you're bundling:

environment :prod do
  # ... Distillery config

  plugin Railyard.Distillery.Plugin, resource: {MyApp.Infrastructure, :distillery}
end

Distillery will now handle packaging and uploading releases in a way that will allow instances to automatically fetch and install releases during provisioning. Simply run MIX_ENV=prod mix release to build and upload a new version.

Getting Started

You're in the right place. The rest of this document will help you get oriented, and set up with some basic config management and infrastructure as code. For reference material, the Railyard and Railyard.Dsl modules are the best place to go.

To get started with Railyard, there are a couple of terms that you will need to know.

Resource Spec

When writing code with Railyard, you will be writing resource specs. A resource spec describes what a resource should look like at a particular moment in time, but does not generally describe how to get there, or what changes to make along the way.

A resource spec looks something like this:

resource :my_file, Railyard.Fs.File do
  path "./my_file.txt"
  contents "Hello, world!"
end

Resource specs are written inside resource modules. Speaking of which...

Resource Module

A resource module is an Elixir module that has used Railyard.Dsl to define infrastructure components. Resource modules are the entrypoint for instantiating the infrastructure described in the resource specs. To elaborate on the above example...

defmodule MyFiles do
  use Railyard.Dsl

  resource :my_file, Railyard.Fs.File do
    path "./my_file.txt"
    contents "Hello, world!"
  end
end

Resource

A resource is the actual instance of the thing you wanted. A launched and running EC2 instance is a resource. A file on disk is a resource.

A Resource is a genserver that supervises that resource, and ships changes to those resources.

Ship

To ship a resource requires two pieces: the resource spec as described above, and a set of bindings.

To ship the resource module we defined earlier, we would do something like this:

MyFiles.ship([])

Resource Provider