diff --git a/cmd/root.go b/cmd/root.go
index 24a5fed67463871d5a6360faa32b02f5b77cecf2..66cdc3210192b7d22bfd981685f68c3d5df235f3 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -32,6 +32,7 @@ package cmd
 
 import (
   "code.fbi.h-da.de/cocsn/gosdn/nucleus"
+  "context"
   "fmt"
   log "github.com/sirupsen/logrus"
   "github.com/spf13/cobra"
@@ -46,6 +47,7 @@ var username string
 var password string
 var address string
 var loglevel string
+var grpcPort string
 
 
 // rootCmd represents the base command when called without any subcommands
@@ -54,8 +56,9 @@ var rootCmd = &cobra.Command{
   Short: "starts the gosdn controller",
   Long: `Set GOSDN_DEBUG environment variable to enalbe debug logging.`,
   	RunE: func(cmd *cobra.Command, args []string) error {
-  	  rc := make(chan bool)
-  	  return nucleus.StartAndRun(rc)
+  	  ctx, cancel := context.WithCancel(context.Background())
+  	  defer cancel()
+  	  return nucleus.Run(ctx)
     },
 }
 
@@ -63,7 +66,9 @@ var rootCmd = &cobra.Command{
 // This is called by main.main(). It only needs to happen once to the rootCmd.
 func Execute() {
   if err := rootCmd.Execute(); err != nil {
-    fmt.Println(err)
+    log.WithFields(log.Fields{
+
+    }).Error(err)
     os.Exit(1)
   }
 }
@@ -80,6 +85,8 @@ func init() {
   rootCmd.PersistentFlags().StringVarP(&password, "password", "p", "arista", "password for a gnmi resource")
   rootCmd.PersistentFlags().StringVarP(&username, "address", "a", "ceos-cocsn.apps.ocp.fbi.h-da.de:6030", "address to a gnmi resource")
   rootCmd.PersistentFlags().StringVarP(&loglevel, "log-level", "l", "", "log level 'debug' or 'trace'")
+
+  rootCmd.Flags().StringVar(&grpcPort, "grpc-port", "55055", "port for gRPC NBI")
 }
 
 
@@ -90,6 +97,8 @@ func initConfig() {
     viper.SetConfigFile(cfgFile)
   } else {
     viper.AddConfigPath("./configs")
+    viper.AddConfigPath("/usr/local/etc/gosdn/")
+    viper.SetConfigType("toml")
     viper.SetConfigName("gosdn")
   }
 
@@ -100,7 +109,9 @@ func initConfig() {
     fmt.Println("Using config file:", viper.ConfigFileUsed())
   }
 
-  loglevel = viper.GetString("GOSDN_DEBUG")
+  viper.SetDefault("socket", ":" + grpcPort)
+
+  loglevel = viper.GetString("GOSDN_LOG")
   log.SetReportCaller(true)
   switch loglevel {
   case "trace":
diff --git a/nucleus/controller.go b/nucleus/controller.go
index e503fb60e5f8fa45f60b5d557b7c84a7af530f71..f7477d6baf0dd5514442c1424d176a1ce0676179 100644
--- a/nucleus/controller.go
+++ b/nucleus/controller.go
@@ -1,12 +1,11 @@
 package nucleus
 
 import (
-	"github.com/google/uuid"
-	"os"
-
 	"code.fbi.h-da.de/cocsn/gosdn/database"
+	"context"
+	"github.com/google/uuid"
 	log "github.com/sirupsen/logrus"
-	"github.com/spf13/viper"
+	"time"
 )
 
 // Core is the representation of the controllers core
@@ -14,13 +13,19 @@ type Core struct {
 	// deprecated
 	database database.Database
 
-	pndc      pndStore
-	sbic      sbiStore
-	IsRunning chan bool
+	pndc pndStore
+	sbic sbiStore
 }
 
+var c *Core
+
 //Initialize does start-up housekeeping like reading controller config files
-func (c *Core) Initialize(IsRunningChannel chan bool) error {
+func initialize() error {
+	c = &Core{
+		database: database.Database{},
+		pndc:     pndStore{},
+		sbic:     sbiStore{},
+	}
 	c.sbic = sbiStore{
 		store{},
 	}
@@ -28,53 +33,48 @@ func (c *Core) Initialize(IsRunningChannel chan bool) error {
 		store{},
 	}
 
-	// Set config defaults
-	viper.SetDefault("socket", ":55055")
-
-	// Set config path and read config
-	viper.SetConfigName("gosdn")
-	viper.SetConfigType("toml")
-	viper.AddConfigPath("/usr/local/etc/gosdn/")
-	viper.AddConfigPath("./configs/")
-	err := viper.ReadInConfig()
-	if err != nil {
+	if err := createSouthboundInterfaces(); err != nil {
 		return err
 	}
-	c.AttachDatabase()
-	if err := c.CreateSouthboundInterfaces(); err != nil {
+	// TODO: Start grpc listener here
+
+	if err := httpApi(); err != nil {
 		return err
 	}
 
-	c.IsRunning = IsRunningChannel
+	attachDatabase()
+
 	return nil
 }
 
 // deprecated
 // AttachDatabase connects to the database and passes the connection to the controller core
-func (c *Core) AttachDatabase() {
+func attachDatabase() {
 	c.database = database.NewDatabaseClient()
 }
 
 // CreateSouthboundInterfaces initializes the controller with its supported SBIs
-func (c *Core) CreateSouthboundInterfaces() error {
-	if err := c.sbic.add(&OpenConfig{id: uuid.New()}); err != nil {
-		return err
-	}
+func createSouthboundInterfaces() error {
 	if err := c.sbic.add(&OpenConfig{id: uuid.New()}); err != nil {
 		return err
 	}
 	return nil
 }
 
-// Shutdown waits for the shutdown signal and gracefully shuts down once it arrived
-func (c *Core) Shutdown() {
-	<-c.IsRunning
-	log.Info("Received shutdown signal. Shutting down")
+func Run(ctx context.Context) error {
+	if err := initialize(); err != nil {
+		log.WithFields(log.Fields{
 
-	err := viper.WriteConfig()
-	if err != nil {
-		log.Fatal(err)
+		}).Error(err)
+		return err
+	}
+	log.WithFields(log.Fields{}).Info("initialisation finished")
+	for {
+		select {
+		case <-ctx.Done():
+			return nil
+		case <-time.Tick(time.Minute):
+			log.Debug("up and running")
+		}
 	}
-	log.Info("Shutdown complete")
-	os.Exit(0)
 }
diff --git a/nucleus/http.go b/nucleus/http.go
new file mode 100644
index 0000000000000000000000000000000000000000..390c123ed25e47ba8bd2e5981691fd36970754fa
--- /dev/null
+++ b/nucleus/http.go
@@ -0,0 +1,124 @@
+package nucleus
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
+	"fmt"
+	"github.com/google/uuid"
+	gpb "github.com/openconfig/gnmi/proto/gnmi"
+	log "github.com/sirupsen/logrus"
+	"net/http"
+	"net/url"
+)
+
+const basePath = "/api"
+
+func httpApi() (err error) {
+	id := c.sbic.UUIDs()[0]
+	sbi, err := c.sbic.get(id)
+	if err != nil {
+		return
+	}
+	pnd, err := NewPND("http", "http base pnd", uuid.New(), sbi)
+	if err != nil {
+		return
+	}
+	err = c.pndc.add(pnd)
+	if err != nil {
+		return
+	}
+
+	httpHandler := func(writer http.ResponseWriter, request *http.Request) {
+		log.WithFields(log.Fields{
+			"request": request,
+		}).Debug("incoming request")
+
+		query, err := url.ParseQuery(request.URL.RawQuery)
+		if err != nil {
+			log.Error(err)
+			return
+		}
+
+		id, err := uuid.Parse(query.Get("uuid"))
+		if err != nil {
+			log.Error(err)
+		}
+
+		switch query.Get("q") {
+		case "addDevice":
+			d, err := NewDevice(sbi, &GnmiTransportOptions{
+				Config: gnmi.Config{
+					Addr:     query.Get("address"),
+					Password: query.Get("password"),
+					Username: query.Get("username"),
+					Encoding: gpb.Encoding_JSON_IETF,
+				},
+				SetNode:   sbi.SetNode(),
+				Unmarshal: sbi.(*OpenConfig).Unmarshal(),
+				RespChan:  make(chan *gpb.SubscribeResponse),
+			})
+			err = pnd.AddDevice(d)
+			if err != nil {
+				writer.WriteHeader(http.StatusBadRequest)
+				log.Error(err)
+				return
+			}
+			writer.WriteHeader(http.StatusCreated)
+		case "request":
+			err = pnd.Request(id, query.Get("path"))
+			if err != nil {
+				switch err.(type) {
+				case *ErrNotFound:
+					writer.WriteHeader(http.StatusNotFound)
+				default:
+					writer.WriteHeader(http.StatusInternalServerError)
+				}
+				log.Error(err)
+				return
+			}
+			writer.WriteHeader(http.StatusOK)
+		case "requestAll":
+			err = pnd.RequestAll(query.Get("path"))
+			if err != nil {
+				switch err.(type) {
+				case *ErrNotFound:
+					writer.WriteHeader(http.StatusNotFound)
+				default:
+					writer.WriteHeader(http.StatusInternalServerError)
+				}
+				log.Error(err)
+				return
+			}
+			writer.WriteHeader(http.StatusOK)
+		case "getDevice":
+			device, err := pnd.MarshalDevice(id)
+			if err != nil {
+				switch err.(type) {
+				case *ErrNotFound:
+					writer.WriteHeader(http.StatusNotFound)
+				default:
+					writer.WriteHeader(http.StatusInternalServerError)
+				}
+				log.Error(err)
+				return
+			}
+			writer.Header().Set("Content-Type", "application/json")
+			fmt.Fprintf(writer, "%v", device)
+		case "getIDs":
+			ids := pnd.(*pndImplementation).devices.UUIDs()
+			for i, id := range ids {
+				fmt.Fprintf(writer, "%v: %v\n", i+1, id)
+			}
+		default:
+			writer.WriteHeader(http.StatusBadRequest)
+		}
+	}
+	http.HandleFunc(basePath, httpHandler)
+
+	go func() {
+		err = http.ListenAndServe(":8080", nil)
+		if err != nil {
+			return
+		}
+	}()
+	return nil
+}
diff --git a/nucleus/nucleus-core.go b/nucleus/nucleus-core.go
deleted file mode 100644
index 1256182d1ab456247945d7af5c5242ad3dd8a04d..0000000000000000000000000000000000000000
--- a/nucleus/nucleus-core.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package nucleus
-
-import (
-	"time"
-
-	log "github.com/sirupsen/logrus"
-)
-
-//StartAndRun starts the gosdn core and auxiliary services.
-func StartAndRun(IsRunningChannel chan bool) error {
-	log.Info("This is the network superintendent...")
-	log.Info("Starting my ducks")
-
-	// Initialize the Core
-	core := Core{}
-	if err := core.Initialize(IsRunningChannel); err != nil {
-		return err
-	}
-	go core.Shutdown()
-
-	log.Info("and ready for take off")
-
-	//Just to produce some signs of vitality...
-	for {
-		time.Sleep(10 * time.Second)
-		log.Debug("Still alive...")
-	}
-}