diff --git a/Makefile b/Makefile
index b5ee9911a886b56f44eb6e11d5481e8db5d514da..f0ef9e5ec6322965484b8b93cfbc53f3fd7d656a 100644
--- a/Makefile
+++ b/Makefile
@@ -12,7 +12,7 @@ compile:
 	@$(REBAR) compile
 
 eunit:
-	@FORMAT="compact" ERL_AFLAGS="-args_file config/test-vm.args -config config/test-sys.config" $(REBAR) as test do eunit --cover --application=consul_proxy --dir=apps/consul_proxy/test, cover --verbose
+	$(REBAR) as test do eunit --cover --application=consul_proxy --dir=apps/consul_proxy/test, cover --verbose
 
 dialyzer:
 	@$(REBAR) dialyzer
diff --git a/apps/consul_proxy/priv/Dockerfile b/apps/consul_proxy/priv/Dockerfile
index 6364e316c4dd816c9dbe8ceb7ef0a661d59677da..b312bc9818b71e467fd4252839383aee233499bd 100644
--- a/apps/consul_proxy/priv/Dockerfile
+++ b/apps/consul_proxy/priv/Dockerfile
@@ -1,12 +1,12 @@
-FROM        hedenstroem/otp
+FROM        hedenstroem/otp:19.1
 MAINTAINER  Erik Hedenström <erik@erlang.ninja>
 
-ENV NAME_PREFIX consul_proxy
+ENV NAME_PREFIX {{release_name}}
 ENV COOKIE Nax7jEj7bay6ril
 
-ADD rel/consul_proxy/consul_proxy-${REL_VSN}.tar.gz /opt/consul_proxy
+ADD {{release_name}}-{{rel_vsn}}.tar.gz /opt/{{release_name}}
 
 EXPOSE 8080-8083
 
-ENTRYPOINT [ "/opt/consul_proxy/bin/consul_proxy-wrapper" ]
+ENTRYPOINT [ "/opt/{{release_name}}/bin/wrapper" ]
 CMD [ "foreground" ]
diff --git a/apps/consul_proxy/priv/consul_proxy-wrapper b/apps/consul_proxy/priv/wrapper
similarity index 84%
rename from apps/consul_proxy/priv/consul_proxy-wrapper
rename to apps/consul_proxy/priv/wrapper
index 7de6a3eb7f0a21926a45966f348a2c1418ebdde7..a4c26e902b0f8e57d438db8b1c876c48151365a9 100755
--- a/apps/consul_proxy/priv/consul_proxy-wrapper
+++ b/apps/consul_proxy/priv/wrapper
@@ -9,7 +9,7 @@ fi;
 SCRIPT_DIR="$(cd `dirname "$SCRIPT"` && pwd -P)"
 
 if [ -z "$NAME_PREFIX" ]; then
-    NAME_PREFIX="consul_proxy-$(openssl rand -hex 4)"
+    NAME_PREFIX="{{release_name}}-$(openssl rand -hex 4)"
 fi
 
 if [ -z "$COOKIE" ]; then
@@ -25,4 +25,4 @@ export NODE_NAME=${NAME_PREFIX}@${HOST_IP}
 
 echo "Starting ${NODE_NAME} with cookie ${COOKIE}"
 
-${SCRIPT_DIR}/consul_proxy $@
+${SCRIPT_DIR}/{{release_name}} $@
diff --git a/apps/consul_proxy/src/consul_client.erl b/apps/consul_proxy/src/consul_client.erl
index 46215a38119581c03c35a552989a3701e40344af..ef9be505145e447a86bbedbe1e29038ea72042af 100644
--- a/apps/consul_proxy/src/consul_client.erl
+++ b/apps/consul_proxy/src/consul_client.erl
@@ -503,7 +503,7 @@ watch(Parent, Path, PathWithIndex, Delay) ->
 
 -spec trigger_webhooks(Path :: binary, Index :: number()) -> any().
 trigger_webhooks(<<"/v1/kv/consul_proxy?recurse">>, Index) ->
-    trigger_webhooks(<<"consul_proxy/watchers/kv">>, Index, []);
+    trigger_webhooks(<<"consul_proxy/watchers/kv">>, Index, [{<<"index">>, Index}]);
 trigger_webhooks(<<"/v1/catalog/services">>, Index) ->
     case consul_client:services() of
         {ok, Services} ->
diff --git a/apps/consul_proxy/src/consul_proxy.app.src b/apps/consul_proxy/src/consul_proxy.app.src
index 548d36bed4fe641b26990cad9afee2bf8b35cf0b..8bc1ff176f5816b47f93b3acfe6e8c692b7742b5 100644
--- a/apps/consul_proxy/src/consul_proxy.app.src
+++ b/apps/consul_proxy/src/consul_proxy.app.src
@@ -1,6 +1,6 @@
 {application, consul_proxy, [
     {description, "Proxy for docker swarm using consul and vegur"},
-    {vsn, "0.5.3"},
+    {vsn, "0.5.4"},
     {registered, []},
     {mod, {consul_proxy_app, []}},
     {applications, [
diff --git a/apps/consul_proxy/src/consul_proxy_lager_backend.erl b/apps/consul_proxy/src/consul_proxy_lager_backend.erl
index 825e1e9df03184e996891eddbaa6981e0e082c0e..b5fb8ab733b8ed8352ccedd098c9c450ec765152 100644
--- a/apps/consul_proxy/src/consul_proxy_lager_backend.erl
+++ b/apps/consul_proxy/src/consul_proxy_lager_backend.erl
@@ -7,7 +7,6 @@
 -record(state, {level, formatter, config, socket}).
 
 init(Config) ->
-    random:seed(erlang:phash2([node()]), erlang:monotonic_time(), erlang:unique_integer()),
     Level = proplists:get_value(level, Config, info),
     Formatter = proplists:get_value(formatter, Config, consul_proxy_request_formatter),
     Levels = lager_util:config_to_mask(Level),
@@ -69,14 +68,14 @@ pick_node([]) ->
 pick_node([Node]) ->
     Node;
 pick_node(Nodes) ->
-    N = random:uniform(length(Nodes)),
+    N = rand:uniform(length(Nodes)),
     lists:nth(N, Nodes).
 
 %% @private
 lookup_nodes() ->
     case consul_proxy_utils:cache_get(logservice) of
         undefined ->
-            Service = application:get_env(consul_proxy, logservice, "logstash-udp"),
+            Service = application:get_env(consul_proxy, logservice, "logstash"),
             case consul_client:service(Service) of
                 {ok, List} ->
                     Nodes = lists:map(
diff --git a/apps/consul_proxy/src/consul_proxy_loadbalancer.erl b/apps/consul_proxy/src/consul_proxy_loadbalancer.erl
index 7cd0623e9e4064be18f103598e1e3f08b2942c53..39fb699e566559df2adcf689d6ecf24b32bfbb5b 100644
--- a/apps/consul_proxy/src/consul_proxy_loadbalancer.erl
+++ b/apps/consul_proxy/src/consul_proxy_loadbalancer.erl
@@ -97,7 +97,6 @@ start_link(Args) ->
     {stop, Reason :: term()} | ignore).
 init(Args) ->
     lager:info("Args: ~p", [Args]),
-    random:seed(erlang:phash2([node()]), erlang:monotonic_time(), erlang:unique_integer()),
     Counter = tsuru_counter:new(),
     ForwardDecays = ets:new(forward_decays, [set, {write_concurrency, true}]),
     Weights = ets:new(weights, [set, {write_concurrency, true}]),
@@ -118,7 +117,7 @@ init(Args) ->
     {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
     {stop, Reason :: term(), NewState :: #state{}}).
 handle_call({pick, random, Services}, _From, State) ->
-    Index = random:uniform(length(Services)),
+    Index = rand:uniform(length(Services)),
     Pick = lists:nth(Index, Services),
     {reply, {ok, Pick, lists:delete(Pick, Services)}, State};
 
@@ -129,7 +128,7 @@ handle_call({pick, jsq, Services}, _From, State = #state{counter = Counter}) ->
                 {Service, get_count(Counter, Service), NewServices};
             (Candidate, {Current, CurrentCount, NewServices}) ->
                 CandidateCount = get_count(Counter, Candidate),
-                OneOrTwo = random:uniform(2),
+                OneOrTwo = rand:uniform(2),
                 if
                     CandidateCount < CurrentCount -> {Candidate, CandidateCount, [Current | NewServices]};
                     CandidateCount > CurrentCount -> {Current, CurrentCount, [Candidate | NewServices]};
@@ -147,7 +146,7 @@ handle_call({pick, esl, Services}, _From, State) ->
                 {Candidate, Weight, []};
             ({Candidate, Weight}, {Current, Sum, NewServices}) ->
                 NewSum = Sum + Weight,
-                R = random:uniform(NewSum),
+                R = rand:uniform(NewSum),
                 if
                     R > Sum ->
                         {Candidate, NewSum, [Current | NewServices]};
@@ -158,19 +157,19 @@ handle_call({pick, esl, Services}, _From, State) ->
     {reply, {ok, Pick, ServicesExcludingPick}, State};
 
 handle_call({sort, random, Services}, _From, State) ->
-    ShuffledServices = [R || {_, R} <- lists:sort([{random:uniform(), S} || S <- Services])],
+    ShuffledServices = [R || {_, R} <- lists:sort([{rand:uniform(), S} || S <- Services])],
     {reply, {ok, ShuffledServices}, State};
 
 handle_call({sort, jsq, Services}, _From, State = #state{counter = Counter}) ->
     OrderingFun = fun({A, _}, {B, _}) -> A =< B end,
-    ShuffledServices = [R || {_, R} <- lists:sort(OrderingFun, [{random:uniform(), S} || S <- Services])],
+    ShuffledServices = [R || {_, R} <- lists:sort(OrderingFun, [{rand:uniform(), S} || S <- Services])],
     WeightedServices = [{get_count(Counter, Service), Service} || Service <- ShuffledServices],
     SortedServices = [R || {_, R} <- lists:sort(OrderingFun, WeightedServices)],
     {reply, {ok, SortedServices}, State};
 
 handle_call({sort, esl, Services}, _From, State) ->
     OrderingFun = fun({A, _}, {B, _}) -> A =< B end,
-    ShuffledServices = [R || {_, R} <- lists:sort(OrderingFun, [{random:uniform(), S} || S <- Services])],
+    ShuffledServices = [R || {_, R} <- lists:sort(OrderingFun, [{rand:uniform(), S} || S <- Services])],
     WeightedServices = [{get_weight(State, Service), Service} || Service <- ShuffledServices],
     SortedServices = [R || {_, R} <- lists:sort(OrderingFun, WeightedServices)],
     {reply, {ok, SortedServices}, State};
diff --git a/apps/consul_proxy/src/consul_proxy_router.erl b/apps/consul_proxy/src/consul_proxy_router.erl
index 25395655498df67776a74dcc8aa3d392a569fb96..3baacc3992fd19a7dd667f85a5a07710a9c5c28b 100644
--- a/apps/consul_proxy/src/consul_proxy_router.erl
+++ b/apps/consul_proxy/src/consul_proxy_router.erl
@@ -16,8 +16,7 @@
 
 -record(state, {services = undefined, headers = []}).
 
-init(AcceptTime, Upstream) ->
-    random:seed(AcceptTime),
+init(_AcceptTime, Upstream) ->
     {ok, Upstream, #state{}}.
 
 lookup_domain_name(Domain, Upstream, HandlerState) ->
diff --git a/apps/consul_proxy/test/common_steps.erl b/apps/consul_proxy/test/common_steps.erl
index e2f758ccfe71ee6b995cc3ebf54fc2a878ed4913..8a28a1d5694137952cf5a77cf5ba87e8274d17a9 100644
--- a/apps/consul_proxy/test/common_steps.erl
+++ b/apps/consul_proxy/test/common_steps.erl
@@ -25,26 +25,20 @@ setup_feature(_Tokens) ->
             {K, V}
         end, os:getenv()),
     lager:debug("~p", [Env]),
-    application:ensure_all_started(inets),
-    application:ensure_all_started(nkdocker),
-    {_Pid, State} = get_nkdocker_pid(#{os_env => Env, test_env => [], nkdocker_ids => []}),
-    {ok, State}.
+    application:ensure_all_started(hackney),
+    {ok, Pid} = dockerl:start_link(socket, <<"/var/run/docker.sock">>),
+    IPAddress = list_to_binary(inet:ntoa(local_ip_v4())),
+    {ok, #{os_env => Env, test_env => [{<<"ip_address">>, IPAddress}], applications => [], containers => [], dockerl_pid => Pid}}.
 
-teardown_feature(#{nkdocker_pid := Pid, nkdocker_ids := Ids}) ->
-    {async, Ref} = nkdocker:events(Pid),
+teardown_feature(#{dockerl_pid := Pid, containers := Containers, applications := Applications}) ->
+    [application:stop(Application) || Application <- lists:reverse(Applications)],
     lists:foreach(
         fun({Name, Id}) ->
-            ok = nkdocker:kill(Pid, Id),
-            nkdocker_receive_status(Ref, Id, <<"kill">>),
-            nkdocker_receive_status(Ref, Id, <<"die">>),
-            lager:notice("Docker container ~s killed", [Name]),
-            ok = nkdocker:rm(Pid, Id),
-            nkdocker_receive_status(Ref, Id, <<"destroy">>),
-            lager:notice("Docker container ~s destroyed", [Name])
-        end, Ids),
-    nkdocker:finish_async(Pid, Ref),
-    nkdocker_receive(Ref, {ok, user_stop}),
-    nkdocker:stop(Pid),
+            ok = dockerl:stop_container(Pid, Id),
+            lager:notice("Docker container ~s stopped", [Name]),
+            ok = dockerl:remove_container(Pid, Id),
+            lager:notice("Docker container ~s removed", [Name])
+        end, Containers),
     ok;
 teardown_feature(_State) ->
     ok.
@@ -56,63 +50,67 @@ teardown_scenario(_State) ->
     ok.
 
 %% noinspection ErlangUnboundVariable
-given([<<"a">>, <<"docker">>, <<"container">>, <<"named">>, Name, <<"running">>, Image, <<"with">>, <<"commands:">>, {docstring, Args}], State = #{nkdocker_pid := Pid, nkdocker_ids := Ids}) ->
+given([<<"a">>, <<"docker">>, <<"container">>, <<"named">>, Name, <<"running">>, Image, <<"with">>, <<"commands:">>, {docstring, Args}], State = #{dockerl_pid := Pid, containers := Containers}) ->
     InterpolatedImage = consul_proxy_utils:string_interpolate(Image, maps:get(os_env, State, []) ++ maps:get(test_env, State, []), []),
-    {async, Ref} = nkdocker:events(Pid),
-    {ok, #{<<"Id">> := Id}} = nkdocker:create(Pid, InterpolatedImage,
+    {ok, _} = dockerl:pull_image(Pid, Image),
+    {ok, Id} = dockerl:create_container(Pid, Image,
         #{
-            publish_all => true,
-            cmds => binary:split(Args, <<" ">>, [trim_all, global])
+            'Tty' => true,
+            'Cmd' => binary:split(Args, <<" ">>, [trim_all, global]),
+            'PublishAllPorts' => true
         }),
-    nkdocker_receive_status(Ref, Id, <<"create">>),
     lager:notice("Docker container ~s running ~s created: ~s", [Name, InterpolatedImage, Id]),
-    ok = nkdocker:start(Pid, Id),
-    nkdocker_receive_status(Ref, Id, <<"start">>),
-    lager:notice("Docker container ~s started", [Name]),
-    nkdocker:finish_async(Pid, Ref),
-    nkdocker_receive(Ref, {ok, user_stop}),
-    {ok, State#{nkdocker_ids => [{Name, Id} | Ids]}};
-
-given("$Name logs match $Pattern", State = #{nkdocker_pid := Pid, nkdocker_ids := Ids}) ->
-    Id = proplists:get_value(Name, Ids),
-    {async, Ref} = nkdocker:logs(Pid, Id, #{stdout=>true, follow=>true}),
-    {match, _Captured} = nkdocker_receive_match(Ref, Pattern),
-    nkdocker:finish_async(Pid, Ref),
-    nkdocker_receive(Ref, {ok, user_stop}),
+    ok = dockerl:start_container(Pid, Id),
+    lager:notice("Docker container ~s started", [Id]),
+    {ok, State#{containers => [{Name, Id} | Containers]}};
+
+given("$Name logs match $Pattern", State = #{dockerl_pid := Pid, containers := Containers}) ->
+    Id = proplists:get_value(Name, Containers),
+    {ok, Stream} = dockerl:container_logs(Pid, Id),
+    ok = match_logs(Stream, Pattern),
     {ok, State};
 
-given("consul_proxy is connected to $Name on port $Port", State = #{nkdocker_pid := Pid, nkdocker_ids := Ids}) ->
-    Id = proplists:get_value(Name, Ids),
-    {ok, Data} = nkdocker:inspect(Pid, Id),
-    NetworkSettings = maps:get(<<"NetworkSettings">>, Data),
-    IPAddress = maps:get(<<"IPAddress">>, NetworkSettings),
-    URL = binary_to_list(<<"http://", IPAddress/binary, ":", Port/binary>>),
+given("consul_proxy is connected to $Name port $Port", State = #{dockerl_pid := Pid, containers := Containers, applications := Applications}) ->
+    Id = proplists:get_value(Name, Containers),
+    {ok, Ports} = dockerl_utils:get_ports(Pid, Id),
+    [{_, IntPort}] = maps:get(Port, Ports),
+    BinPort = integer_to_binary(IntPort),
+    BinAddress = case os:type() of
+                     {unix, darwin} -> %% Todo: remove this hack once routing is fixed in Docker for Mac
+                         <<"127.0.0.1">>;
+                     _ ->
+                         {ok, Gateway} = dockerl_utils:get_gateway(Pid, Id),
+                         list_to_binary(inet:ntoa(Gateway))
+                 end,
+    URL = binary_to_list(<<"http://", BinAddress/binary, ":", BinPort/binary>>),
+    lager:notice("Consul URL: ~s", [URL]),
     ok = application:set_env(consul_proxy, consul_urls, URL, [{timeout, infinity}, {persistent, true}]),
     case application:ensure_all_started(consul_proxy) of
         {ok, Started} ->
             lager:notice("Started ~p applications: ~p on ~p~n", [erlang:length(Started), Started, node()]),
             {ok, HttpcPid} = inets:start(httpc, [{profile, consul_proxied}]),
             httpc:set_options([{proxy, {{"localhost", 8080}, []}}], consul_proxied),
-            {ok, State#{consul_proxied_httpc => HttpcPid}};
+            {ok, State#{consul_proxied_httpc => HttpcPid, applications => Applications ++ Started}};
         {error, Reason} ->
             lager:error("~p", [Reason]),
             {error, Reason}
     end;
 
-given("a UDP listener registered as $ServiceName", State) ->
-    {ok, Socket} = gen_udp:open(0, [binary, {ip, {127, 0, 0, 1}}, {active, false}]),
-    {ok, Port} = inet:port(Socket),
-    BinPort = integer_to_binary(Port),
-    Value = <<"{\"Name\":\"", ServiceName/binary, "\",\"Address\":\"127.0.0.1\",\"Port\":", BinPort/binary, "}">>,
+given("a UDP listener registered as $ServiceName", State = #{test_env := TestEnv}) ->
+    {ok, Socket} = gen_udp:open(0, [binary, {ip, {0, 0, 0, 0}}, {active, false}]),
+    {ok, IntPort} = inet:port(Socket),
+    BinPort = integer_to_binary(IntPort),
+    BinAddress = proplists:get_value(<<"ip_address">>, TestEnv),
+    Value = <<"{\"Name\":\"", ServiceName/binary, "\",\"Address\":\"", BinAddress/binary, "\",\"Port\":", BinPort/binary, "}">>,
     {ok, <<>>} = consul_client:http_put(<<"/v1/agent/service/register">>, Value),
-    lager:notice("UDP listener ~p started on ~p", [ServiceName, Port]),
+    lager:notice("UDP listener ~p started on ~p", [ServiceName, IntPort]),
     spawn(fun() -> udp_receive(Socket) end),
-    {ok, State#{test_env => [{<<ServiceName/binary, "_port">>, BinPort} | maps:get(test_env, State, [])]}};
+    {ok, State#{test_env => [{<<ServiceName/binary, "_port">>, BinPort} | TestEnv]}};
 
-given("an HTTP Server with root $Root and handlers $Handlers registered as $ServiceName", State) ->
+given("an HTTP Server with root $Root and handlers $Handlers registered as $ServiceName", State = #{test_env := TestEnv}) ->
     Modules = [binary_to_atom(Handler, utf8) || Handler <- binary:split(Handlers, <<",">>, [trim_all, global])],
     ServiceConfig = [
-        {bind_address, "localhost"},
+        {bind_address, "0.0.0.0"},
         {port, 0},
         {modules, [mod_esi, mod_dir, mod_get]},
         {erl_script_alias, {"/erl", Modules}},
@@ -124,7 +122,8 @@ given("an HTTP Server with root $Root and handlers $Handlers registered as $Serv
     {ok, Pid} = inets:start(httpd, ServiceConfig),
     Port = proplists:get_value(port, httpd:info(Pid)),
     BinPort = integer_to_binary(Port),
-    Value = <<"{\"Name\":\"", ServiceName/binary, "\",\"Address\":\"127.0.0.1\",\"Port\":", BinPort/binary, "}">>,
+    BinAddress = proplists:get_value(<<"ip_address">>, TestEnv),
+    Value = <<"{\"Name\":\"", ServiceName/binary, "\",\"Address\":\"", BinAddress/binary, "\",\"Port\":", BinPort/binary, "}">>,
     {ok, <<>>} = consul_client:http_put(<<"/v1/agent/service/register">>, Value),
     lager:notice("HTTP Server ~p started on ~p", [ServiceName, Port]),
     {ok, State#{test_env => [{<<ServiceName/binary, "_port">>, BinPort} | maps:get(test_env, State, [])]}};
@@ -171,91 +170,22 @@ then(Tokens, _State) ->
 %%===================================================================
 %% Internal functions
 %%===================================================================
-get_nkdocker_pid(State) ->
-    case maps:get(nkdocker_pid, State, undefined) of
-        undefined ->
-            {ok, Pid} = nkdocker:start_link(),
-            {ok, Version} = nkdocker:version(Pid),
-            lager:debug("Docker Version:~n~s", [io_lib_pretty:print(Version)]),
-            {Pid, State#{nkdocker_pid => Pid}};
-        Pid ->
-            {Pid, State}
-    end.
-
-nkdocker_receive(Ref, Data) ->
-    receive
-        {nkdocker, Ref, Data} ->
-            lager:debug("~p", [Data]),
-            ok;
-        Other ->
-            lager:debug("~p", [Other]),
-            nkdocker_receive(Ref, Data)
-    after
-        1000 ->
-            {error, timeout}
-    end.
-
-nkdocker_receive_status(Ref, Id, Status) ->
-    receive
-        {nkdocker, Ref, Data = {data, #{<<"id">>:=Id, <<"status">>:=Status}}} ->
-            lager:debug("~p", [Data]),
-            ok;
-        Other ->
-            lager:debug("~p", [Other]),
-            nkdocker_receive_status(Ref, Id, Status)
-    after
-        1000 ->
-            {error, timeout}
-    end.
-
-nkdocker_receive_data(Ref) ->
-    nkdocker_receive_data(Ref, <<>>, 3000).
-
-nkdocker_receive_data(Ref, Buffer, Timeout) ->
-    receive
-        {ok, <<>>} ->
-            {ok, Buffer};
-        {nkdocker, Ref, {data, Data}} when is_binary(Data) ->
-            lager:debug("~p", [Data]),
-            nkdocker_receive_data(Ref, <<Buffer/binary, Data/binary>>, Timeout);
-        {nkdocker, Ref, {data, Data}} ->
-            lager:debug("~p", [Data]),
-            nkdocker_receive_data(Ref, Buffer, Timeout);
-        Other ->
-            lager:debug("~p", [Other]),
-            nkdocker_receive_data(Ref, Buffer, Timeout)
-    after
-        Timeout ->
-            {error, timeout}
-    end.
 
-nkdocker_receive_match(Ref, RE) ->
-    nkdocker_receive_match(Ref, RE, 3000).
-
-nkdocker_receive_match(Ref, Regexp, Timeout) when is_binary(Regexp) ->
-    case re:compile(Regexp) of
-        {ok, MP} ->
-            nkdocker_receive_match(Ref, MP, Timeout);
-        {error, Reason} ->
-            {error, Reason}
-    end;
-nkdocker_receive_match(Ref, RE, Timeout) ->
+match_logs(Stream, Pattern) ->
     receive
-        {ok, <<>>} ->
-            nomatch;
-        {nkdocker, Ref, {data, Data}} when is_binary(Data) ->
-            lager:debug("~p", [Data]),
-            case re:run(Data, RE) of
-                nomatch ->
-                    nkdocker_receive_match(Ref, RE, Timeout);
-                Match ->
-                    Match
-            end;
-        Other ->
-            lager:debug("~p", [Other]),
-            nkdocker_receive_match(Ref, RE, Timeout)
+        done ->
+            {error, no_match};
+        Msg ->
+            case re:run(Msg, Pattern) of
+                {match, _} ->
+                    Stream ! stop,
+                    ok;
+                _ ->
+                    match_logs(Stream, Pattern)
+            end
     after
-        Timeout ->
+        10000 ->
+            Stream ! stop,
             {error, timeout}
     end.
 
@@ -267,3 +197,10 @@ udp_receive(Socket) ->
         {error, _Reason} ->
             udp_receive(Socket)
     end.
+
+local_ip_v4() ->
+    {ok, Addrs} = inet:getifaddrs(),
+    hd([
+        Addr || {_, Opts} <- Addrs, {addr, Addr} <- Opts,
+        size(Addr) == 4, Addr =/= {127, 0, 0, 1}
+    ]).
diff --git a/apps/consul_proxy/test/feature_consul_proxy.erl b/apps/consul_proxy/test/feature_consul_proxy.erl
index 9b8011b03b497b08e3b5f9148113f3511464fc0e..3ba9c3537d638a52749ab721ebaa0405b36515fb 100644
--- a/apps/consul_proxy/test/feature_consul_proxy.erl
+++ b/apps/consul_proxy/test/feature_consul_proxy.erl
@@ -37,12 +37,12 @@ given(Tokens, State) ->
 %% noinspection ErlangUnboundVariable
 'when'("the consul client lists nodes", State) ->
     {ok, Nodes} = consul_client:nodes(),
-    lager:notice("~p", [Nodes]),
+    lager:notice("Nodes: ~p", [Nodes]),
     {ok, State#{result => Nodes}};
 
 'when'("the consul client lists services", State) ->
     {ok, Services} = consul_client:services(),
-    lager:notice("~p", [Services]),
+    lager:notice("Services: ~p", [Services]),
     {ok, State#{result => Services}};
 
 'when'("a request is made to $URL", State) ->
diff --git a/apps/consul_proxy/test/features_test.erl b/apps/consul_proxy/test/features_test.erl
index db2280754b15d6bc7c5ba75da0982e0bf720ac34..4c458351d2af29abf3fb87c29086125deff38f43 100644
--- a/apps/consul_proxy/test/features_test.erl
+++ b/apps/consul_proxy/test/features_test.erl
@@ -11,6 +11,14 @@ features_test_() ->
     gurka_eunit:setup(Features, fun teardown/1).
 
 setup() ->
+    case file:consult("config/test-sys.config") of
+        {ok, [ConfigList]} ->
+            [application:set_env(Application, Key, Val, [{timeout, infinity}, {persistent, true}]) ||
+                {Application, Items} <- ConfigList,
+                {Key, Val} <- Items];
+        {error, Reason} ->
+            ?debugFmt("~p: ~p", ["config/test-sys.config", Reason])
+    end,
     lager:start().
 
 teardown(_) ->
diff --git a/config/test-sys.config b/config/test-sys.config
index 6628c229a499d00750b4cf0f3a6b3ea58989f8b4..6a4769863b6b063db5a30bbd7741018cc41ce895 100644
--- a/config/test-sys.config
+++ b/config/test-sys.config
@@ -30,7 +30,7 @@
         {crash_log_size, 10485760},
         {crash_log_date, "$D0"},
         {crash_log_count, 5},
-        {error_logger_redirect, false}
+        {error_logger_redirect, true}
     ]},
     {vegur, [
         {downstream_connect_timeout, 1000},
diff --git a/config/test-vm.args b/config/test-vm.args
deleted file mode 100644
index 1afe19d9c76a43e1a0ff07d4f3d3fdd86e9715a2..0000000000000000000000000000000000000000
--- a/config/test-vm.args
+++ /dev/null
@@ -1,16 +0,0 @@
-## Name of the node
--sname consul_proxy
-
-## Enable kernel poll and a few async threads
-+K true
-+A 64
-+P 262144
-
-## enable smp support
--smp auto
-
-## Increase number of concurrent ports/sockets
--env ERL_MAX_PORTS 16384
-
-## Tweak GC to run more often
--env ERL_FULLSWEEP_AFTER 10
diff --git a/features/consul_proxy.feature b/features/consul_proxy.feature
index e5f5ddc555ae24b62861911d5630a9c42f496f76..d01d77c16baaf55624b86c0ffe5eafb26ee58c8f 100644
--- a/features/consul_proxy.feature
+++ b/features/consul_proxy.feature
@@ -9,25 +9,25 @@ Feature: Proxy functionality
     agent -dev -ui-dir /ui -client 0.0.0.0
     """
     And consul logs match "Synced service 'consul'"
-    And consul_proxy is connected to consul on port 8500
+    And consul_proxy is connected to consul port 8500/tcp
     And a UDP listener registered as logstash
     And an HTTP Server with root "test/www" and handlers "eunit_www" registered as eunit
     And consul client has set consul_proxy/watchers/kv to:
     """
     [
-        "http://localhost:$<eunit_port>/erl/eunit_www:info"
+        "http://$<ip_address>:$<eunit_port>/erl/eunit_www:info"
     ]
     """
     And consul client has set consul_proxy/watchers/services to:
     """
     [
-        "http://localhost:$<eunit_port>/erl/eunit_www:info"
+        "http://$<ip_address>:$<eunit_port>/erl/eunit_www:info"
     ]
     """
     And consul client has set consul_proxy/watchers/nodes to:
     """
     [
-        "http://localhost:$<eunit_port>/erl/eunit_www:info"
+        "http://$<ip_address>:$<eunit_port>/erl/eunit_www:info"
     ]
     """
     And consul client has set consul_proxy/domains/eunit to:
diff --git a/rebar.config b/rebar.config
index db2b06599bf7d514c8e32f0d0d7991f2e3e010e9..240dba8936353ed57758ff08af48d2af0fe3b472 100644
--- a/rebar.config
+++ b/rebar.config
@@ -1,5 +1,10 @@
 {global_rebar_dir, ".rebar3"}.
 
+{plugins, [
+    {rebar_alias, "0.2.0"},
+    {rebar_cmd, "0.2.5"}
+]}.
+
 {erl_opts, [{parse_transform, lager_transform}, {lager_extra_sinks, [request_log, latency_log]}]}.
 
 {eunit_opts, [{report, {eunit_surefire, [{dir, "_build/test"}]}}]}.
@@ -7,18 +12,18 @@
 {edoc_opts, [{dir, "_build/edoc"}]}.
 
 {deps, [
-    {lager, {git, "https://github.com/basho/lager.git", {tag, "3.1.0"}}},
-    {tsuru, "1.4.0"},
+    {lager, "3.2.1"},
+    {tsuru, "1.4.1"},
     {msgpack, "0.4.0"},
     {jsx, "2.8.0"},
     {lru, "1.3.1"},
     {pbkdf2, "2.0.0"},
     {luerl, {git, "https://github.com/rvirding/luerl.git", {tag, "v0.3"}}},
-    {vegur, {git, "https://github.com/heroku/vegur.git", {tag, "v1.1.1"}}}
+    {vegur, {git, "https://github.com/heroku/vegur.git", {tag, "2.0.3"}}}
 ]}.
 
 {relx, [
-    {release, {consul_proxy, "0.5.3"}, [consul_proxy]},
+    {release, {consul_proxy, "0.5.4"}, [consul_proxy]},
     {sys_config, "./config/sys.config"},
     {vm_args, "./config/vm.args"},
     {dev_mode, true},
@@ -26,7 +31,8 @@
     {system_libs, false},
     {extended_start_script, true},
     {overlay, [
-        {copy, "apps/consul_proxy/priv/consul_proxy-wrapper", "bin/consul_proxy-wrapper"}
+        {template, "apps/consul_proxy/priv/wrapper", "bin/wrapper"},
+        {template, "apps/consul_proxy/priv/Dockerfile", "Dockerfile"}
     ]}
 ]}.
 
@@ -34,20 +40,56 @@
     {test, [
         {deps, [
             {gurka, "0.1.7"},
-            {gun, "1.0.0-pre.1"},
-            {cowlib, {git, "https://github.com/ninenines/cowlib.git", {tag, "1.3.0"}}},
-            {cowboy, ".*", {git, "https://github.com/extend/cowboy", {ref, "90ae31998e8d0887b9efe4b441136ac047708bb9"}}},
-            {nkpacket, {git, "https://github.com/NetComposer/nkpacket.git", {ref, "b2869f68060f779da56f63d0ff5e8c58a011d32c"}}},
-            {nkdocker, {git, "https://github.com/NetComposer/nkdocker.git", {ref, "f0fc3f866ecf9ded00c3eaaef2402afefc56f77f"}}}
+            {dockerl, {git, "https://gitlab.hedenstroem.com/erlang-ninja/dockerl.git", {tag, "0.1.0"}}}
         ]},
         {eunit_opts, [{report, {eunit_surefire, [{dir, "_build/test"}]}}]},
         {erl_opts, [debug_info, nowarn_unused_vars]}
     ]},
-    {production, [
+    {prod, [
+        {erl_opts, [no_debug_info, warnings_as_errors]},
         {relx, [
-            {dev_mode, false},
-            {include_erts, false}
+            {dev_mode, false}
         ]},
-        {erl_opts, [no_debug_info, warnings_as_errors]}
+        {commands, [
+            {docker, "docker build -t registry.hedenstroem.com/erlang-ninja/consul_proxy _build/prod/rel/consul_proxy"}
+        ]}
     ]}
 ]}.
+
+{dist_node, [
+    {setcookie, 'cookie'},
+    {sname, 'consul_proxy@localhost'}
+]}.
+
+{shell, [
+    {config, "config/test-sys.config"}
+]}.
+
+{dialyzer, [
+    {base_plt_location, global}
+]}.
+
+{alias, [
+    {test, [
+        {eunit, "--cover --application=consul_proxy --dir=apps/consul_proxy/test"},
+        {cover, "--verbose"}
+    ]},
+    {analyze, [
+        dialyzer,
+        xref
+    ]},
+    {cleanup, [
+        clean,
+        {cmd, "distclean"}
+    ]},
+    {docker, [
+        tar,
+        {cmd, "docker"}
+    ]}
+]}.
+
+{commands, [
+    {distclean, "rm -rf .rebar3 _build _checkouts/*/ebin ebin log"},
+    {sync, "git fetch upstream && git merge upstream/master"},
+    {docker, "docker build -t registry.hedenstroem.com/erlang-ninja/consul_proxy _build/default/rel/consul_proxy"}
+]}.
diff --git a/rebar.lock b/rebar.lock
index 5ab9781755b16f98011b5fe0d9dd1e1cdaf4e1a0..7a41e87cd8593e92c40d8bd1aa79b3bedf37c7db 100644
--- a/rebar.lock
+++ b/rebar.lock
@@ -1,6 +1,6 @@
 [{<<"cowboyku">>,
   {git,"https://github.com/heroku/cowboyku.git",
-       {ref,"ca64d29abe15c1522ba77283f15de20677aa5889"}},
+       {ref,"4acffec2be36d2ac66b79d4e9782de1213d1de4a"}},
   1},
  {<<"cowlib">>,
   {git,"https://github.com/ninenines/cowlib.git",
@@ -8,17 +8,11 @@
   1},
  {<<"erequest_id">>,
   {git,"https://github.com/heroku/erequest_id.git",
-       {ref,"e24f250c119e14975eff038ac30b2f9f7d1ceefa"}},
-  1},
- {<<"goldrush">>,
-  {git,"git://github.com/DeadZen/goldrush.git",
-       {ref,"212299233c7e7eb63a97be2777e1c05ebaa58dbe"}},
+       {ref,"6fae0c878f2dde809482915c8b207dc80882f7b3"}},
   1},
+ {<<"goldrush">>,{pkg,<<"goldrush">>,<<"0.1.8">>},1},
  {<<"jsx">>,{pkg,<<"jsx">>,<<"2.8.0">>},0},
- {<<"lager">>,
-  {git,"https://github.com/basho/lager.git",
-       {ref,"b2cb2735713e3021e0761623ff595d53a545438e"}},
-  0},
+ {<<"lager">>,{pkg,<<"lager">>,<<"3.2.1">>},0},
  {<<"lru">>,{pkg,<<"lru">>,<<"1.3.1">>},0},
  {<<"luerl">>,
   {git,"https://github.com/rvirding/luerl.git",
@@ -32,7 +26,7 @@
  {<<"pbkdf2">>,{pkg,<<"pbkdf2">>,<<"2.0.0">>},0},
  {<<"quickrand">>,
   {git,"https://github.com/okeuday/quickrand.git",
-       {ref,"cf7ac11a820367496252243e49898480b25009f7"}},
+       {ref,"ad46bb697b98e8dcbf5c4a0af0099a5f1b2a0aa2"}},
   2},
  {<<"ranch">>,
   {git,"https://github.com/ninenines/ranch.git",
@@ -40,14 +34,14 @@
   1},
  {<<"ranch_proxy_protocol">>,
   {git,"https://github.com/heroku/ranch_proxy_protocol.git",
-       {ref,"5110e6ca4bc25dfb11d4ecf8d003169b95bf8969"}},
+       {ref,"0129227305a5b41f0875b337ac75f02f613f81c1"}},
   1},
- {<<"tsuru">>,{pkg,<<"tsuru">>,<<"1.4.0">>},0},
+ {<<"tsuru">>,{pkg,<<"tsuru">>,<<"1.4.1">>},0},
  {<<"uuid">>,
   {git,"https://github.com/okeuday/uuid.git",
-       {ref,"24325ae6309d03897735c3a320aab6f74b189ab7"}},
+       {ref,"4b705b22f5d095970558d904e43c4354bd0e0a7f"}},
   1},
  {<<"vegur">>,
   {git,"https://github.com/heroku/vegur.git",
-       {ref,"612d2de22bc6931dcc2bb0ae9c3e3187c4d77ca1"}},
+       {ref,"038542b071c8d1591f3f7843759271be3ed4a99b"}},
   0}].
diff --git a/scripts/genpasswd.escript b/scripts/genpasswd.escript
index 76f9f31729d78051f0aad4a064891f56cfd1cfa7..53e853889047717c7a6ac78c89db070ef7362b20 100755
--- a/scripts/genpasswd.escript
+++ b/scripts/genpasswd.escript
@@ -5,6 +5,8 @@
 -define(PBKDF2_ITERATIONS, 4096).
 -define(PBKDF2_DERIVED_LENGTH, 32).
 
+-export([main/1]).
+
 main([Username, Password]) ->
     try
         Hash = base64:encode(hash(Password)),
diff --git a/test/boot2docker-route.sh b/test/boot2docker-route.sh
deleted file mode 100755
index f4ffdbc39f4f025fcdd153c9c2fe2408b2780a9a..0000000000000000000000000000000000000000
--- a/test/boot2docker-route.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env bash
-
-if [[ 'Running' != $(docker-machine status) ]]; then
-    echo "boot2docker's VM not running"
-    exit 1
-fi
-
-IP=$(docker-machine ip default 2> /dev/null)
-for NET in $(docker-machine ssh default route | awk '/docker0|br-/{print $1}'); do
-    case $1 in
-        "add" )
-            sudo route -n add "$NET" "$IP";;
-        "delete" )
-            sudo route -n delete "$NET" "$IP";;
-    esac
-done
-
-HOST_IP=$(docker-machine ssh default route | awk '/UG/{print $2}')
-
-echo "IP to host inside container: $HOST_IP"
-netstat -rn | awk "\$2 == \"$IP\"||/Destination.*Refs/{print;}"
diff --git a/test/consul/consul.json b/test/consul/consul.json
new file mode 100644
index 0000000000000000000000000000000000000000..e2a462f90ae968e5db5c2e9258f9a1aa1ee2a545
--- /dev/null
+++ b/test/consul/consul.json
@@ -0,0 +1,10 @@
+{
+  "data_dir": "/data",
+  "ui_dir": "/ui",
+  "client_addr": "0.0.0.0",
+  "recursors": ["8.8.8.8", "8.8.4.4"],
+  "disable_update_check": true,
+  "server" : true,
+  "rejoin_after_leave" :  true,
+  "bootstrap_expect" : 1
+}
diff --git a/test/defaults.consul b/test/defaults.consul
index e1eb12a355d30ed616b664223444453f65d38c43..a6d317f8a8806afa46420de2f3dab9ab75b77e26 100644
--- a/test/defaults.consul
+++ b/test/defaults.consul
@@ -2,9 +2,9 @@ consul_proxy/domains/test.service.docker:ewogICJTZXJ2aWNlTmFtZSIgOiAidGVzdCIKfQ=
 consul_proxy/domains/consul.service.docker:ewogICJTZXJ2aWNlTmFtZSIgOiAiY29uc3VsIgp9
 consul_proxy/domains/rewrite-example:ewogICJTZXJ2aWNlTmFtZSIgOiAiJDxzZXJ2aWNlPiIsCiAgIkFsaWFzZXMiIDogWwogICAgIig/PHNlcnZpY2U+LiopLXJld3JpdGVbLl1zZXJ2aWNlWy5dZG9ja2VyIgogIF0sCiAgIlJld3JpdGUiIDogWwogICAgWyJeL2FwaS8oLiopJCIsIi9pbmZvLnBocD9hcGk9JDEiXQogIF0KfQ==
 consul_proxy/scripts/resolver-example.erl:UmVxdWVzdCA9IHByb3BsaXN0czpnZXRfdmFsdWUocmVxdWVzdCwgUHJvcHMsIFtdKSwKTWV0YSA9IHByb3BsaXN0czpnZXRfdmFsdWUobWV0YSwgUmVxdWVzdCwgW10pLApDYXB0dXJlID0gcHJvcGxpc3RzOmdldF92YWx1ZShob3N0X2NhcHR1cmUsIE1ldGEsIFtdKSwKcHJvcGxpc3RzOmdldF92YWx1ZSg8PCJzZXJ2aWNlIj4+LCBDYXB0dXJlKS4=
-consul_proxy/watchers/nodes:WwogICAgImh0dHBzOi8vdGVzdC5zZXJ2aWNlLmRvY2tlci9pbmZvLnBocCIKXQ==
-consul_proxy/watchers/services:WwogICAgImh0dHBzOi8vdGVzdC5zZXJ2aWNlLmRvY2tlci9pbmZvLnBocCIKXQ==
-consul_proxy/watchers/kv:WwogICAgImh0dHBzOi8vdGVzdC5zZXJ2aWNlLmRvY2tlci9pbmZvLnBocCIKXQ==
+consul_proxy/watchers/nodes:WwogICAgImh0dHA6Ly9sb2dzdGFzaDo4MDgwL3dhdGNoL25vZGVzIgpd
+consul_proxy/watchers/services:WwogICAgImh0dHA6Ly9sb2dzdGFzaDo4MDgwL3dhdGNoL3NlcnZpY2VzIgpd
+consul_proxy/watchers/kv:WwogICAgImh0dHA6Ly9sb2dzdGFzaDo4MDgwL3dhdGNoL2t2Igpd
 consul_proxy/hijackers:WwogIHsKICAgICJ1c2VybmFtZSIgOiAiaGlqYWNrZXIiLAogICAgInBhc3N3b3JkIiA6ICIwdEhWdFNhOThrSGkyZStkVHVWdHo3S3lYWTgzVys3cGZ6eEZYd2VKWUtualcxOXRSeHBVbFFSV1lYbGI4V21YIiwKICAgICJkb21haW5zIiA6IFsKICAgICAgIi4qIgogICAgXQogIH0KXQ==
 consul_proxy/domains/resolver-example-erl:ewogICJTZXJ2aWNlUmVzb2x2ZXIiIDogInJlc29sdmVyLWV4YW1wbGUuZXJsIiwKICAiQWxpYXNlcyIgOiBbCiAgICAiKD88c2VydmljZT4uKiktcmVzb2x2ZXItZXJsWy5dc2VydmljZVsuXWRvY2tlciIKICBdCn0=
 consul_proxy/domains/resolver-example-lua:ewogICJTZXJ2aWNlUmVzb2x2ZXIiIDogInJlc29sdmVyLWV4YW1wbGUubHVhIiwKICAiQWxpYXNlcyIgOiBbCiAgICAiKD88c2VydmljZT4uKiktcmVzb2x2ZXItbHVhWy5dc2VydmljZVsuXWRvY2tlciIKICBdCn0=
diff --git a/test/docker-compose.yml b/test/docker-compose.yml
index 34d7a45776cbb26481b4eec1ea6210c4ef184385..c3278db6dd9a3bd7ed3b0d49a2c712988ab67c8e 100644
--- a/test/docker-compose.yml
+++ b/test/docker-compose.yml
@@ -3,8 +3,8 @@ version: '2'
 services:
 
   consul:
-    image: ehedenst/consul:x86
-    command: agent -dev -ui-dir /ui -client 0.0.0.0
+    image: hedenstroem/consul
+    command: agent -config-dir /config
     environment:
       - SERVICE_8300_IGNORE=true
       - SERVICE_8301_IGNORE=true
@@ -15,9 +15,32 @@ services:
     ports:
       - "8500:8500"
       - "8600:8600/udp"
+      - "8600:8600/tcp"
+    volumes:
+      - ./consul:/config
+
+  consul_proxy:
+    image: registry.hedenstroem.com/erlang-ninja/consul_proxy
+    links:
+      - consul
+      - logstash
+    environment:
+      - CONSUL_PROXY_LOGLEVEL=debug
+      - CONSUL_PROXY_HTTP_PORT=80
+      - CONSUL_PROXY_CONSUL_URLS=http://consul:8500
+      - CONSUL_PROXY_LOGSERVICE=logstash-udp
+      - CONSUL_PROXY_HIJACK_CERT=/var/lib/hitch/certs/service.docker.pem
+      - SERVICE_IGNORE=true
+    ports:
+      - "80:80"
+      - "8081:8081"
+      - "8082:8082"
+      - "8083:8083"
+    volumes:
+      - ./hitch:/var/lib/hitch
 
   registrator:
-    image: ehedenst/registrator:x86
+    image: hedenstroem/registrator
     command: -internal -ttl 600 -ttl-refresh 300 -resync 600 -cleanup consul://consul:8500/dc1
     links:
       - consul
@@ -28,9 +51,12 @@ services:
       - /var/run/docker.sock:/tmp/docker.sock
 
   hitch:
-    image: ehedenst/hitch:x86
+    image: hedenstroem/hitch
+    links:
+      - consul_proxy
     environment:
       - SERVICE_402_NAME=acme-challenge
+      - SERVICE_403_IGNORE=true
       - SERVICE_443_NAME=hitch
       - MODE=staging
     ports:
@@ -39,15 +65,38 @@ services:
       - ./hitch:/var/lib/hitch
       - ./acme:/var/lib/acme
 
+  elasticsearch:
+    image: elasticsearch:2
+    command: elasticsearch -Des.network.host=0.0.0.0
+    environment:
+      - SERVICE_9200_NAME=elasticsearch
+      - SERVICE_9300_IGNORE=true
+
   logstash:
-    image: ehedenst/logstash:x86
+    image: logstash:2
+    command: -f /opt/logstash/config/logstash.conf
+    environment:
+      - SERVICE_5000_NAME=logstash-udp
+      - SERVICE_8080_NAME=logstash-http
+    links:
+      - elasticsearch
     ports:
       - "5000/udp"
+      - "8080"
     volumes:
       - ./logstash:/opt/logstash/config
 
+  kibana:
+    image: hedenstroem/kibana
+    environment:
+      - ELASTICSEARCH_URL=http://elasticsearch:9200
+    ports:
+      - "5601:5601"
+    links:
+      - elasticsearch
+
   test-slow:
-    image: ehedenst/php5:x86
+    image: hedenstroem/php5
     environment:
       - SERVICE_NAME=test
       - SERVICE_TAGS=php5,slow
@@ -57,7 +106,7 @@ services:
       - ./www:/var/www
 
   test-medium:
-    image: ehedenst/php5:x86
+    image: hedenstroem/php5
     environment:
       - SERVICE_NAME=test
       - SERVICE_TAGS=php5,medium
@@ -67,7 +116,7 @@ services:
       - ./www:/var/www
 
   test-fast:
-    image: ehedenst/php5:x86
+    image: hedenstroem/php5
     environment:
       - SERVICE_NAME=test
       - SERVICE_TAGS=php5,fast
diff --git a/test/hitch/conf/hitch.conf b/test/hitch/conf/hitch.conf
index 42c7914a6d62a1114cbfe08abecbbf2de6b42e5d..b1eae575feab771e7a059fbcd7e55ac182f3227c 100644
--- a/test/hitch/conf/hitch.conf
+++ b/test/hitch/conf/hitch.conf
@@ -14,7 +14,7 @@ frontend = "[*]:443"
 #
 # type: string
 # syntax: [HOST]:PORT.
-backend = "[10.0.2.2]:8081"
+backend = "[consul_proxy]:8081"
 
 # SSL x509 certificate file. REQUIRED.
 # List multiple certs to use SNI. Certs are used in the order they
diff --git a/test/logstash/logstash.conf b/test/logstash/logstash.conf
index 31616602a5befb9099f2ef7a21ae2a2f7deb2020..8e5c8957dc043160696bb0b3c62e7442c2e18213 100644
--- a/test/logstash/logstash.conf
+++ b/test/logstash/logstash.conf
@@ -4,7 +4,13 @@ input {
     codec => msgpack
     type => "consul_proxy"
   }
+  http {
+    port => 8080
+  }
 }
 output {
   stdout { codec => rubydebug }
+  elasticsearch {
+      hosts => "elasticsearch:9200"
+  }
 }