diff --git a/.gitignore b/.gitignore
index 2df65224e347b7d94c61db238220b38118c5a538..0340bd651fee853c7c8fa9e2859e891594ee411b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@ gl-codeclimate.json
 
 # containerlab
 clab-gosdn*/
+clab-*/
 *.yml.bak
 dev_env_data/clab/*.yaml.bak
 
diff --git a/applications/rtdt-manager/.gitignore b/applications/rtdt-manager/.gitignore
index 97e240260a403059f75e4876461ea51d001f1ab0..3b1e998f8d9eabb808312d46a450162b1aa0e9ee 100644
--- a/applications/rtdt-manager/.gitignore
+++ b/applications/rtdt-manager/.gitignore
@@ -1,3 +1,4 @@
 *.bak
 *.BAK
 twin*
+tmp/
diff --git a/applications/rtdt-manager/clab-config/clab-config.go b/applications/rtdt-manager/clab-config/clab-config.go
index 432fb25cb92a174979987dd02f9dcaced27b0e86..75a401e657f9214b8bd8edcb894a0e8c3aab8211 100644
--- a/applications/rtdt-manager/clab-config/clab-config.go
+++ b/applications/rtdt-manager/clab-config/clab-config.go
@@ -13,7 +13,6 @@ import (
 
 	"gopkg.in/yaml.v3"
 
-	"code.fbi.h-da.de/danet/gosdn/api/go/gosdn/networkelement"
 	util "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/util"
 )
 
@@ -60,9 +59,10 @@ type Link struct {
 // from the DB
 var nodeBlueprints = map[string]Node{
 	"gnmi-target-switch": {
-		Kind:         "linux",
-		Image:        "registry.code.fbi.h-da.de/danet/gnmi-target/debian:interface-enabled-test",
-		Binds:        []string{"../../../artifacts/ssl/gnmi-target:/etc/gnmi-target/ssl"},
+		Kind:  "linux",
+		Image: "gnmi-target-local",
+		//Image:        "registry.code.fbi.h-da.de/danet/gnmi-target/debian:interface-enabled-test",
+		Binds:        []string{"../../../../artifacts/ssl/gnmi-target:/etc/gnmi-target/ssl"},
 		Cmd:          "start --ca_file /etc/gnmi-target/ssl/ca.crt --cert /etc/gnmi-target/ssl/certs/gnmi-target-selfsigned.crt --key /etc/gnmi-target/ssl/private/gnmi-target-selfsigned.key",
 		StartupDelay: 5,
 	},
@@ -71,6 +71,41 @@ var nodeBlueprints = map[string]Node{
 	},
 }
 
+// Function for deep copying clab config struct
+func (c *ClabConfig) Copy() *ClabConfig {
+	newC := &ClabConfig{
+		Name: c.Name,
+		Mgmt: c.Mgmt,
+		Topology: Topology{
+			Nodes: make(map[string]Node),
+			Links: make([]Link, len(c.Topology.Links)),
+		},
+	}
+	for name, node := range c.Topology.Nodes {
+		newNode := Node{
+			Kind:         node.Kind,
+			Image:        node.Image,
+			Ports:        append([]string{}, node.Ports...),
+			Cmd:          node.Cmd,
+			MgmtIPv4:     node.MgmtIPv4,
+			Env:          make(map[string]string),
+			Binds:        append([]string{}, node.Binds...),
+			StartupDelay: node.StartupDelay,
+			Group:        node.Group,
+		}
+		for envName, env := range node.Env {
+			newNode.Env[envName] = env
+		}
+		newC.Topology.Nodes[name] = newNode
+	}
+	for i, link := range c.Topology.Links {
+		newC.Topology.Links[i] = Link{
+			Endpoints: append([]string{}, link.Endpoints...),
+		}
+	}
+	return newC
+}
+
 func GetNodeTemplate(kind, ipv4subnet string) *Node {
 	re := regexp.MustCompile("(^\\D+)(\\d)")
 	matches := re.FindStringSubmatch(kind)
@@ -90,6 +125,8 @@ func GetNodeTemplate(kind, ipv4subnet string) *Node {
 			fmt.Printf("Error trying to get centos digit: %v\n", err)
 			return nil
 		}
+		// Alter the ideitifying octet in the ipaddress, not ideal but works for now
+		// Has to be done this way because sdnconfig doesn't save an address for non-gnmi-targets
 		ipOffset := digit + 17
 		ipv4subnetSplit := strings.Split(ipv4subnet, ".")
 		ipv4subnetSplit[3] = strconv.Itoa(ipOffset)
@@ -136,14 +173,18 @@ func LoadConfig(filename string) (*ClabConfig, error) {
 func WriteConfig(filename string, config *ClabConfig) error {
 	data, err := yaml.Marshal(config)
 	if err != nil {
-		return fmt.Errorf("failed to marshal YAML: %w", err)
+		return fmt.Errorf("Failed to marshal YAML: %w", err)
+	}
+	dir := filepath.Dir(filename)
+	if _, err := os.Stat(dir); os.IsNotExist(err) {
+		if err := os.MkdirAll(dir, 0700); err != nil {
+			return fmt.Errorf("failed to create directory %s: %w", dir, err)
+		}
 	}
-
 	err = os.WriteFile(filename, data, 0644)
 	if err != nil {
 		return fmt.Errorf("failed to write file: %w", err)
 	}
-
 	return nil
 }
 
@@ -156,46 +197,30 @@ func incrementPort(port string, offset int) (string, error) {
 	return strconv.Itoa(portNum + offset), nil
 }
 
-// TODO
-// What we get from this relevant for ClabConfig:
-// Name, Plugin? TransportOptions (Address, Type), TLS yes/no
-// Not for ClabConfig but useful: Pnd, GnmiSubscribepaths,
-func (c *ClabConfig) InsertMNE(mnes []*networkelement.ManagedNetworkElement) {
-	for _, mne := range mnes {
-		c.Topology.Nodes[mne.Name] = Node{
-			MgmtIPv4: mne.TransportAddress,
-		}
-	}
-}
-
-// Take a clab yaml config file and derive another clab config from it
-func DeriveConfig(clabconfig *ClabConfig, newIPv4Subnet, newIPv6Subnet string, postfix string) (*ClabConfig, error) {
+// Take a clab yaml config file and derive another clab config from it (only use to derive base clab)
+func DeriveConfig(clabConfig *ClabConfig, newIPv4Subnet, newIPv6Subnet string, clabName string) (*ClabConfig, error) {
 	// Create deep copy
-	derivedConfig := *clabconfig
+	derivedConfig := *clabConfig
 	derivedConfig.Topology.Nodes = make(map[string]Node)
-	derivedConfig.Topology.Links = append([]Link{}, clabconfig.Topology.Links...) // Copy links
+	derivedConfig.Topology.Links = append([]Link{}, clabConfig.Topology.Links...) // Copy links
 	portOffset := 5                                                               // TODO set dynamically in some way
 
-	derivedConfig.Name = fmt.Sprintf("%s-%s", clabconfig.Name, postfix)
+	derivedConfig.Name = fmt.Sprintf("gosdn_%s", clabName)
+	derivedConfig.Mgmt.Network = fmt.Sprintf("gosdn-%s-net", clabName)
 	subnetParts := strings.Split(newIPv4Subnet, ".")
 	derivedConfig.Mgmt.IPv4Subnet = newIPv4Subnet
 	derivedConfig.Mgmt.IPv6Subnet = newIPv6Subnet
-	derivedConfig.Mgmt.Network = fmt.Sprintf("%s-%s", clabconfig.Name, postfix)
 
 	// Adjust all nodes
-	for name, node := range clabconfig.Topology.Nodes {
+	for name, node := range clabConfig.Topology.Nodes {
 		splitIPv4 := strings.Split(node.MgmtIPv4, ".")
 		splitIPv4[0], splitIPv4[1], splitIPv4[2] = subnetParts[0], subnetParts[1], subnetParts[2]
 		node.MgmtIPv4 = strings.Join(splitIPv4, ".")
 
-		if strings.HasPrefix(name, "gosdn") {
-			node.Cmd = "--config /app/configs/containerlab-gosdn-twin.toml"
-			//node.Binds = []string{"../../../applications/rtdt-manager/data/ssl/gosdn:/app/ssl"}
-		}
-		//
-		// //use separate ssl folders, testing
-		// if strings.HasPrefix(name, "gnmi-target") {
-		// 	node.Binds = []string{"../../../applications/rtdt-manager/data/ssl/gnmi-target:/etc/gnmi-target/ssl"}
+		// if strings.HasPrefix(name, "gosdn") {
+		// 	pluginRegistryAddress := fmt.Sprintf("clab-%s-plugin-registry:55057", clabConfig.Name)
+		// 	dbAddress := fmt.Sprintf("mongodb://root:example@clab-%s-mongodb:27017", clabConfig.Name)
+		// 	node.Cmd = fmt.Sprintf("%s --plugin-registry %s -d %s", node.Cmd, pluginRegistryAddress, dbAddress)
 		// }
 		// Ports: host side needs to be incremented or there will be conflicts
 		// for now just use 5 as increment
@@ -224,18 +249,6 @@ func DeriveConfig(clabconfig *ClabConfig, newIPv4Subnet, newIPv6Subnet string, p
 		}
 		derivedConfig.Topology.Nodes[name] = node
 	}
-
-	// Update Links so they reference the correct nodes
-	// for i, link := range clabconfig.Topology.Links {
-	// 	for j, endpoint := range link.Endpoints {
-	// 		parts := strings.Split(endpoint, ":")
-	// 		if len(parts) != 2 {
-	// 			return nil, fmt.Errorf("invalid link endpoint: %s", endpoint)
-	// 		}
-	// 		clabconfig.Topology.Links[i].Endpoints[j] = strings.Join(parts, ":")
-	// 	}
-	// }
-
 	return &derivedConfig, nil
 }
 
diff --git a/applications/rtdt-manager/data/base-clab.yaml b/applications/rtdt-manager/data/base-clab.yaml
index ca733ff57cef7ad9ba1534cd6d0c536e293bac7e..8e051a11fd4637588849eb4047504c16a0d398cf 100644
--- a/applications/rtdt-manager/data/base-clab.yaml
+++ b/applications/rtdt-manager/data/base-clab.yaml
@@ -20,7 +20,7 @@ topology:
         - 55055:55055
         - 8080:8080
         - 40000:40000
-      cmd: --config /app/configs/containerlab-gosdn.toml
+      cmd: --config /app/configs/containerlab-gosdn.toml --plugin-registry clab-gosdn_realnet-plugin-registry:55057 -d mongodb://root:example@clab-realnet_gosdn-mongodb:27017
       mgmt-ipv4: 172.100.0.5
       env:
         GOSDN_ADMIN_PASSWORD: TestPassword
diff --git a/applications/rtdt-manager/data/realnet-deploy-clab.yaml b/applications/rtdt-manager/data/realnet-deploy-clab.yaml
index 29ac6e68025919cee25192d923de860110ec8a55..a13d662a493481b97fc836b4087065c6761aaf64 100644
--- a/applications/rtdt-manager/data/realnet-deploy-clab.yaml
+++ b/applications/rtdt-manager/data/realnet-deploy-clab.yaml
@@ -18,7 +18,7 @@ topology:
             group: server
         gnmi-target-switch0:
             kind: linux
-            image: registry.code.fbi.h-da.de/danet/gnmi-target/debian:interface-enabled-test
+            image: gnmi-target-local
             cmd: start --ca_file /etc/gnmi-target/ssl/ca.crt --cert /etc/gnmi-target/ssl/certs/gnmi-target-selfsigned.crt --key /etc/gnmi-target/ssl/private/gnmi-target-selfsigned.key
             mgmt-ipv4: 172.100.0.11
             binds:
@@ -26,7 +26,7 @@ topology:
             startup-delay: 5
         gnmi-target-switch1:
             kind: linux
-            image: registry.code.fbi.h-da.de/danet/gnmi-target/debian:interface-enabled-test
+            image: gnmi-target-local
             cmd: start --ca_file /etc/gnmi-target/ssl/ca.crt --cert /etc/gnmi-target/ssl/certs/gnmi-target-selfsigned.crt --key /etc/gnmi-target/ssl/private/gnmi-target-selfsigned.key
             mgmt-ipv4: 172.100.0.12
             binds:
@@ -39,7 +39,7 @@ topology:
                 - 55055:55055
                 - 8080:8080
                 - 40000:40000
-            cmd: --config /app/configs/containerlab-gosdn.toml --plugin-registry clab-gosdn_realnet-plugin-registry:55057 -d mongodb://root:example@clab-gosdn_realnet-mongodb:27017
+            cmd: --config /app/configs/containerlab-gosdn.toml --plugin-registry clab-gosdn_realnet-plugin-registry:55057 -d mongodb://root:example@172.100.0.13:27017
             mgmt-ipv4: 172.100.0.5
             env:
                 GOSDN_ADMIN_PASSWORD: TestPassword
diff --git a/applications/rtdt-manager/main.go b/applications/rtdt-manager/main.go
index df792348b185281792cadc0beb2cec04b6bcf88c..4bee9cc7ba850f2ef999391952d02920f680fc10 100644
--- a/applications/rtdt-manager/main.go
+++ b/applications/rtdt-manager/main.go
@@ -93,7 +93,7 @@ func main() {
 	}
 
 	if withTwin {
-		rtdtMan.LaunchTwin("172.101.0.0/16", "2001:db9::/64", "TEST-TWIN")
+		rtdtMan.LaunchTwin("172.101.0.0/16", "2001:db9::/64", "test-twin")
 	}
 	if err := rtdtMan.Run(); err != nil {
 		fmt.Println("Program exited with errors: %w", err)
diff --git a/applications/rtdt-manager/rtdt-manager/rtdt-manager.go b/applications/rtdt-manager/rtdt-manager/rtdt-manager.go
index 37136d8c33ab51578398012fb5219008642c7dbc..ae5d2f77bdc269a678b7754030b68ad770f799a1 100644
--- a/applications/rtdt-manager/rtdt-manager/rtdt-manager.go
+++ b/applications/rtdt-manager/rtdt-manager/rtdt-manager.go
@@ -10,14 +10,10 @@ import (
 	"sync"
 	"time"
 
-	"code.fbi.h-da.de/danet/gosdn/api/go/gosdn/networkelement"
 	"code.fbi.h-da.de/danet/gosdn/application-framework/event"
-
 	"code.fbi.h-da.de/danet/gosdn/application-framework/registration"
 	clabconfig "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/clab-config"
-	rtdt_topology "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/rtdt-topology"
 	"code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/sdnconfig"
-	"code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/util"
 	"code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/venv"
 )
 
@@ -49,7 +45,7 @@ func (r *RtdtManager) LaunchRealnetVEnv(realnetName string, sdnConfig *sdnconfig
 	var realnetClabFName string
 
 	// Generate a clabconfig file based on the base config and sdnconfig
-	realnetClab, err := r.ProduceClabConfig(realnetName, r.baseClabConfig, sdnConfig)
+	realnetClab, err := r.ProduceClabConfig(realnetName, sdnConfig, r.baseClabConfig.Copy())
 	if err != nil {
 		return fmt.Errorf("Error in LaunchRealnet(): %w", err)
 	}
@@ -59,6 +55,7 @@ func (r *RtdtManager) LaunchRealnetVEnv(realnetName string, sdnConfig *sdnconfig
 	if err != nil {
 		return fmt.Errorf("Error in LaunchRealnet() %w", err)
 	}
+	realnetClabPath += "/tmp"
 	realnetClabFName = filepath.Join(realnetClabPath, realnetName+"-deploy-clab.yaml")
 	err = clabconfig.WriteConfig(realnetClabFName, realnetClab)
 	if err != nil {
@@ -78,87 +75,50 @@ func (r *RtdtManager) LaunchRealnetVEnv(realnetName string, sdnConfig *sdnconfig
 	if r.realnet == nil {
 		return fmt.Errorf("Error in LaunchRealnet: Couldn't deploy VEnv")
 	}
-	//TODO: REPLACE THIS WITH ApplyConfiguration() ???
-	// Create the devices based on sdn config file
-	// err = r.realnet.CreateDevices()
-	// if err != nil {
-	// 	fmt.Printf("Error: Couldn't create devices!")
-	// 	return err
-	// }
-	// // Apply the topology based on links in the sdn config file:
-	// err = r.realnet.UploadTopology()
-	// if err != nil {
-	// 	fmt.Printf("Error occured while trying to upload r.realnet topology to DB: %v\n", err)
-	// 	return err
-	// }
-	// return fmt.Errorf("--------------------ONLY RUN UNTIL HERE----------------------------")
-
-	// This doesn't work for some reason..
 	err = r.realnet.ApplyConfiguration(sdnConfig)
 	if err != nil {
 		fmt.Printf("Failed to apply configuration: %v\n", err)
 	}
-	return fmt.Errorf("--------------------ONLY RUN UNTIL HERE----------------------------")
-
-	// Now setup the just-created environment
-	// Need to:
-	// - Upload managed network elements
-	err = r.realnet.DeriveTopologyFromClabData()
-	if err != nil {
-		fmt.Printf("Error occured while trying to construct topology in r.realnet: %v\n", err)
-		return err
-	}
-	return nil
-	err = r.realnet.UploadClabConfig()
-	if err != nil {
-		fmt.Printf("Error: Couldnt upload clab config: %v\n", err)
-		return err
-	}
-	// err = r.realnet.RetrieveClabConfig()
-	// if err != nil {
-	// 	fmt.Printf("Error: Couldn't retrieve clab config: %v\n", err)
-	// 	return err
-	// }
-
 	return nil
 }
 
-func (r *RtdtManager) ProduceClabConfig(clabName string, c *clabconfig.ClabConfig, sdnConfig *sdnconfig.SdnConfig) (*clabconfig.ClabConfig, error) {
-	var clabConfig *clabconfig.ClabConfig
+// takes a prepared sdnconfig to produce a clabConfig struct based on it
+func (r *RtdtManager) ProduceClabConfig(name string, sdnConfig *sdnconfig.SdnConfig, baseClab *clabconfig.ClabConfig) (*clabconfig.ClabConfig, error) {
+	// Test abort conditions
 	if sdnConfig == nil {
 		return nil, fmt.Errorf("Can't produce clab config without loading sdnconfig\n")
 	}
-	// clabConfig can be nil, but wouldn't be very useful without base gosdn environment
-	if c != nil {
-		clabConfig = c
-		for nodeName, node := range clabConfig.Topology.Nodes {
-			// database and plugin-registry need to be loaded dynamically based on generated name
-			if strings.HasPrefix(nodeName, "gosdn") {
-				pluginRegistryAddress := fmt.Sprintf("clab-%s-plugin-registry:55057", clabConfig.Name)
-				dbAddress := fmt.Sprintf("mongodb://root:example@clab-%s-mongodb:27017", clabConfig.Name)
-				newCmd := fmt.Sprintf("%s --plugin-registry %s -d %s", node.Cmd, pluginRegistryAddress, dbAddress)
-				node.Cmd = newCmd
-				clabConfig.Topology.Nodes[nodeName] = node
-				fmt.Println("node.Cmd is now:", node.Cmd)
-			}
-		}
-	} else {
-		return nil, fmt.Errorf("No base clabconfig set\n")
-	}
 	if sdnConfig.Nodes == nil {
 		return nil, fmt.Errorf("sdnconfig exists, but Nodes is nil")
 	}
+	// First get all the node of base gosdn environment (rabbitmq, mongodb etc.)
+	clabConfig := baseClab
+	pluginRegistryAddress := clabConfig.Topology.Nodes["plugin-registry"].MgmtIPv4
+	mongodbAddress := clabConfig.Topology.Nodes["mongodb"].MgmtIPv4
+	// Replace the nodes on the basis of base config
+	// var NewNodes map[string]clabconfig.Node
+	for nodename, node := range clabConfig.Topology.Nodes {
+		// newName := fmt.Sprintf("%s-%s", nodename, name)
+		if strings.HasPrefix(nodename, "gosdn") {
+			node.Binds = []string{"../../../../artifacts/ssl/gosdn:/app/ssl"}
+			pluginRegistryAddress := fmt.Sprintf("%s:55057", pluginRegistryAddress)
+			dbAddress := fmt.Sprintf("mongodb://root:example@%s:27017", mongodbAddress)
+			node.Cmd = fmt.Sprintf("%s --plugin-registry %s -d %s", node.Cmd, pluginRegistryAddress, dbAddress)
+			clabConfig.Topology.Nodes[nodename] = node
+		}
+	}
+	// Create the entries in the clabconfig struct
 	for _, node := range sdnConfig.Nodes {
 		var clabNode *clabconfig.Node
 
-		clabNode = clabconfig.GetNodeTemplate(node.Name, c.Mgmt.IPv4Subnet)
+		clabNode = clabconfig.GetNodeTemplate(node.Name, clabConfig.Mgmt.IPv4Subnet)
 		if clabNode == nil {
 			return nil, fmt.Errorf("No template exists for node %s", node.Name)
 		}
 		mne := sdnConfig.GetMneByID(node.ID)
 		if mne != nil {
 			ipv4 := strings.Split(mne.TransportAddress, ":")
-			clabNode.MgmtIPv4 = ipv4[0] // Doesn't work wor centos hosts
+			clabNode.MgmtIPv4 = ipv4[0] // Doesn't work for non-gnmi-targets
 		} else {
 			fmt.Printf("ProduceClabConfig(): Warning: No MNE entry for node: %s\n", node.Name)
 		}
@@ -183,50 +143,46 @@ func (r *RtdtManager) ProduceClabConfig(clabName string, c *clabconfig.ClabConfi
 // - Use that config to call "containerlab deploy"
 // Launch a second gosdn instance which will manage the virtual network
 func (r *RtdtManager) LaunchTwin(twinSubnetIPv4, twinSubnetIPv6, twinName string) error {
-	var derivedConfig *clabconfig.ClabConfig
-	var twinClabConfig *clabconfig.ClabConfig
 	var clabConfigPath string
 	var err error
-	var topo *rtdt_topology.Topology
-	conn := r.realnet.GetConn()
-
-	topo = r.realnet.GetTopology()
-	if topo == nil {
-		return fmt.Errorf("Error: Couldn't get topology since it hasn't been retrieved from DB yet")
+	var prefixLength int
+	prefixRegex := regexp.MustCompile("/(\\d+)$")
+	prefixMatch := prefixRegex.FindStringSubmatch(twinSubnetIPv4)
+	if len(prefixMatch) > 1 {
+		prefixLength, err = strconv.Atoi(prefixMatch[1])
+		if err != nil {
+			return err
+		}
+	} else {
+		return fmt.Errorf("Couldn't extract prefix length from ipv4 subnet address")
 	}
 
 	// First add the base config's nodes
-	twinClabConfig = r.baseClabConfig
-	// Now retrieve the nodes (gnmi-targets and hosts + topology) via MNE Api
-	mneServiceRealnet := networkelement.NewNetworkElementServiceClient(conn)
-	getRequest := &networkelement.GetAllRequest{
-		Timestamp: util.Now(),
-		Pid:       r.realnet.GetPnd().Id,
+	TwinSdnConfig := sdnconfig.SdnConfig{}
+	// Get the up-to-date sdnconfig from realnet DB
+	err = TwinSdnConfig.RetrieveSdnConfig(r.realnet.GetPnd().String(), *r.realnet.GetAuth())
+	if err != nil {
+		return fmt.Errorf("LaunchTwin Error: %v\n", err)
 	}
-	mneCtx := r.realnet.GetAuth().CreateContextWithAuthorization()
-	getAllResponse, err := mneServiceRealnet.GetAll(mneCtx, getRequest)
-	elements := getAllResponse.GetMne()
-	// These now need to go into the new VEnv's clabData so clab yaml config can be created
-	if len(elements) > 0 {
-		twinClabConfig.InsertMNE(elements)
+	// Transpose the retrieved SdnConfig structs
+	TwinSdnConfig.Transpose(twinName, twinSubnetIPv4, twinSubnetIPv6, prefixLength)
+    fmt.Println("TwinSdnConfig:")
+    fmt.Println(TwinSdnConfig)
+	// produce the twin clab configuration based on the transposed sdnconfig and derived clab
+	baseClabConfig, err := clabconfig.DeriveConfig(r.baseClabConfig.Copy(), twinSubnetIPv4, twinSubnetIPv6, twinName)
+	twinClabConfig, err := r.ProduceClabConfig(twinName, &TwinSdnConfig, baseClabConfig)
+	if err != nil {
+		return err
 	}
-	// Also get topology from db
-	// TODO: Maybe update the topology first before retrieving it?
-	// reminder: Topology might not include all targets? TODO: Check UploadTopology
-	rtdt_topology.NewTopology().RetrieveTopology(r.realnet.GetPnd().Id, r.realnet.GetAuth())
-
-	// Could pass topo, clabconfig and elements into this
+	// Construct filepath for derived clab yaml
 	// Get the basic containerlab config with gosdn, mongodb, rabbitmq
 	clabConfigPath, err = clabconfig.ClabConfigPath()
 	if err != nil {
 		return err
 	}
-	if derivedConfig, err = clabconfig.DeriveConfig(twinClabConfig, twinSubnetIPv4, twinSubnetIPv6, twinName); err != nil {
-		return fmt.Errorf("Failed to derive config for twin: %w", err)
-	}
-	// Construct filepath for derived clab yaml
-	twinClabFName := filepath.Join(clabConfigPath, "twin-clab.yaml")
-	if err = clabconfig.WriteConfig(twinClabFName, derivedConfig); err != nil {
+	clabConfigPath += "/tmp"
+	twinClabFName := filepath.Join(clabConfigPath, twinName+"-clab.yaml")
+	if err = clabconfig.WriteConfig(twinClabFName, twinClabConfig); err != nil {
 		return fmt.Errorf("Failed to write modified twin clab config to disk: %w", err)
 	}
 
diff --git a/applications/rtdt-manager/sdnconfig/sdnconfig.go b/applications/rtdt-manager/sdnconfig/sdnconfig.go
index 23c70e86c6bdcd942488b04ab189c19ed77c8b78..89032c9ec2e3d5c54ced8e885f5e13963e0bac01 100644
--- a/applications/rtdt-manager/sdnconfig/sdnconfig.go
+++ b/applications/rtdt-manager/sdnconfig/sdnconfig.go
@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"os"
 	"path/filepath"
+	"strings"
 	"time"
 
 	configPb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/configurationmanagement"
@@ -120,6 +121,7 @@ func (s *SdnConfig) LoadSdnConfig(configFilename string) error {
 		return fmt.Errorf("Error in LoadSdnConfig(): %w", err)
 	}
 
+	// Output
 	// jsonData, err := json.MarshalIndent(s, "", "  ")
 	// if err != nil {
 	// 	return fmt.Errorf("Error marshalling struct to JSON: %w", err)
@@ -130,6 +132,52 @@ func (s *SdnConfig) LoadSdnConfig(configFilename string) error {
 	return nil
 }
 
+// Transpose an sdnconfig struct networkElements
+// takes name of network, address range in ipv4 and ipv6 (e.g. 172.101.0.0) and ipv4 prefix for network
+// Limitations:
+// - No differing prefix lengths between realnet, twin,
+// - No prefix lengths other than 8, 16, 24 (cidr)
+func (s *SdnConfig) Transpose(name, addressIpv4, addressIpv6 string, ipv4PrefixLength int) {
+	ipv4Parts := strings.Split(addressIpv4, ".")
+	for i := range s.Nodes {
+		s.Nodes[i].Name += fmt.Sprintf("-%s", name)
+	}
+	for i, mne := range s.NetworkElements {
+		HostIpv4Parts := strings.Split(s.NetworkElements[i].TransportAddress, ".")
+		var NewIpv4 string
+		switch ipv4PrefixLength {
+		case 8:
+			NewIpv4 = fmt.Sprintf("%s.%s.%s.%s", ipv4Parts[0], HostIpv4Parts[1], HostIpv4Parts[2], HostIpv4Parts[3])
+		case 16:
+			NewIpv4 = fmt.Sprintf("%s.%s.%s.%s", ipv4Parts[0], ipv4Parts[1], HostIpv4Parts[2], HostIpv4Parts[3])
+		case 24:
+			NewIpv4 = fmt.Sprintf("%s.%s.%s.%s", ipv4Parts[0], ipv4Parts[1], ipv4Parts[2], HostIpv4Parts[3])
+		default:
+			fmt.Printf("Error: unsupported ipv4 prefix length\n")
+
+		}
+		s.NetworkElements[i].Name += fmt.Sprintf("-%s", name)
+		// TransportAddress has form 172.100.0.5:7030
+		s.NetworkElements[i].TransportAddress = NewIpv4
+		s.NetworkElements[i].Model = s.transposeModelIpv4(mne.Model, mne.TransportAddress, addressIpv6, ipv4PrefixLength)
+	}
+	for i := range s.Links {
+		s.Links[i].SourceNode.Name += fmt.Sprintf("-%s", name)
+		s.Links[i].TargetNode.Name += fmt.Sprintf("-%s", name)
+	}
+}
+
+func (s *SdnConfig) transposeModelIpv4(model, ipv4, oldIpv4 string, ipv4PrefixLength int) string {
+	ipv4Parts := strings.Split(ipv4, ".")
+	OldIpv4Parts := strings.Split(oldIpv4, ".")
+	networkPortionLength := ipv4PrefixLength / 8
+	oldNetworkPortion := strings.Join(OldIpv4Parts[:networkPortionLength-1], ".")
+	newNetworkPortion := strings.Join(ipv4Parts[:networkPortionLength-1], ".")
+	strings.ReplaceAll(model, oldNetworkPortion, newNetworkPortion)
+
+	return model
+}
+
 func (s *SdnConfig) RetrieveSdnConfig(pndId string, auth rtdt_auth.RtdtAuth) error {
 	var err error
 	conn := auth.GetConn()
diff --git a/applications/rtdt-manager/venv/venv.go b/applications/rtdt-manager/venv/venv.go
index 1e9edbf042fb1150f3eb2942407ba50b556c87e7..516725614fdf1774ffa3b90ae4e52a1c47a869da 100644
--- a/applications/rtdt-manager/venv/venv.go
+++ b/applications/rtdt-manager/venv/venv.go
@@ -29,7 +29,6 @@ import (
 	"github.com/openconfig/ygot/ygot"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/credentials/insecure"
-	"gopkg.in/yaml.v3"
 )
 
 type VEnv struct {
@@ -81,8 +80,8 @@ func NewVEnv(name, clabFilename, user, pass string, wg *sync.WaitGroup, sdnConfi
 		}
 	}
 
-	fmt.Printf("[%s] - Sleep for 10 seconds to give containers time to settle..\n", name)
-	time.Sleep(time.Second * 10)
+	fmt.Printf("[%s] - Sleep for 15 seconds to give containers time to settle..\n", name)
+	time.Sleep(time.Second * 15)
 	// Now log into gosdn physical network
 	dialOption := grpc.WithTransportCredentials(insecure.NewCredentials())
 	gosdnconn, err := grpc.NewClient(gosdnAddress, dialOption, grpc.WithDefaultCallOptions())
@@ -124,6 +123,7 @@ func NewVEnv(name, clabFilename, user, pass string, wg *sync.WaitGroup, sdnConfi
 	}
 }
 
+// Upload a sdnconfig .json file to the DB
 func (v *VEnv) ApplyConfiguration(sdnConfig *sdnconfig.SdnConfig) error {
 	v.sdnConfig = sdnConfig
 	sdnConfigParsed, err := json.Marshal(v.sdnConfig)
@@ -351,88 +351,6 @@ func (v *VEnv) UploadTopology() error {
 	return nil
 }
 
-// What this does: Upload the nodes that make up the gosdn environment
-// via the gosdn configuration service to the db (applies to db, message broker, etc.)
-// This is probably not the intended use for the configuration interface?
-// TODO Delete! Wrong approach
-func (v *VEnv) UploadClabConfig() error {
-	if v.clabData == nil {
-		return fmt.Errorf("Can't upload clabconfig when it hasn't been loaded yet (is nil pointer)")
-	}
-	var clabToUpload = *v.clabData
-	for nodename, node := range v.clabData.Topology.Nodes {
-		if !strings.Contains(nodename, "gosdn") &&
-			!strings.Contains(nodename, "mongodb") &&
-			!strings.Contains(nodename, "rabbitmq") &&
-			!strings.Contains(nodename, "plugin-registry") {
-			fmt.Println("Removing node:", node)
-			delete(clabToUpload.Topology.Nodes, nodename)
-		}
-	}
-	clabToUpload.Topology.Links = nil
-
-	clabConfig, err := yaml.Marshal(clabToUpload)
-	if err != nil {
-		return fmt.Errorf("Encountered error marshalling clabConfig: %w", err)
-	}
-	var jsonData interface{}
-	if err := yaml.Unmarshal(clabConfig, &jsonData); err != nil {
-		return fmt.Errorf("failed to unmarshal YAML to JSON: %w", err)
-	}
-	jsonBytes, err := json.MarshalIndent(jsonData, "", " ")
-	if err != nil {
-		return fmt.Errorf("Failed to marshal JSON: %w", err)
-	}
-
-	req := &configPb.ImportSDNConfigRequest{
-		Timestamp:     util.Now(),
-		Pid:           v.pnd.GetId(), // TODO: check if this can be nil
-		SdnConfigData: string(jsonBytes),
-	}
-	conn := v.auth.GetConn()
-	configService := configPb.NewConfigurationManagementServiceClient(conn)
-	ctx := v.auth.CreateContextWithAuthorization()
-	configResponse, err := configService.ImportSDNConfig(ctx, req)
-	if err != nil {
-		return err
-	}
-	fmt.Println("Successfully uploaded clab config:", configResponse.String())
-	return nil
-}
-
-// TODO This doesn't really work this way..
-func (v *VEnv) RetrieveClabConfig() error {
-	ctx := v.auth.CreateContextWithAuthorization()
-	conn := v.auth.GetConn()
-	configService := configPb.NewConfigurationManagementServiceClient(conn)
-
-	req := &configPb.ExportSDNConfigRequest{
-		Timestamp: util.Now(),
-		Pid:       v.pnd.GetId(),
-	}
-
-	configResponse, err := configService.ExportSDNConfig(ctx, req)
-	if err != nil {
-		return fmt.Errorf("Failed retrieving config clab data: %w", err)
-	}
-	var jsonData map[string]interface{}
-	err = json.Unmarshal([]byte(configResponse.SdnConfigData), &jsonData)
-	if err != nil {
-		return fmt.Errorf("Failed to unmarshal SDN config data: %w", err)
-	}
-	// Pretty-print the JSON data
-	formattedJSON, err := json.MarshalIndent(jsonData, "", "  ")
-	if err != nil {
-		return fmt.Errorf("failed to format JSON data: %w", err)
-	}
-
-	fmt.Println("Retrieved SDN Config Data:")
-	fmt.Println(string(formattedJSON)) // Print the formatted JSON
-
-	return nil
-
-}
-
 func getTypedValue(value string) *gnmi.TypedValue {
 	if boolVal, err := strconv.ParseBool(value); err == nil {
 		return &gnmi.TypedValue{Value: &gnmi.TypedValue_BoolVal{BoolVal: boolVal}}
diff --git a/controller/interfaces/networkelement/networkElement.go b/controller/interfaces/networkelement/networkElement.go
index 39b7ae9c3297a68c1f3ff22dc3637255d8c3ea04..3433e4350c1ed07dc50c8dd0d3e25fd7058742d8 100644
--- a/controller/interfaces/networkelement/networkElement.go
+++ b/controller/interfaces/networkelement/networkElement.go
@@ -89,7 +89,7 @@ func EnsureIntendedConfigurationIsAppliedOnNetworkElement(mne NetworkElement) er
 	}
 	fmt.Println("Made it here 1")
 
-	req.Update = []*gpb.Update{{
+	req.Replace = []*gpb.Update{{
 		Path: path,
 		Val: &gpb.TypedValue{
 			Value: &gpb.TypedValue_JsonIetfVal{JsonIetfVal: []byte(model)},
diff --git a/controller/northbound/server/configurationmanagement.go b/controller/northbound/server/configurationmanagement.go
index 8b93acc6c6c6be762ef1536fc8a162cce6287222..71dd2e2df3316de6c5b166c7cfbc12c2c9c42570 100644
--- a/controller/northbound/server/configurationmanagement.go
+++ b/controller/northbound/server/configurationmanagement.go
@@ -109,7 +109,6 @@ func (c ConfigurationManagementServer) ExportSDNConfig(ctx context.Context, requ
 			ReattachConfig: *plug.GetClient().ReattachConfig(),
 		}
 		sdnConfig.Plugins = append(sdnConfig.Plugins, loadedPlugin)
-
 	}
 
 	sdnConfig.Nodes, err = c.nodeService.GetAll()
@@ -334,6 +333,7 @@ func (c ConfigurationManagementServer) createNetworkElements(sdnConfig *loadedSD
 			// TODO: change TransportOption - type is not needed; this should
 			// be removed as soon as we remove the csbi device type
 			Type: spb.Type_TYPE_OPENCONFIG,
+            Tls: inputNetworkElement.TransportTLS,
 		}
 
 		plugin, err := c.pluginService.RequestPlugin(uuid.MustParse(inputNetworkElement.Plugin))