diff --git a/exporter.go b/exporter.go
index 6bc0126..e3947c9 100644
--- a/exporter.go
+++ b/exporter.go
@@ -3,23 +3,17 @@ package main
 import (
 	"fmt"
 	"log"
-	"net/http"
 	"os"
 	"os/signal"
 	"syscall"
 
 	"github.com/prometheus/client_golang/prometheus"
-	"github.com/prometheus/client_golang/prometheus/promhttp"
 	"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/cfg"
 	"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/collector/f2b"
 	"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/collector/textfile"
 	"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/server"
 )
 
-const (
-	metricsPath = "/metrics"
-)
-
 var (
 	version = "dev"
 	commit  = "none"
@@ -32,26 +26,6 @@ func printAppVersion() {
 	fmt.Printf("    build date:  %s\r\n    commit hash: %s\r\n    built by:    %s\r\n", date, commit, builtBy)
 }
 
-func rootHtmlHandler(w http.ResponseWriter, r *http.Request) {
-	_, err := w.Write([]byte(
-		`<html>
-			<head><title>Fail2Ban Exporter</title></head>
-			<body>
-			<h1>Fail2Ban Exporter</h1>
-			<p><a href="` + metricsPath + `">Metrics</a></p>
-			</body>
-		</html>`))
-	if err != nil {
-		log.Printf("error handling root url: %v", err)
-		w.WriteHeader(http.StatusInternalServerError)
-	}
-}
-
-func metricHandler(w http.ResponseWriter, r *http.Request, collector *textfile.Collector) {
-	promhttp.Handler().ServeHTTP(w, r)
-	collector.WriteTextFileMetrics(w, r)
-}
-
 func main() {
 	appSettings := cfg.Parse()
 	if appSettings.VersionMode {
@@ -67,21 +41,7 @@ func main() {
 		textFileCollector := textfile.NewCollector(appSettings)
 		prometheus.MustRegister(textFileCollector)
 
-		http.HandleFunc("/", server.BasicAuthMiddleware(rootHtmlHandler, appSettings.AuthProvider))
-		http.HandleFunc(metricsPath, server.BasicAuthMiddleware(
-			func(w http.ResponseWriter, r *http.Request) {
-				metricHandler(w, r, textFileCollector)
-			},
-			appSettings.AuthProvider,
-		))
-		log.Printf("metrics available at '%s'", metricsPath)
-
-		svrErr := make(chan error)
-		go func() {
-			svrErr <- http.ListenAndServe(appSettings.MetricsAddress, nil)
-		}()
-		log.Print("ready")
-
+		svrErr := server.StartServer(appSettings, textFileCollector)
 		err := <-svrErr
 		log.Fatal(err)
 	}
diff --git a/server/handler.go b/server/handler.go
new file mode 100644
index 0000000..a0d8bf2
--- /dev/null
+++ b/server/handler.go
@@ -0,0 +1,33 @@
+package server
+
+import (
+	"log"
+	"net/http"
+
+	"github.com/prometheus/client_golang/prometheus/promhttp"
+	"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/collector/textfile"
+)
+
+const (
+	metricsPath = "/metrics"
+)
+
+func rootHtmlHandler(w http.ResponseWriter, r *http.Request) {
+	_, err := w.Write([]byte(
+		`<html>
+			<head><title>Fail2Ban Exporter</title></head>
+			<body>
+			<h1>Fail2Ban Exporter</h1>
+			<p><a href="` + metricsPath + `">Metrics</a></p>
+			</body>
+		</html>`))
+	if err != nil {
+		log.Printf("error handling root url: %v", err)
+		w.WriteHeader(http.StatusInternalServerError)
+	}
+}
+
+func metricHandler(w http.ResponseWriter, r *http.Request, collector *textfile.Collector) {
+	promhttp.Handler().ServeHTTP(w, r)
+	collector.WriteTextFileMetrics(w, r)
+}
diff --git a/server/server.go b/server/server.go
new file mode 100644
index 0000000..70599a4
--- /dev/null
+++ b/server/server.go
@@ -0,0 +1,33 @@
+package server
+
+import (
+	"log"
+	"net/http"
+
+	"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/cfg"
+	"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/collector/textfile"
+)
+
+func StartServer(
+	appSettings *cfg.AppSettings,
+	textFileCollector *textfile.Collector,
+) chan error {
+	http.HandleFunc("/", BasicAuthMiddleware(
+		rootHtmlHandler,
+		appSettings.AuthProvider,
+	))
+	http.HandleFunc(metricsPath, BasicAuthMiddleware(
+		func(w http.ResponseWriter, r *http.Request) {
+			metricHandler(w, r, textFileCollector)
+		},
+		appSettings.AuthProvider,
+	))
+	log.Printf("metrics available at '%s'", metricsPath)
+
+	svrErr := make(chan error)
+	go func() {
+		svrErr <- http.ListenAndServe(appSettings.MetricsAddress, nil)
+	}()
+	log.Print("ready")
+	return svrErr
+}