Keyword arguments in Ruby +2.1

Tagged argument, keyword, options, ruby  Languages ruby

Before keyword arguments were introduced in Ruby:

def call(options={})
  puts options[:optional_param]
  puts options.fetch(:optional_param_with_default, 'default')
  puts options.fetch(:mandatory_param)


def call(mandatory_param:, optional_param: nil, optional_param_with_default: 'default')
  puts optional_param
  puts optional_param_with_default
  puts mandatory_param

Multi-tenancy in Ecto and Phoenix

Tagged ecto, elixir, multi-tenancy, postgres, phoenix  Languages bash, elixir

Creating a new tentant

A new tenant requires a namespace, which is a schema in Postgres, and a prefix in Ecto:

$ psql -U postgres database_x
> create schema aktagon; 

Querying data

import Ecto.Query
email = ""
q = from(m in User, where: == ^email)
Repo.all(%{q | prefix: "aktagon"})


Inserting data

   %User{ email: "" },
   prefix: "aktagon"


$ mix ecto.migrate --prefix "aktagon"


  • (KeyError) key :__meta__ not found

I got this error when passing a changeset to Ecto.put_meta instead of a User struct.

How to fix "the response was already sent" error in Elixir

Tagged elixir, phoenix, plug  Languages elixir

If you get an “(Plug.Conn.AlreadySentError) the response was already sent” error:

Server: localhost:4000 (http)
Request: POST /api/v1/xxx
** (exit) an exception was raised:
    ** (Plug.Conn.AlreadySentError) the response was already sent
        (plug) lib/plug/conn.ex:332: Plug.Conn.put_status/2

Verify that you do not have defined the action plug multiple times:

plug :action

How to send emails with Mailgun and Elixir

Tagged elixir, httpotion, mailgun  Languages elixir

This example shows how to send emails with Mailgun and Elixir:

url = ""
headers = [
  "User-Agent": "My App",
  "Content-Type": "application/x-www-form-urlencoded"
params = %{
  "from" => "",
  "to" => "",
  "subject" => "Hello Christian",
  "text" => "Hello"
body = URI.encode_query(params)
auth = { "api", "key-xxx" }
response = url, [body: body, headers: headers, basic_auth: auth]
if !HTTPotion.Response.success?(response) do

Replace the API key and mailgun URL with your own API key and URL.


How to use fswatch to run a command when a file is changed

Tagged fswatch, rspec  Languages bash

This example executes the the rspec command when a Ruby file is modified in the current directory:

# watch .rb files in spec directory and execute rspec <file>
fswatch -0 -e ".*" -i ".rb" . | xargs -0 -n 1 -I {} rspec {}

Note that fswatch will execute test concurrently if the same test file is changed again before the previous test has time to complete.

Haproxy configuration template with SSL

Tagged haproxy, ssl, template  Languages 
# HAProxy documentation:
# Inspiration:
  # syslog
  log               /dev/log local0
  log      local1 notice
  # run as haproxy
  user              haproxy
  group             haproxy
  # total number of allowed open connections
  maxconn           50000
  pidfile           /var/run/
  # random health checks
  spread-checks     5
  # run in background
  # SSL certificates are found here
  ca-base           /etc/ssl/certs
  crt-base          /etc/ssl/private
  # SSL hardening, see
  tune.ssl.default-dh-param   2048
  ssl-default-bind-options    no-sslv3
  ssl-default-server-options  no-sslv3
  # uncomment to debug

# defaults apply to all servers
  log               global
  # requests use HTTP protocol
  mode              http
  # log HTTP requests
  option            httplog
  # keep alive connections between client and balancer. Close connections between balancer and backend
  option            http-server-close
  # X-Forwarded-For header
  option            forwardfor
  # Client closed connection, abort request
  option            abortonclose
  # if request fails, resend request to up to 2 servers
  retries           3
  # request can be handled by any server in case of failure
  option            redispatch
  # total number of allowed open connections per server
  maxconn           25000
  # health check fails it takes longer than this to respond
  timeout check     5s
  timeout client    30s
  timeout connect   30s
  timeout server    30s

# Define frontends (haproxy)
frontend http
  bind            *:80
  # redirect HTTP to HTTPS
  redirect scheme https if !{ ssl_fc }
  default_backend http-backend

frontend https
  bind            *:443 ssl crt
  default_backend http-backend

# Define backends (Rails, Go, Elixir, etc)
backend http-backend
  balance         roundrobin
  # health check is done by fetching /
  option          httpchk HEAD / HTTP/1.1
  # Define two backend servers
  server          http1 check #inter 5s rise 18 fall 2
  server          http2 check #inter 5s rise 18 fall 2
  # Set HTTP headers
  http-request    set-header X-Forwarded-Port %[dst_port]
  http-request    add-header X-Forwarded-Proto https if { ssl_fc }

Using rsyslog for remote logging (Rails and Haproxy)

Tagged rsyslog, haproxy, rails  Languages bash, ruby

First, tell your application to use syslog

# Example in config/production.rb:
#   config.logger =
#   config.log_tags = [ :uuid, :remote_ip ]
require 'syslog/logger'

class LogHelper
  PROGRAM_NAME = "rails"
  LEVEL = Logger::DEBUG

  # Maps syslog severity to a string
    0 => 'debug',
    1 => 'info',
    2 => 'warn',
    3 => 'error',
    nil => ''

    # There can only be one program name
    l =
    l.formatter = proc do |severity, datetime, progname, msg|
      "[#{SEVERITY_MAP[severity].center(5)}] #{msg}\n"
    l.level = LEVEL
    # Add tags to log messages from thread local context, e.g., request.uuid


logger ="test")

Install and configure the rsyslog server

Next install rsyslog on the server:

$ sudo apt-get install rsyslog

Uncomment the TCP module:

# provides TCP syslog reception
$ModLoad imtcp
$InputTCPServerRun 514

Comment out the IncludeConfig directive:

# $IncludeConfig /etc/rsyslog.d/*.conf

We’ll use a DynaFile to simplify the rsyslog configuration:

$template DynaFile,"/var/log/hosts/%HOSTNAME%/%PROGRAMNAME%.log"
*.* -?DynaFile

This tells rsyslog to write to a file named after the host and program that sent the message, e.g., /var/log/hosts/prod-1/rails.log.

Install and configure rsyslog clients

The naming of rsyslog configuration files IS important. Rules are processed in alphabetic order according to file name:

$ ls /var/rsyslog.d/

First, tell syslog to forward everything to the remote rsyslog server by editing /etc/rsyslog.conf:

# Send all logs to centralized log server over TCP
*.*       @@

# Include all config files in /etc/rsyslog.d/
$IncludeConfig /etc/rsyslog.d/*.conf

You can configure application logs to be written to a local file in addition to the default (remote server):

if $programname startswith 'rails' then {
  # Uncomment this to disable forwarding:
  # & stop

Configure Haproxy

Add log-send-hostname to the haproxy configuration.

Haproxy only seems to work with UDP logging, so enable it in /etc/rsyslog.conf:

$ModLoad imudp
$UDPServerRun 514

Restarting rsyslog

Remember to restart rsyslog after checking the configuration is valid:

$ rsyslogd -N1
$ sudo service rsyslog restart

Tested with rsyslog version 8.


  • rsyslog’s default rate-limiting configuration will drop messages
  • make sure to check rsyslog’s own logs for warnings
  • you probably want to use monit to monitor that rsyslog is writing log messages to disk

Annotated Plug and Elixir Example

Tagged cowboy, elixir, erlang, genserver, otp, plug  Languages elixir, bash

This is an annotated example of a web application written using Elixir and Plug.

Create mix.exs:

# Mix is a build tool that provides tasks for creating, compiling, and testing
# Elixir projects, managing its dependencies, and more.
defmodule PlugExample.Mixfile do
  # In order to configure Mix, a developer needs to use Mix.Project in a module
  # and define a function named project that returns a keyword list with
  # configuration.
  use Mix.Project

  # Configure project.
  def project do
    [app: :Router,
      version: "0.0.1",
      elixir: "~> 1.2",
      deps: deps]

  # Returns applications that should be started.
  # In OTP, application denotes a component implementing some specific
  # functionality, that can be started and stopped as a unit, and which can be
  # re-used in other systems as well.
  def application do
      applications: [:logger, :plug], # 3rd-party applications
      mod: {PlugExample.Supervisor, []} # own application

  # Returns project dependencies:
  def deps do
      {:cowboy, "~> 1.0.0"}, # Erlang web server
      {:plug, "~> 1.0"} # Elixir's rack (Ruby), wsgi (Python), servlet (Java) API

Create lib/router.exs

defmodule PlugExample.Router do
  # Plug ships with a router that allows developers to quickly match on
  # incoming requests and perform some action:
  use Plug.Router
  # This module defines a Plug.Conn struct and the main functions for working with Plug connections.
  import Plug.Conn
  # Logs request to STDOUT
  plug Plug.Logger
  # Matches request to a route
  plug :match
  # Dispatches request to a route
  plug :dispatch

  # Start a GenServer, i.e., a server instance:
  def start_link do
    # Cowboy adapter:
    {:ok, _} = Plug.Adapters.Cowboy.http PlugExample.Router, []

  # HTTP GET /
  # Use conn.private to access route options:
  #   conn.private[:protected]
  get "/", private: %{protected: false} do
    conn |> send_resp(200, "Hello world")

  get "/favicon.ico" do
    conn |> send_resp(200, "LOL")
  # Forward /about to another router's get "/" route
  # forward "/about", to: PlugExample.About

  # A catch-all route
  match _ do
    conn |> send_resp(404, "Not found")

Create lib/supervisor.ex

# A supervisor is a process which supervises other processes, called child
# processes. Supervisors are used to build a hierarchical process structure
# called a supervision tree, a nice way to structure fault-tolerant applications.
defmodule PlugExample.Supervisor do
  # In Elixir (actually, in Erlang/OTP), an application is a component
  # implementing some specific functionality, that can be started and stopped as a
  # unit, and which can be re-used in other systems.
  use Application

  # The type argument passed to start/2 is usually :normal unless in a
  # distributed setup where application takeovers and failovers are configured.
  # start/2 typically returns {:ok, pid} or {:ok, pid, state} where pid
  # identifies the supervision tree and state is the application state.
  def start(_type, _args) do
    # Convenience functions for defining a supervision specification.
    import Supervisor.Spec, warn: false
    # A list of children (workers or supervisors) to supervise
    children = [
      worker(PlugExample.Router, [])
    # If a child process terminates, only that process is restarted:
    opts = [strategy: :one_for_one, name: PlugExample.Supervisor]
    # Start supervisor by passing the children to start_link/2.
    # You may want to use a module-based supervisor.
    Supervisor.start_link(children, opts)

Start the server:

$ mix deps.get
$ iex -S mix

Continue reading: How to deploy an Elixir web application.

Elixir Deployment

Tagged deployment, elixir, exrm, deploy, rollback, upgrade  Languages bash


Development environment:

  1. Sign up for a Gitlab account, or use your favorite git server
  2. Create a (private) repository
  3. Create a deploy key that allows read-only access to your private repository (optional, if public)
  4. Commit code to the repository


Production environment:

  1. Clone project
$ cd /var/www
$ git clone
  1. Create a release
$ MIX_ENV=prod mix do deps.get, clean, compile
$ MIX_ENV=prod mix release --verbosity=verbose
  1. Create a monit start script
check process snippets MATCHING "snippets/bin/snippets"
    start program = "/bin/su - deploy -c '/var/www/aktagon-snippets/rel/snippets/bin/snippets start'"
    stop program = "/bin/su - deploy -c '/var/www/aktagon-snippets/rel/snippets/bin/snippets stop'"
  1. Start server
$ sudo monit start snippets

Deploying a new version

How to perform hot upgrades:

$ git pull
$ MIX_ENV=prod mix do compile, release
$ rel/snippets/bin/snippets upgrade "0.0.2"

Rolling back to a previous version

How to perform hot downgrades:

$ rel/snippets/bin/snippets downgrade "0.0.1"