aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Perry <np@nathanperry.dev>2020-01-28 16:06:48 -0500
committerNathan Perry <np@nathanperry.dev>2020-01-28 16:06:48 -0500
commit5dadc47eb07be076a8b270458badb9d8cd7dfead (patch)
tree69918ab33ded1e98905ebdf99c6f88f373a7a396
parentdde5eb52706a9ca8ee257a6cbd75e243582d0a86 (diff)
start elixir conversion
-rw-r--r--.formatter.exs4
-rw-r--r--.gitignore26
-rw-r--r--.thulani_root0
-rw-r--r--apps/thulani_bot/.formatter.exs3
-rw-r--r--apps/thulani_bot/.gitignore24
-rw-r--r--apps/thulani_bot/README.md2
-rw-r--r--apps/thulani_bot/lib/thulani/bot/application.ex13
-rw-r--r--apps/thulani_bot/lib/thulani/bot/config.ex58
-rw-r--r--apps/thulani_bot/lib/thulani/bot/consumer.ex23
-rw-r--r--apps/thulani_bot/mix.exs32
-rw-r--r--apps/thulani_bot/test/test_helper.exs1
-rw-r--r--apps/thulani_bot/test/thulani/bot/application_test.exs4
-rw-r--r--apps/util/.formatter.exs4
-rw-r--r--apps/util/.gitignore24
-rw-r--r--apps/util/README.md21
-rw-r--r--apps/util/lib/thulani/util.ex2
-rw-r--r--apps/util/lib/thulani/util/compose.ex13
-rw-r--r--apps/util/lib/thulani/util/curry.ex16
-rw-r--r--apps/util/mix.exs27
-rw-r--r--apps/util/test/test_helper.exs1
-rw-r--r--apps/util/test/thulani/util_test.exs4
-rw-r--r--config.example.toml10
-rw-r--r--config/config.exs9
-rw-r--r--config/dev.exs14
-rw-r--r--config/load_from_dotenv.exs36
-rw-r--r--config/prod.exs5
-rw-r--r--config/release.exs1
-rw-r--r--mix.exs43
-rw-r--r--mix.lock17
-rw-r--r--rel/env.bat.eex7
-rw-r--r--rel/env.sh.eex18
-rw-r--r--rel/vm.args.eex11
32 files changed, 473 insertions, 0 deletions
diff --git a/.formatter.exs b/.formatter.exs
new file mode 100644
index 0000000..6915976
--- /dev/null
+++ b/.formatter.exs
@@ -0,0 +1,4 @@
+[
+ inputs: ["mix.exs", "config/*.exs"],
+ subdirectories: ["apps/*"]
+]
diff --git a/.gitignore b/.gitignore
index 3352214..750b022 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,29 @@
*.log
user_id_mapping.json
restrict.json
+config.toml
+
+# The directory Mix will write compiled artifacts to.
+/_build/
+
+# If you run "mix test --cover", coverage assets end up here.
+/cover/
+
+# The directory Mix downloads your dependencies sources to.
+/deps/
+
+# Where third-party dependencies like ExDoc output generated docs.
+/doc/
+
+# Ignore .fetch files in case you like to edit your project deps locally.
+/.fetch
+
+# If the VM crashes, it generates a dump, let's ignore it too.
+erl_crash.dump
+
+# Also ignore archive artifacts (built via "mix archive.build").
+*.ez
+
+# Ignore package tarball (built via "mix hex.build").
+thulani_bot-*.tar
+
diff --git a/.thulani_root b/.thulani_root
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/.thulani_root
diff --git a/apps/thulani_bot/.formatter.exs b/apps/thulani_bot/.formatter.exs
new file mode 100644
index 0000000..d304ff3
--- /dev/null
+++ b/apps/thulani_bot/.formatter.exs
@@ -0,0 +1,3 @@
+[
+ inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
+]
diff --git a/apps/thulani_bot/.gitignore b/apps/thulani_bot/.gitignore
new file mode 100644
index 0000000..302c179
--- /dev/null
+++ b/apps/thulani_bot/.gitignore
@@ -0,0 +1,24 @@
+# The directory Mix will write compiled artifacts to.
+/_build/
+
+# If you run "mix test --cover", coverage assets end up here.
+/cover/
+
+# The directory Mix downloads your dependencies sources to.
+/deps/
+
+# Where third-party dependencies like ExDoc output generated docs.
+/doc/
+
+# Ignore .fetch files in case you like to edit your project deps locally.
+/.fetch
+
+# If the VM crashes, it generates a dump, let's ignore it too.
+erl_crash.dump
+
+# Also ignore archive artifacts (built via "mix archive.build").
+*.ez
+
+# Ignore package tarball (built via "mix hex.build").
+thulani_bot-*.tar
+
diff --git a/apps/thulani_bot/README.md b/apps/thulani_bot/README.md
new file mode 100644
index 0000000..77f6232
--- /dev/null
+++ b/apps/thulani_bot/README.md
@@ -0,0 +1,2 @@
+# Thulani.Bot
+The actual bot running in discord.
diff --git a/apps/thulani_bot/lib/thulani/bot/application.ex b/apps/thulani_bot/lib/thulani/bot/application.ex
new file mode 100644
index 0000000..63bd89e
--- /dev/null
+++ b/apps/thulani_bot/lib/thulani/bot/application.ex
@@ -0,0 +1,13 @@
+defmodule Thulani.Bot.Application do
+ alias Thulani.Bot.Config
+ use Application
+
+ def start(_type, _args) do
+ Config.init!()
+
+ children = []
+
+ opts = [strategy: :one_for_one, name: Thulani.Bot.Supervisor]
+ Supervisor.start_link(children, opts)
+ end
+end
diff --git a/apps/thulani_bot/lib/thulani/bot/config.ex b/apps/thulani_bot/lib/thulani/bot/config.ex
new file mode 100644
index 0000000..5542752
--- /dev/null
+++ b/apps/thulani_bot/lib/thulani/bot/config.ex
@@ -0,0 +1,58 @@
+defmodule Thulani.Bot.Config do
+ @env_vars %{
+ database_url: nil,
+ spreadsheet_id: nil,
+ sheets_api_key: nil,
+ steam_api_key: nil,
+ max_sheet_column: "zz",
+ default_hist: "5",
+ max_hist: "30"
+ }
+
+ require Logger
+
+ def init!() do
+ load_env()
+ |> Enum.each(fn {application, vals} ->
+ Enum.each(vals, fn {key, val} -> Application.put_env(application, key, val) end)
+ end)
+
+ if System.get_env("THULANI_DEBUG") do
+ Application.put_env(:logger, :level, :debug)
+ end
+ end
+
+ def load_env() do
+ if Application.get_env(:thulani, :env) == :dev, do: load_dotenv()
+
+ %{
+ nostrum: [
+ token: System.fetch_env!("THULANI_TOKEN"),
+ shards: System.get_env("THULANI_DISCORD_SHARDS", "1") |> Integer.parse()
+ ],
+ thulani: thulani_env()
+ }
+ end
+
+ defp thulani_env do
+ @env_vars
+ |> Enum.map(fn {env_var, default} ->
+ canonical_env_var =
+ env_var
+ |> to_string
+ |> String.upcase()
+ |> (fn x -> "THULANI_" <> x end).()
+
+ value =
+ canonical_env_var
+ |> System.get_env(default)
+
+ if value == nil do
+ raise "required environment variable not found: #{canonical_env_var}"
+ end
+
+ {env_var, value}
+ end)
+ end
+
+end
diff --git a/apps/thulani_bot/lib/thulani/bot/consumer.ex b/apps/thulani_bot/lib/thulani/bot/consumer.ex
new file mode 100644
index 0000000..f5deec6
--- /dev/null
+++ b/apps/thulani_bot/lib/thulani/bot/consumer.ex
@@ -0,0 +1,23 @@
+defmodule Thulani.Bot.Consumer do
+ use Nostrum.Consumer
+
+ alias Nostrum.Api
+ require Logger
+
+ def start_link do
+ Consumer.start_link(__MODULE__)
+ end
+
+ def handle_event({:MESSAGE_CREATE, {msg}, ws_state}, state) do
+ case msg.content do
+ "!thulani " <> command -> Logger.debug("got command", command: command)
+ _ -> :ignore
+ end
+
+ {:ok, state}
+ end
+
+ def handle_event(_, state) do
+ {:ok, state}
+ end
+end
diff --git a/apps/thulani_bot/mix.exs b/apps/thulani_bot/mix.exs
new file mode 100644
index 0000000..13afa4f
--- /dev/null
+++ b/apps/thulani_bot/mix.exs
@@ -0,0 +1,32 @@
+defmodule Thulani.Bot.MixProject do
+ use Mix.Project
+
+ def project do
+ [
+ app: :thulani_bot,
+ version: "0.1.0",
+ build_path: "../../_build",
+ config_path: "../../config/config.exs",
+ deps_path: "../../deps",
+ lockfile: "../../mix.lock",
+ elixir: "~> 1.9",
+ start_permanent: Mix.env() == :prod,
+ deps: deps()
+ ]
+ end
+
+ def application do
+ [
+ extra_applications: [:logger],
+ mod: {Thulani.Bot.Application, []}
+ ]
+ end
+
+ defp deps do
+ [
+ # we look up the token based on an environment variable, so we can't do this
+ {:nostrum, "~> 0.4"},
+ {:util, in_umbrella: true}
+ ]
+ end
+end
diff --git a/apps/thulani_bot/test/test_helper.exs b/apps/thulani_bot/test/test_helper.exs
new file mode 100644
index 0000000..869559e
--- /dev/null
+++ b/apps/thulani_bot/test/test_helper.exs
@@ -0,0 +1 @@
+ExUnit.start()
diff --git a/apps/thulani_bot/test/thulani/bot/application_test.exs b/apps/thulani_bot/test/thulani/bot/application_test.exs
new file mode 100644
index 0000000..2cc18fb
--- /dev/null
+++ b/apps/thulani_bot/test/thulani/bot/application_test.exs
@@ -0,0 +1,4 @@
+defmodule Thulani.Bot.ApplicationTest do
+ use ExUnit.Case
+ doctest Thulani.Bot.Application
+end
diff --git a/apps/util/.formatter.exs b/apps/util/.formatter.exs
new file mode 100644
index 0000000..d2cda26
--- /dev/null
+++ b/apps/util/.formatter.exs
@@ -0,0 +1,4 @@
+# Used by "mix format"
+[
+ inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
+]
diff --git a/apps/util/.gitignore b/apps/util/.gitignore
new file mode 100644
index 0000000..d8dbee4
--- /dev/null
+++ b/apps/util/.gitignore
@@ -0,0 +1,24 @@
+# The directory Mix will write compiled artifacts to.
+/_build/
+
+# If you run "mix test --cover", coverage assets end up here.
+/cover/
+
+# The directory Mix downloads your dependencies sources to.
+/deps/
+
+# Where third-party dependencies like ExDoc output generated docs.
+/doc/
+
+# Ignore .fetch files in case you like to edit your project deps locally.
+/.fetch
+
+# If the VM crashes, it generates a dump, let's ignore it too.
+erl_crash.dump
+
+# Also ignore archive artifacts (built via "mix archive.build").
+*.ez
+
+# Ignore package tarball (built via "mix hex.build").
+util-*.tar
+
diff --git a/apps/util/README.md b/apps/util/README.md
new file mode 100644
index 0000000..4b69d4c
--- /dev/null
+++ b/apps/util/README.md
@@ -0,0 +1,21 @@
+# Thulani.Util
+
+**TODO: Add description**
+
+## Installation
+
+If [available in Hex](https://hex.pm/docs/publish), the package can be installed
+by adding `util` to your list of dependencies in `mix.exs`:
+
+```elixir
+def deps do
+ [
+ {:util, "~> 0.1.0"}
+ ]
+end
+```
+
+Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
+and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
+be found at [https://hexdocs.pm/util](https://hexdocs.pm/util).
+
diff --git a/apps/util/lib/thulani/util.ex b/apps/util/lib/thulani/util.ex
new file mode 100644
index 0000000..fad5e39
--- /dev/null
+++ b/apps/util/lib/thulani/util.ex
@@ -0,0 +1,2 @@
+defmodule Thulani.Util do
+end
diff --git a/apps/util/lib/thulani/util/compose.ex b/apps/util/lib/thulani/util/compose.ex
new file mode 100644
index 0000000..cd4435e
--- /dev/null
+++ b/apps/util/lib/thulani/util/compose.ex
@@ -0,0 +1,13 @@
+defmodule Thulani.Util.Compose do
+ import Thulani.Util.Curry
+
+ def f <|> g, do: compose(f, g)
+
+ def compose(f, g) when is_function(g) do
+ fn arg -> compose(curry(f), curry(g).(arg)) end
+ end
+
+ def compose(f, arg) do
+ f.(arg)
+ end
+end
diff --git a/apps/util/lib/thulani/util/curry.ex b/apps/util/lib/thulani/util/curry.ex
new file mode 100644
index 0000000..b03afab
--- /dev/null
+++ b/apps/util/lib/thulani/util/curry.ex
@@ -0,0 +1,16 @@
+defmodule Thulani.Util.Curry do
+ @moduledoc false
+
+ def curry(f) do
+ {_, arity} = :erlang.fun_info(f, :arity)
+ curry(f, arity, [])
+ end
+
+ defp curry(f, 0, args) do
+ apply(f, Enum.reverse(args))
+ end
+
+ defp curry(f, arity, args) do
+ fn arg -> curry(f, arity - 1, [arg | args]) end
+ end
+end
diff --git a/apps/util/mix.exs b/apps/util/mix.exs
new file mode 100644
index 0000000..a0caff9
--- /dev/null
+++ b/apps/util/mix.exs
@@ -0,0 +1,27 @@
+defmodule Thulani.Util.MixProject do
+ use Mix.Project
+
+ def project do
+ [
+ app: :util,
+ version: "0.1.0",
+ build_path: "../../_build",
+ config_path: "../../config/config.exs",
+ deps_path: "../../deps",
+ lockfile: "../../mix.lock",
+ elixir: "~> 1.9",
+ start_permanent: Mix.env() == :prod,
+ deps: deps()
+ ]
+ end
+
+ def application do
+ [
+ extra_applications: [:logger]
+ ]
+ end
+
+ defp deps do
+ []
+ end
+end
diff --git a/apps/util/test/test_helper.exs b/apps/util/test/test_helper.exs
new file mode 100644
index 0000000..869559e
--- /dev/null
+++ b/apps/util/test/test_helper.exs
@@ -0,0 +1 @@
+ExUnit.start()
diff --git a/apps/util/test/thulani/util_test.exs b/apps/util/test/thulani/util_test.exs
new file mode 100644
index 0000000..9246f40
--- /dev/null
+++ b/apps/util/test/thulani/util_test.exs
@@ -0,0 +1,4 @@
+defmodule Thulani.UtilTest do
+ use ExUnit.Case
+ doctest Thulani.Util
+end
diff --git a/config.example.toml b/config.example.toml
new file mode 100644
index 0000000..3ff5459
--- /dev/null
+++ b/config.example.toml
@@ -0,0 +1,10 @@
+[thulani]
+token = "aaaaaaa"
+database_url = "bbbbbbb"
+spreadsheet_id = "google_sheets_id"
+sheets_api_key = "cccccccccc"
+max_sheet_column = "ZZZ"
+steam_api_key = "ddddddddddd"
+max_hist = 30
+default_hist = 5
+prefixes = ["thulani", "thulando", "thulando madando"]
diff --git a/config/config.exs b/config/config.exs
new file mode 100644
index 0000000..f0746d1
--- /dev/null
+++ b/config/config.exs
@@ -0,0 +1,9 @@
+import Config
+
+config :thulani,
+ env: Mix.env()
+
+config :logger,
+ level: :info
+
+import_config "#{Mix.env}.exs" \ No newline at end of file
diff --git a/config/dev.exs b/config/dev.exs
new file mode 100644
index 0000000..9cba782
--- /dev/null
+++ b/config/dev.exs
@@ -0,0 +1,14 @@
+import Config
+
+config :logger,
+ level: :debug
+
+config :nostrum,
+ dev: true
+
+IO.puts("hello")
+
+Thulani.Bot.Config.load_env()
+|> Enum.each(fn {key, vals} ->
+ config key, vals
+end)
diff --git a/config/load_from_dotenv.exs b/config/load_from_dotenv.exs
new file mode 100644
index 0000000..244e2bc
--- /dev/null
+++ b/config/load_from_dotenv.exs
@@ -0,0 +1,36 @@
+def load_dotenv!() do
+ {:ok, projroot} = __DIR__ |> get_projroot
+
+ contents =
+ case projroot |> Path.join(".env") |> File.read() do
+ {:error, :enoent} ->
+ Logger.warn("skipping dotenv file: doesn't exist")
+ ""
+
+ {:ok, contents} ->
+ contents
+ end
+
+ contents
+ |> String.split("\n")
+ |> Enum.map(&String.trim/1)
+ |> Enum.filter(fn x -> x != "" end)
+ |> Enum.map(fn x ->
+ result = String.split(x, "=")
+ {Enum.at(result, 0), Enum.at(result, 1)}
+ end)
+ |> System.put_env()
+end
+
+def get_projroot(base) do
+ result =
+ with {:ok, info} <- base |> Path.join(".thulani_root") |> File.stat(),
+ :regular <- info.type,
+ do: {:ok, base}
+
+ case result do
+ {:error, :enoent} -> get_projroot(base |> Path.join("..") |> Path.expand())
+ {:ok, "/"} -> {:error, "couldn't find .thulani_root"}
+ x -> x
+ end
+end
diff --git a/config/prod.exs b/config/prod.exs
new file mode 100644
index 0000000..ba90609
--- /dev/null
+++ b/config/prod.exs
@@ -0,0 +1,5 @@
+import Config
+
+config :logger,
+ utc_log: true,
+ level: :warn
diff --git a/config/release.exs b/config/release.exs
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/config/release.exs
@@ -0,0 +1 @@
+
diff --git a/mix.exs b/mix.exs
new file mode 100644
index 0000000..ada3618
--- /dev/null
+++ b/mix.exs
@@ -0,0 +1,43 @@
+defmodule Thulani.MixProject do
+ use Mix.Project
+
+ def project do
+ [
+ apps_path: "apps",
+ version: "0.1.0",
+ start_permanent: Mix.env() == :prod,
+ deps: deps(),
+ releases: releases(),
+ default_release: :thulani_flex
+ ]
+ end
+
+ defp deps do
+ [
+ {:toml, "~> 0.6.1"}
+ ]
+ end
+
+ defp releases do
+ config_providers = [
+ # {Toml.Provider, ["./config.toml", "/etc/thulani/config.toml"]}
+ ]
+
+ applications = [thulani_bot: :permanent]
+
+ [
+ thulani_flex: [
+ include_executables_for: [:unix, :windows],
+ strip_beams: false,
+ config_providers: config_providers,
+ applications: applications
+ ],
+ thulani_prod: [
+ include_executables_for: [:unix],
+ strip_beams: true,
+ config_providers: config_providers,
+ applications: applications
+ ]
+ ]
+ end
+end
diff --git a/mix.lock b/mix.lock
new file mode 100644
index 0000000..93687d1
--- /dev/null
+++ b/mix.lock
@@ -0,0 +1,17 @@
+%{
+ "certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
+ "cowlib": {:hex, :cowlib, "2.6.0", "8aa629f81a0fc189f261dc98a42243fa842625feea3c7ec56c48f4ccdb55490f", [:rebar3], [], "hexpm"},
+ "gen_stage": {:hex, :gen_stage, "0.14.3", "d0c66f1c87faa301c1a85a809a3ee9097a4264b2edf7644bf5c123237ef732bf", [:mix], [], "hexpm"},
+ "gun": {:hex, :gun, "1.3.1", "1489fd96018431b89f401041a9ce0b02b45265247f0fdcf71273bf087c64ea4f", [:rebar3], [{:cowlib, "~> 2.6.0", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm"},
+ "hackney": {:hex, :hackney, "1.15.2", "07e33c794f8f8964ee86cebec1a8ed88db5070e52e904b8f12209773c1036085", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.5", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
+ "httpoison": {:hex, :httpoison, "1.6.2", "ace7c8d3a361cebccbed19c283c349b3d26991eff73a1eaaa8abae2e3c8089b6", [:mix], [{:hackney, "~> 1.15 and >= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
+ "idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
+ "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
+ "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"},
+ "nostrum": {:hex, :nostrum, "0.4.1", "da5f1ad98146117f6b7884e144c38fdc2b2a413d863d88a73297c67ef86fc863", [:mix], [{:gen_stage, "~> 0.11", [hex: :gen_stage, repo: "hexpm", optional: false]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: false]}, {:httpoison, "~> 1.5", [hex: :httpoison, repo: "hexpm", optional: false]}, {:poison, "~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
+ "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"},
+ "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"},
+ "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm"},
+ "toml": {:hex, :toml, "0.6.1", "e1c3c91c1fc1ed87e7315a5a88e4bd1eeddf3e61dca2b708724a6a2d1a013844", [:mix], [], "hexpm"},
+ "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
+}
diff --git a/rel/env.bat.eex b/rel/env.bat.eex
new file mode 100644
index 0000000..2ecd77f
--- /dev/null
+++ b/rel/env.bat.eex
@@ -0,0 +1,7 @@
+@echo off
+rem Set the release to work across nodes. If using the long name format like
+rem the one below (my_app@127.0.0.1), you need to also uncomment the
+rem RELEASE_DISTRIBUTION variable below.
+
+set RELEASE_DISTRIBUTION=name
+set RELEASE_NODE=<%= @release.name %>@0.0.0.0
diff --git a/rel/env.sh.eex b/rel/env.sh.eex
new file mode 100644
index 0000000..365fa18
--- /dev/null
+++ b/rel/env.sh.eex
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Sets and enables heart (recommended only in daemon mode)
+case $RELEASE_COMMAND in
+ daemon*)
+ export HEART_COMMAND="$RELEASE_ROOT/bin/$RELEASE_NAME $RELEASE_COMMAND"
+ export ELIXIR_ERL_OPTIONS="-heart"
+ ;;
+
+ *)
+ ;;
+esac
+
+# Set the release to work across nodes. If using the long name format like
+# the one below (my_app@127.0.0.1), you need to also uncomment the
+# RELEASE_DISTRIBUTION variable below.
+export RELEASE_DISTRIBUTION=name
+export RELEASE_NODE="<%= @release.name %>@0.0.0.0"
diff --git a/rel/vm.args.eex b/rel/vm.args.eex
new file mode 100644
index 0000000..71e8032
--- /dev/null
+++ b/rel/vm.args.eex
@@ -0,0 +1,11 @@
+## Customize flags given to the VM: http://erlang.org/doc/man/erl.html
+## -mode/-name/-sname/-setcookie are configured via env vars, do not set them here
+
+## Number of dirty schedulers doing IO work (file, sockets, etc)
+##+SDio 5
+
+## Increase number of concurrent ports/sockets
+##+Q 65536
+
+## Tweak GC to run more often
+##-env ERL_FULLSWEEP_AFTER 10