mirkoify
diff --git a/Gopkg.lock b/Gopkg.lock
index 9058ae0..e565ddc 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -10,6 +10,14 @@
   revision = "624295da664fea57a1e3bd8cee639ae04f4c0ccf"
 
 [[projects]]
+  branch = "master"
+  digest = "1:48353f64f7cc9626e4396b286552812a40a9c1d3e653d51ecbe6cedf2c4f4778"
+  name = "code.hackerspace.pl/q3k/mirko"
+  packages = ["."]
+  pruneopts = "UT"
+  revision = "b21f9b9a2ec6ada755aac41595acdf1961d3c48d"
+
+[[projects]]
   digest = "1:d1665c44bd5db19aaee18d1b6233c99b0b9a986e8bccb24ef54747547a48027f"
   name = "github.com/PuerkitoBio/purell"
   packages = ["."]
@@ -180,10 +188,11 @@
   revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998"
 
 [[projects]]
-  digest = "1:4c0989ca0bcd10799064318923b9bc2db6b4d6338dd75f3f2d86c3511aaaf5cf"
+  digest = "1:5d1b5a25486fc7d4e133646d834f6fca7ba1cef9903d40e7aa786c41b89e9e91"
   name = "github.com/golang/protobuf"
   packages = [
     "proto",
+    "protoc-gen-go/descriptor",
     "ptypes",
     "ptypes/any",
     "ptypes/duration",
@@ -301,7 +310,7 @@
   revision = "af9cb2a35e7f169ec875002c1829c9b315cddc04"
 
 [[projects]]
-  digest = "1:ab8e92d746fb5c4c18846b0879842ac8e53b3d352449423d0924a11f1020ae1b"
+  digest = "1:dc0c170b110c22d9a4eccf08ab58490608053eac450bf456f3aaf9b30a668781"
   name = "google.golang.org/grpc"
   packages = [
     ".",
@@ -324,6 +333,8 @@
     "metadata",
     "naming",
     "peer",
+    "reflection",
+    "reflection/grpc_reflection_v1alpha",
     "resolver",
     "resolver/dns",
     "resolver/passthrough",
@@ -367,6 +378,7 @@
   analyzer-version = 1
   input-imports = [
     "code.hackerspace.pl/q3k/hspki",
+    "code.hackerspace.pl/q3k/mirko",
     "github.com/digitalocean/go-netbox/netbox",
     "github.com/digitalocean/go-netbox/netbox/client",
     "github.com/digitalocean/go-netbox/netbox/client/dcim",
diff --git a/graph/.graph.go.swp b/graph/.graph.go.swp
deleted file mode 100644
index 14109d8..0000000
--- a/graph/.graph.go.swp
+++ /dev/null
Binary files differ
diff --git a/main.go b/main.go
index 87675bc..bbaba70 100644
--- a/main.go
+++ b/main.go
@@ -7,6 +7,7 @@
 	"flag"
 	"io/ioutil"
 
+	"code.hackerspace.pl/q3k/mirko"
 	"github.com/digitalocean/go-netbox/netbox"
 	"github.com/digitalocean/go-netbox/netbox/client"
 	"github.com/golang/glog"
@@ -22,7 +23,6 @@
 	flagConfigPath   string
 	flagNetboxHost   string
 	flagNetboxAPIKey string
-	flagDebugListen  string
 )
 
 func init() {
@@ -33,9 +33,13 @@
 	flag.StringVar(&flagConfigPath, "config_path", "./topo.pb.text", "Text proto configuration of Topo (per config.proto)")
 	flag.StringVar(&flagNetboxHost, "netbox_host", "netbox.bgp.wtf", "Netbox host")
 	flag.StringVar(&flagNetboxAPIKey, "netbox_api_key", "", "Netbox API key")
-	flag.StringVar(&flagDebugListen, "debug_listen", "127.0.0.1:42001", "Debug HTTP listen address")
 	flag.Parse()
 
+	m := mirko.New()
+	if err := m.Listen(); err != nil {
+		glog.Exitf("Listen(): %v", err)
+	}
+
 	ctx := context.Background()
 
 	data, err := ioutil.ReadFile(flagConfigPath)
@@ -65,9 +69,12 @@
 		glog.Exitf("Initial netbox feed failed: %v", err)
 	}
 
-	sconf := ServiceConfig{
-		DebugListen: flagDebugListen,
+	s := NewService(gr, stm)
+	s.Setup(m)
+
+	if err := m.Serve(); err != nil {
+		glog.Exitf("Serve(): %v", err)
 	}
-	srv := NewService(gr, stm, sconf)
-	srv.Run()
+
+	select {}
 }
diff --git a/service.go b/service.go
index 03fd218..ec75153 100644
--- a/service.go
+++ b/service.go
@@ -7,8 +7,8 @@
 	"sort"
 	"strings"
 
+	"code.hackerspace.pl/q3k/mirko"
 	"github.com/gobuffalo/packr"
-	"github.com/golang/glog"
 	"github.com/q3k/statusz"
 	"vbom.ml/util/sortorder"
 
@@ -18,21 +18,15 @@
 	pb "code.hackerspace.pl/q3k/topo/proto/control"
 )
 
-type ServiceConfig struct {
-	DebugListen string
-}
-
 type Service struct {
-	gr     *graph.Graph
-	stm    *state.StateManager
-	config ServiceConfig
+	gr  *graph.Graph
+	stm *state.StateManager
 }
 
-func NewService(gr *graph.Graph, stm *state.StateManager, c ServiceConfig) *Service {
+func NewService(gr *graph.Graph, stm *state.StateManager) *Service {
 	return &Service{
-		gr:     gr,
-		stm:    stm,
-		config: c,
+		gr:  gr,
+		stm: stm,
 	}
 }
 
@@ -110,20 +104,14 @@
 	</div>
 `
 
-func (s *Service) Run() {
+func (s *Service) Setup(m *mirko.Mirko) {
 	assets := packr.NewBox("./assets")
-	http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(assets)))
-	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
-		http.Redirect(w, r, "/debug/status", http.StatusSeeOther)
-	})
-	http.HandleFunc("/debug/graphviz", s.httpHandleGraphviz)
-
+	m.HTTPMux().Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(assets)))
+	m.HTTPMux().HandleFunc("/debug/graphviz", s.httpHandleGraphviz)
 	statusz.AddStatusPart("Switch Ports", switchportsFragment, s.statusHandleSwitchports)
 	statusz.AddStatusPart("Topology", topologyFragment, func(ctx context.Context) interface{} {
 		return nil
 	})
-	glog.Infof("Debug listening on %s....", s.config.DebugListen)
-	http.ListenAndServe(s.config.DebugListen, nil)
 }
 
 func (s *Service) statusHandleSwitchports(ctx context.Context) interface{} {