diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 28975f9f28981ce60f9b4795df1c858bb4592f66..806f2c18bfab1af500e2fedbe98ba8ecc40ba0ab 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -22,6 +22,8 @@ before_script:
   - gem install bundler  --no-ri --no-rdoc
   - bundle install -j $(nproc) --path vendor
   - bundle exec ruby /builds/leap/nickserver/bin/nickserver version
+  - apt update -y
+  - apt install -y lsof
 
 test:
   script:
diff --git a/lib/nickserver/dispatcher.rb b/lib/nickserver/dispatcher.rb
index 71e71cf7c38afca87f1efd043476d9638cebafb6..dfd53e5177777b7e479230ab6e56f58e3d650720 100644
--- a/lib/nickserver/dispatcher.rb
+++ b/lib/nickserver/dispatcher.rb
@@ -24,21 +24,23 @@ require 'nickserver/request_handlers/fingerprint_handler'
 module Nickserver
   class Dispatcher
 
-
-    def initialize(responder)
+    def initialize(responder, adapter = nil)
       @responder = responder
+      @adapter = adapter
     end
 
     def respond_to(params, headers)
       request = Nickserver::Request.new params, headers
       response = handle request
-      send_response response
+      responder.respond response.status, response.content
     end
 
     protected
 
+    attr_reader :responder, :adapter
+
     def handle(request)
-      handler_chain.handle request
+      handler_chain.handle request, adapter
     end
 
     def handler_chain
@@ -51,7 +53,7 @@ module Nickserver
         RequestHandlers::LeapEmailHandler,
         RequestHandlers::HkpEmailHandler,
         RequestHandlers::FingerprintHandler,
-        Proc.new {|_req| proxy_error_response },
+        Proc.new { proxy_error_response },
         Proc.new { Nickserver::Response.new(404, "404 Not Found\n") }
       chain.continue_on HTTP::ConnectionError
       return chain
@@ -65,11 +67,5 @@ module Nickserver
       end
     end
 
-    def send_response(response)
-      responder.respond response.status, response.content
-    end
-
-    attr_reader :responder
-
   end
 end
diff --git a/lib/nickserver/reel_server.rb b/lib/nickserver/reel_server.rb
index c378acaba9727fd5aa8e110697e63576409bb7b1..96264669001a15b49bf13d2fc25f718deba1eec3 100644
--- a/lib/nickserver/reel_server.rb
+++ b/lib/nickserver/reel_server.rb
@@ -10,6 +10,8 @@ require 'nickserver/logging_responder'
 module Nickserver
   class ReelServer < Reel::Server::HTTP
 
+    DEFAULT_ADAPTER_CLASS = Nickserver::Adapters::CelluloidHttp
+
     def self.start(options = {})
       new(options[:host], options[:port])
     end
@@ -35,20 +37,37 @@ module Nickserver
     protected
 
     def handle_request(request)
+      logging_request(request) do
+        with_http_adapter do |adapter|
+          handler = handler_for(request, adapter)
+          handler.respond_to params(request), request.headers
+        end
+      end
+    rescue StandardError => e
+      request.respond 500, "{}"
+    end
+
+    def logging_request(request)
       logger.info "#{request.method} #{request.uri}"
       logger.debug "  #{params(request)}"
-      handler = handler_for(request)
-      handler.respond_to params(request), request.headers
+      yield
     rescue StandardError => e
       logger.error e
       logger.error e.backtrace.join "\n  "
-      request.respond 500, "{}"
+      raise
+    end
+
+    def with_http_adapter
+      adapter = DEFAULT_ADAPTER_CLASS.new
+      yield adapter
+    ensure
+      adapter.terminate if adapter.respond_to? :terminate
     end
 
-    def handler_for(request)
+    def handler_for(request, adapter)
       # with reel the request is the responder
       responder = LoggingResponder.new(request, logger)
-      Dispatcher.new(responder)
+      Dispatcher.new(responder, adapter)
     end
 
     def params(request)
diff --git a/lib/nickserver/request_handlers/base.rb b/lib/nickserver/request_handlers/base.rb
index e5d899234941cb0cc35a73e5076bebddd2268bb2..495a6da27162089f240c8185233eebd7485896a5 100644
--- a/lib/nickserver/request_handlers/base.rb
+++ b/lib/nickserver/request_handlers/base.rb
@@ -2,16 +2,17 @@ module Nickserver
   module RequestHandlers
     class Base
 
-      def self.call(request)
-        new(request).handle
+      def self.call(request, adapter = nil)
+        new(request, adapter).handle
       end
 
-      def initialize(request)
+      def initialize(request, adapter)
         @request = request
+        @adapter = adapter
       end
 
       protected
-      attr_reader :request
+      attr_reader :request, :adapter
     end
   end
 end
diff --git a/lib/nickserver/request_handlers/fingerprint_handler.rb b/lib/nickserver/request_handlers/fingerprint_handler.rb
index 5b2dc7d73c150d5c9a1d74a43c5dcc7122465365..ac3c3c83cfa04bda9f3498cbdbb49bd0f3309bf1 100644
--- a/lib/nickserver/request_handlers/fingerprint_handler.rb
+++ b/lib/nickserver/request_handlers/fingerprint_handler.rb
@@ -22,7 +22,7 @@ module Nickserver
       end
 
       def source
-        Nickserver::Hkp::Source.new
+        Nickserver::Hkp::Source.new adapter
       end
 
     end
diff --git a/lib/nickserver/request_handlers/hkp_email_handler.rb b/lib/nickserver/request_handlers/hkp_email_handler.rb
index 2f7377327d93db1bbfc9a0eefd4f598031f58f9b..393ef87600089dede98c35f5fe4a2999d621299d 100644
--- a/lib/nickserver/request_handlers/hkp_email_handler.rb
+++ b/lib/nickserver/request_handlers/hkp_email_handler.rb
@@ -16,7 +16,7 @@ module Nickserver
       end
 
       def source
-        Nickserver::Hkp::Source.new
+        Nickserver::Hkp::Source.new adapter
       end
 
     end
diff --git a/lib/nickserver/request_handlers/leap_email_handler.rb b/lib/nickserver/request_handlers/leap_email_handler.rb
index bdebc23b1e5aaca00e5670676ee59e34cff1f0a8..bc3ddef3907a9dc0bed8e289f1f7d53222ff85ae 100644
--- a/lib/nickserver/request_handlers/leap_email_handler.rb
+++ b/lib/nickserver/request_handlers/leap_email_handler.rb
@@ -13,7 +13,7 @@ module Nickserver
       protected
 
       def source
-        @source ||= Nicknym::Source.new
+        @source ||= Nicknym::Source.new adapter
       end
 
       def remote_email?
diff --git a/lib/nickserver/request_handlers/local_email_handler.rb b/lib/nickserver/request_handlers/local_email_handler.rb
index 9165ef23c5421ef89cb3bf758f850fc48f3001f0..08147a04c282f2800613900e57b4cebc5ec84b92 100644
--- a/lib/nickserver/request_handlers/local_email_handler.rb
+++ b/lib/nickserver/request_handlers/local_email_handler.rb
@@ -21,7 +21,7 @@ module Nickserver
       end
 
       def source
-        Nickserver::CouchDB::Source.new
+        Nickserver::CouchDB::Source.new adapter
       end
 
     end
diff --git a/lib/nickserver/source.rb b/lib/nickserver/source.rb
index dc0669a202e96e727076471878135eeb74c88eb5..934407addd81cc6efd4a928de016fa2cd9bdc57c 100644
--- a/lib/nickserver/source.rb
+++ b/lib/nickserver/source.rb
@@ -1,11 +1,7 @@
-require 'nickserver/adapters/celluloid_http'
-
 module Nickserver
   class Source
 
-    DEFAULT_ADAPTER_CLASS = Nickserver::Adapters::CelluloidHttp
-
-    def initialize(adapter = DEFAULT_ADAPTER_CLASS.new)
+    def initialize(adapter = nil)
       @adapter = adapter
     end
 
diff --git a/test/functional/sample_test.rb b/test/functional/sample_test.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5886349c938d975a4c5f07d60932ce5a550b717f
--- /dev/null
+++ b/test/functional/sample_test.rb
@@ -0,0 +1,58 @@
+require 'support/functional_test'
+
+class SampleTest < FunctionalTest
+  # don't parallize me... Hard to get that right with nickserver start & stop
+
+  def run(*args)
+    nickserver :start
+    super
+  ensure
+    nickserver :stop
+  end
+
+  def test_running
+    assert_running
+  end
+
+  # def test_invalid
+  #   assert_lookup_status 400, 'invalid'
+  # end
+
+  def test_nicknym
+    assert_lookup_status 200, 'test@mail.bitmask.net'
+  end
+
+  # Regression Tests
+
+  def test_no_file_descriptors_leak
+    lookup 'test@mail.bitmask.net'
+    before = open_files_count
+    lookup 'test@mail.bitmask.net'
+    assert_equal before, open_files_count, 'Filedescriptors leaked'
+  end
+
+  protected
+
+  def assert_lookup_status(status, address)
+    assert_equal status, lookup(address).to_i
+  end
+
+  def lookup(address)
+    run_command %Q(curl localhost:6425 #{curl_opts} -d "address=#{address}")
+  end
+
+  def curl_opts
+    '--silent -w "%{http_code}" -o /dev/null'
+  end
+
+  def open_files_count
+    `lsof | grep " #{nickserver_pid} " | wc -l`.to_i
+  end
+
+  def run_command(command)
+    `#{command} 2>&1`.tap do |out|
+      assert ($?.exitstatus == 0),
+        "failed to run '#{command}':\n #{out}"
+    end
+  end
+end
diff --git a/test/remote/hkp_source_test.rb b/test/remote/hkp_source_test.rb
index 103b8ade8921116badd3d1c1ee632c6c988e5de9..ff615136e74af5820ff1efdd9a87891afa9613f2 100644
--- a/test/remote/hkp_source_test.rb
+++ b/test/remote/hkp_source_test.rb
@@ -1,8 +1,10 @@
 require 'test_helper'
 require 'support/celluloid_test'
+require 'support/http_adapter_helper'
 require 'nickserver/hkp/source'
 
 class RemoteHkpSourceTest < CelluloidTest
+  include HttpAdapterHelper
 
   def test_key_info
     uid = 'elijah@riseup.net'
@@ -31,12 +33,17 @@ class RemoteHkpSourceTest < CelluloidTest
 
   protected
 
-  def assert_key_info_for_uid(uid, &block)
-    Nickserver::Hkp::Source.new.search uid do |status, keys|
+  def assert_key_info_for_uid(uid)
+    source.search uid do |status, keys|
       assert_equal 200, status
       yield keys
     end
   rescue HTTP::ConnectionError => e
     skip "could not talk to hkp server: #{e}"
   end
+
+  def source
+    Nickserver::Hkp::Source.new adapter
+  end
+
 end
diff --git a/test/remote/nicknym_source_test.rb b/test/remote/nicknym_source_test.rb
index 7840e10eee2cf89f9a5bab73f97882aae3c297b4..4ca303321418d8e71cda4076d015197d7c538ddd 100644
--- a/test/remote/nicknym_source_test.rb
+++ b/test/remote/nicknym_source_test.rb
@@ -1,5 +1,6 @@
 require 'test_helper'
 require 'support/celluloid_test'
+require 'support/http_adapter_helper'
 require 'nickserver/nicknym/source'
 require 'nickserver/email_address'
 
@@ -7,6 +8,7 @@ require 'nickserver/email_address'
 # Please note the Readme.md file in this directory
 #
 class RemoteNicknymSourceTest < CelluloidTest
+  include HttpAdapterHelper
 
   def test_availablility_check
     source.available_for? 'mail.bitmask.net'
@@ -42,7 +44,7 @@ class RemoteNicknymSourceTest < CelluloidTest
   end
 
   def source
-    @source ||= Nickserver::Nicknym::Source.new
+    @source ||= Nickserver::Nicknym::Source.new adapter
   end
 
   def email_with_key
diff --git a/test/support/functional_test.rb b/test/support/functional_test.rb
new file mode 100644
index 0000000000000000000000000000000000000000..4ebc40af11e633b1378b303f201cbead174cbf22
--- /dev/null
+++ b/test/support/functional_test.rb
@@ -0,0 +1,41 @@
+require 'minitest/autorun'
+require 'minitest/pride'
+
+class FunctionalTest < Minitest::Test
+
+  protected
+
+  def nickserver_pid
+    status = nickserver "status"
+    /process id (\d*)\./.match(status)[1]
+  end
+
+  def assert_running
+    status = nickserver "status"
+    assert_includes status, "Nickserver running"
+  end
+
+  def assert_stopped
+    status = nickserver "status"
+    assert_includes status, "No nickserver processes are running."
+  end
+
+  def assert_command_runs(command)
+    out = nickserver command
+    assert ($?.exitstatus == 0),
+      "failed to run 'nickserver #{command}':\n #{out}"
+  end
+
+  def nickserver(command)
+    self.class.nickserver command
+  end
+
+  def self.nickserver(command)
+    `#{path_to_executable} #{command} 2>&1`
+  end
+
+  def self.path_to_executable
+    File.expand_path(File.dirname(__FILE__) + '/../../bin/nickserver')
+  end
+
+end
diff --git a/test/support/http_adapter_helper.rb b/test/support/http_adapter_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6817e1e5a418d07698d9231df071999bcc22026b
--- /dev/null
+++ b/test/support/http_adapter_helper.rb
@@ -0,0 +1,19 @@
+require 'nickserver/adapters/celluloid_http'
+
+module HttpAdapterHelper
+
+  def setup
+    super
+    @adapter = Nickserver::Adapters::CelluloidHttp.new
+  end
+
+  def teardown
+    @adapter.terminate
+    super
+  end
+
+  protected
+
+  attr_reader :adapter
+
+end
diff --git a/test/support/http_stub_helper.rb b/test/support/http_stub_helper.rb
index dd3d1b22eb60edf46bb4668ab3b664764f53908d..c9f2bfa9f05dc66aac82e8ec9f90badc3138572d 100644
--- a/test/support/http_stub_helper.rb
+++ b/test/support/http_stub_helper.rb
@@ -1,9 +1,9 @@
-require 'nickserver/source'
+require 'nickserver/reel_server'
 
 module HttpStubHelper
 
   def stubbing_http
-    Nickserver::Source::DEFAULT_ADAPTER_CLASS.stub :new, adapter do
+    Nickserver::ReelServer::DEFAULT_ADAPTER_CLASS.stub :new, adapter do
       yield
     end
     adapter.verify