diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5afc1e446e7866f3e1636b616bb44d53072d4966..233fbb64f4975205b7ef19cbeb55ab5987af9809 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -51,7 +51,6 @@
       android:name=".ui.chat.topic.TopicActivity"
       android:exported="false"
       android:label="@string/label_topic"
-      android:parentActivityName=".ui.chat.info.channel.ChannelInfoActivity"
       android:windowSoftInputMode="adjustResize" />
 
     <!-- Core Settings -->
@@ -73,6 +72,11 @@
       android:label="@string/settings_network_title"
       android:parentActivityName=".ui.coresettings.CoreSettingsActivity"
       android:windowSoftInputMode="adjustResize" />
+    <activity
+      android:name=".ui.coresettings.networkserver.NetworkServerActivity"
+      android:exported="false"
+      android:label="@string/settings_network_title"
+      android:windowSoftInputMode="adjustResize" />
     <activity
       android:name=".ui.coresettings.identity.IdentityCreateActivity"
       android:exported="false"
diff --git a/app/src/main/java/de/kuschku/quasseldroid/dagger/ActivityModule.kt b/app/src/main/java/de/kuschku/quasseldroid/dagger/ActivityModule.kt
index 422f9fbd367d3154802e6d340d1789a623602546..ae530d1c2043b81025f27c8a4de5c97e67badabe 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/dagger/ActivityModule.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/dagger/ActivityModule.kt
@@ -40,6 +40,8 @@ import de.kuschku.quasseldroid.ui.coresettings.network.NetworkEditActivity
 import de.kuschku.quasseldroid.ui.coresettings.network.NetworkEditFragmentProvider
 import de.kuschku.quasseldroid.ui.coresettings.networkconfig.NetworkConfigActivity
 import de.kuschku.quasseldroid.ui.coresettings.networkconfig.NetworkConfigFragmentProvider
+import de.kuschku.quasseldroid.ui.coresettings.networkserver.NetworkServerActivity
+import de.kuschku.quasseldroid.ui.coresettings.networkserver.NetworkServerFragmentProvider
 import de.kuschku.quasseldroid.ui.setup.accounts.edit.AccountEditActivity
 import de.kuschku.quasseldroid.ui.setup.accounts.selection.AccountSelectionActivity
 import de.kuschku.quasseldroid.ui.setup.accounts.selection.AccountSelectionFragmentProvider
@@ -81,6 +83,9 @@ abstract class ActivityModule {
   @ContributesAndroidInjector(modules = [NetworkEditFragmentProvider::class])
   abstract fun bindNetworkEditActivity(): NetworkEditActivity
 
+  @ContributesAndroidInjector(modules = [NetworkServerFragmentProvider::class])
+  abstract fun bindNetworkServerActivity(): NetworkServerActivity
+
   @ContributesAndroidInjector(modules = [IdentityCreateFragmentProvider::class])
   abstract fun bindIdentityCreateActivity(): IdentityCreateActivity
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/CoreSettingsFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/CoreSettingsFragment.kt
index 9e8ff65448c6a75d6ccf5fb8dc48be498de904d7..25fdaaa019da177c28f06d232eb753854108f1e8 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/CoreSettingsFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/CoreSettingsFragment.kt
@@ -21,6 +21,7 @@ import de.kuschku.quasseldroid.ui.coresettings.chatlist.ChatlistEditActivity
 import de.kuschku.quasseldroid.ui.coresettings.identity.IdentityCreateActivity
 import de.kuschku.quasseldroid.ui.coresettings.identity.IdentityEditActivity
 import de.kuschku.quasseldroid.ui.coresettings.ignorelist.IgnoreListActivity
+import de.kuschku.quasseldroid.ui.coresettings.network.NetworkCreateActivity
 import de.kuschku.quasseldroid.ui.coresettings.network.NetworkEditActivity
 import de.kuschku.quasseldroid.ui.coresettings.networkconfig.NetworkConfigActivity
 import de.kuschku.quasseldroid.util.helper.combineLatest
@@ -131,7 +132,7 @@ class CoreSettingsFragment : ServiceBoundFragment() {
     }
 
     newNetwork.setOnClickListener {
-      //
+      NetworkCreateActivity.launch(requireContext())
     }
 
     newIdentity.setOnClickListener {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityBaseFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityBaseFragment.kt
index 4cca29dbfaecbc5364b22f7a958f2055eec8a70b..ec80b42bdb2ccae459d9c56f52ea04ffbd573438 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityBaseFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityBaseFragment.kt
@@ -104,18 +104,20 @@ abstract class IdentityBaseFragment : SettingsFragment(), SettingsFragment.Savab
       .firstElement()
       .toLiveData().observe(this, Observer {
         it?.let {
-          this.identity = Pair(it, it.copy())
-          this.identity?.let { (_, data) ->
-            identityName.setText(data.identityName())
-            realName.setText(data.realName())
-            ident.setText(data.ident())
-            kickReason.setText(data.kickReason())
-            partReason.setText(data.partReason())
-            quitReason.setText(data.quitReason())
-            awayReason.setText(data.awayReason())
-            detachAway.isChecked = data.detachAwayEnabled()
-            detachAwayReason.setText(data.detachAwayReason())
-            adapter.nicks = data.nicks()
+          if (this.identity == null) {
+            this.identity = Pair(it, it.copy())
+            this.identity?.let { (_, data) ->
+              identityName.setText(data.identityName())
+              realName.setText(data.realName())
+              ident.setText(data.ident())
+              kickReason.setText(data.kickReason())
+              partReason.setText(data.partReason())
+              quitReason.setText(data.quitReason())
+              awayReason.setText(data.awayReason())
+              detachAway.isChecked = data.detachAwayEnabled()
+              detachAwayReason.setText(data.detachAwayReason())
+              adapter.nicks = data.nicks()
+            }
           }
         }
       })
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/ignorelist/IgnoreListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/ignorelist/IgnoreListFragment.kt
index bbdfad785f7373c0cf6cb26e8c734493932049cc..967ab67c638e7ef95e331ae375b8f6381f0bc68f 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/ignorelist/IgnoreListFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/ignorelist/IgnoreListFragment.kt
@@ -57,9 +57,11 @@ class IgnoreListFragment : SettingsFragment(), SettingsFragment.Savable,
       .map(Optional<IgnoreListManager>::get)
       .toLiveData().observe(this, Observer {
         if (it != null) {
-          this.ignoreListManager = Pair(it, it.copy())
-          this.ignoreListManager?.let { (_, data) ->
-            if (adapter.list.isEmpty()) adapter.list = data.ignoreList()
+          if (this.ignoreListManager == null) {
+            this.ignoreListManager = Pair(it, it.copy())
+            this.ignoreListManager?.let { (_, data) ->
+              adapter.list = data.ignoreList()
+            }
           }
         }
       })
@@ -104,7 +106,7 @@ class IgnoreListFragment : SettingsFragment(), SettingsFragment.Savable,
 
   override fun hasChanged() = ignoreListManager?.let { (it, data) ->
     applyChanges(data)
-    data != it
+    data.ignoreList() != it.ignoreList()
   } ?: false
 
   private fun applyChanges(data: IgnoreListManager) {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkBaseFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkBaseFragment.kt
index 4ac703d0908f81fcc6e67bd37958d05c6f5bc342..2340022027e55dde024f2a50b29c0696162e63b3 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkBaseFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkBaseFragment.kt
@@ -1,6 +1,8 @@
 package de.kuschku.quasseldroid.ui.coresettings.network
 
+import android.app.Activity
 import android.arch.lifecycle.Observer
+import android.content.Intent
 import android.os.Bundle
 import android.support.v4.view.ViewCompat
 import android.support.v7.widget.LinearLayoutManager
@@ -21,6 +23,7 @@ import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
 import de.kuschku.libquassel.util.Optional
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
+import de.kuschku.quasseldroid.ui.coresettings.networkserver.NetworkServerActivity
 import de.kuschku.quasseldroid.util.helper.combineLatest
 import de.kuschku.quasseldroid.util.helper.setDependent
 import de.kuschku.quasseldroid.util.helper.toLiveData
@@ -80,6 +83,9 @@ abstract class NetworkBaseFragment : SettingsFragment(), SettingsFragment.Savabl
   @BindView(R.id.autoreconnect_unlimited)
   lateinit var autoreconnectUnlimited: SwitchCompat
 
+  @BindView(R.id.perform)
+  lateinit var perform: EditText
+
   @BindView(R.id.rejoin_channels)
   lateinit var rejoinChannels: SwitchCompat
 
@@ -120,7 +126,10 @@ abstract class NetworkBaseFragment : SettingsFragment(), SettingsFragment.Savabl
     helper.attachToRecyclerView(servers)
 
     newServer.setOnClickListener {
-      // TODO: Add server screen
+      startActivityForResult(
+        NetworkServerActivity.intent(requireContext()),
+        REQUEST_CREATE_SERVER
+      )
     }
 
     val identityAdapter = IdentityAdapter()
@@ -148,33 +157,36 @@ abstract class NetworkBaseFragment : SettingsFragment(), SettingsFragment.Savabl
       .firstElement()
       .toLiveData().observe(this, Observer {
         it?.let {
-          this.network = Pair(it, it.copy())
-          this.network?.let { (_, data) ->
-            networkName.setText(data.networkName())
+          if (this.network == null) {
+            this.network = Pair(it, it.copy())
+            this.network?.let { (_, data) ->
+              networkName.setText(data.networkName())
 
-            identityAdapter.indexOf(data.identity())?.let(identity::setSelection)
+              identityAdapter.indexOf(data.identity())?.let(identity::setSelection)
 
-            adapter.list = data.serverList()
+              adapter.list = data.serverList()
 
-            saslEnabled.isChecked = data.useSasl()
-            saslAccount.setText(data.saslAccount())
-            saslPassword.setText(data.saslPassword())
+              saslEnabled.isChecked = data.useSasl()
+              saslAccount.setText(data.saslAccount())
+              saslPassword.setText(data.saslPassword())
 
-            autoidentifyEnabled.isChecked = data.useAutoIdentify()
-            autoidentifyService.setText(data.autoIdentifyService())
-            autoidentifyPassword.setText(data.autoIdentifyPassword())
+              autoidentifyEnabled.isChecked = data.useAutoIdentify()
+              autoidentifyService.setText(data.autoIdentifyService())
+              autoidentifyPassword.setText(data.autoIdentifyPassword())
 
-            autoreconnectEnabled.isChecked = data.useAutoReconnect()
-            autoreconnectInterval.setText(data.autoReconnectInterval().toString())
-            autoreconnectRetries.setText(data.autoReconnectRetries().toString())
-            autoreconnectUnlimited.isChecked = data.unlimitedReconnectRetries()
+              autoreconnectEnabled.isChecked = data.useAutoReconnect()
+              autoreconnectInterval.setText(data.autoReconnectInterval().toString())
+              autoreconnectRetries.setText(data.autoReconnectRetries().toString())
+              autoreconnectUnlimited.isChecked = data.unlimitedReconnectRetries()
 
-            rejoinChannels.isChecked = data.rejoinChannels()
+              perform.setText(data.perform().joinToString("\n"))
+              rejoinChannels.isChecked = data.rejoinChannels()
 
-            customratelimitsEnabled.isChecked = data.useCustomMessageRate()
-            customratelimitsBurstSize.setText(data.messageRateBurstSize().toString())
-            customratelimitsUnlimited.isChecked = data.unlimitedMessageRate()
-            customratelimitsDelay.setText("${data.messageRateDelay() / 1000.0}")
+              customratelimitsEnabled.isChecked = data.useCustomMessageRate()
+              customratelimitsBurstSize.setText(data.messageRateBurstSize().toString())
+              customratelimitsUnlimited.isChecked = data.unlimitedMessageRate()
+              customratelimitsDelay.setText("${data.messageRateDelay() / 1000.0}")
+            }
           }
         }
       })
@@ -193,14 +205,37 @@ abstract class NetworkBaseFragment : SettingsFragment(), SettingsFragment.Savabl
     return view
   }
 
-  private fun serverClick(index: Int, server: INetwork.Server) {
-    // TODO: Add server screen
+  private fun serverClick(server: INetwork.Server) {
+    startActivityForResult(
+      NetworkServerActivity.intent(requireContext(), server = server),
+      REQUEST_UPDATE_SERVER
+    )
   }
 
   private fun startDrag(holder: RecyclerView.ViewHolder) {
     helper.startDrag(holder)
   }
 
+  override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+    if (resultCode == Activity.RESULT_OK && data != null) {
+      when (requestCode) {
+        REQUEST_UPDATE_SERVER -> {
+          val old = data.getSerializableExtra("old") as? INetwork.Server
+          val new = data.getSerializableExtra("new") as? INetwork.Server
+          if (old != null && new != null) {
+            adapter.replace(old, new)
+          }
+        }
+        REQUEST_CREATE_SERVER -> {
+          val new = data.getSerializableExtra("new") as? INetwork.Server
+          if (new != null) {
+            adapter.add(new)
+          }
+        }
+      }
+    }
+  }
+
   override fun hasChanged() = network?.let { (it, data) ->
     applyChanges(data)
 
@@ -219,6 +254,7 @@ abstract class NetworkBaseFragment : SettingsFragment(), SettingsFragment.Savabl
     data.autoReconnectRetries() != it.autoReconnectRetries() ||
     data.unlimitedReconnectRetries() != it.unlimitedReconnectRetries() ||
     data.rejoinChannels() != it.rejoinChannels() ||
+    data.perform() != it.perform() ||
     data.useCustomMessageRate() != it.useCustomMessageRate() ||
     data.messageRateBurstSize() != it.messageRateBurstSize() ||
     data.unlimitedMessageRate() != it.unlimitedMessageRate() ||
@@ -247,6 +283,7 @@ abstract class NetworkBaseFragment : SettingsFragment(), SettingsFragment.Savabl
                                  ?: data.autoReconnectRetries())
     data.setUnlimitedReconnectRetries(autoreconnectUnlimited.isChecked)
 
+    data.setPerform(perform.text.lines())
     data.setRejoinChannels(rejoinChannels.isChecked)
 
     data.setUseCustomMessageRate(customratelimitsEnabled.isChecked)
@@ -257,4 +294,9 @@ abstract class NetworkBaseFragment : SettingsFragment(), SettingsFragment.Savabl
                                ?.let { (it * 1000).roundToInt() }
                              ?: data.messageRateDelay())
   }
+
+  companion object {
+    private const val REQUEST_UPDATE_SERVER = 1
+    private const val REQUEST_CREATE_SERVER = 2
+  }
 }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkCreateActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkCreateActivity.kt
index a8b204e840757026c1cfdd6b2da347ac6289ce94..25ef7bf72930b924f0d85bd2dd48ef0e01f602d7 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkCreateActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkCreateActivity.kt
@@ -7,6 +7,6 @@ import de.kuschku.quasseldroid.util.ui.SettingsActivity
 class NetworkCreateActivity : SettingsActivity(NetworkCreateFragment()) {
   companion object {
     fun launch(context: Context) = context.startActivity(intent(context))
-    fun intent(context: Context) = Intent(context, NetworkEditActivity::class.java)
+    fun intent(context: Context) = Intent(context, NetworkCreateActivity::class.java)
   }
 }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkServerAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkServerAdapter.kt
index e91a705702380e3e6bea20385dd0762f1ab0102b..80d697bef075f1f5e537acd767284270b44197d9 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkServerAdapter.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkServerAdapter.kt
@@ -18,7 +18,7 @@ import de.kuschku.quasseldroid.util.helper.tint
 import java.util.*
 
 class NetworkServerAdapter(
-  private val clickListener: (Int, INetwork.Server) -> Unit,
+  private val clickListener: (INetwork.Server) -> Unit,
   private val dragListener: (NetworkServerViewHolder) -> Unit
 ) : RecyclerView.Adapter<NetworkServerAdapter.NetworkServerViewHolder>() {
   private val data = mutableListOf<INetwork.Server>()
@@ -38,9 +38,20 @@ class NetworkServerAdapter(
     notifyItemInserted(index)
   }
 
-  fun replace(index: Int, item: INetwork.Server) {
-    data[index] = item
-    notifyItemChanged(index)
+  fun indexOf(item: INetwork.Server): Int? {
+    for ((index, it) in data.withIndex()) {
+      if (it == item) {
+        return index
+      }
+    }
+    return null
+  }
+
+  fun replace(old: INetwork.Server, new: INetwork.Server) {
+    indexOf(old)?.let {
+      data[it] = new
+      notifyItemChanged(it)
+    }
   }
 
   fun remove(index: Int) {
@@ -67,7 +78,7 @@ class NetworkServerAdapter(
 
   class NetworkServerViewHolder(
     itemView: View,
-    clickListener: (Int, INetwork.Server) -> Unit,
+    clickListener: (INetwork.Server) -> Unit,
     dragListener: (NetworkServerViewHolder) -> Unit
   ) : RecyclerView.ViewHolder(itemView) {
     @BindView(R.id.host)
@@ -92,7 +103,7 @@ class NetworkServerAdapter(
       ButterKnife.bind(this, itemView)
       itemView.setOnClickListener {
         item?.let {
-          clickListener(adapterPosition, it)
+          clickListener(it)
         }
       }
       handle.setOnTouchListener { _, event ->
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkconfig/NetworkConfigFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkconfig/NetworkConfigFragment.kt
index e9367b3734eb9efb39751ab37fdaa7965fd20932..e8c697a08a0dbc0dd8a24288cbba4fa5e000a52c 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkconfig/NetworkConfigFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkconfig/NetworkConfigFragment.kt
@@ -60,19 +60,21 @@ class NetworkConfigFragment : SettingsFragment(), SettingsFragment.Savable,
       .map(Optional<NetworkConfig>::get)
       .firstElement()
       .toLiveData().observe(this, Observer {
-        if (it != null) {
-          this.networkConfig = Pair(it, it.copy())
-          this.networkConfig?.let { (_, data) ->
-            pingTimeoutEnabled.isChecked = data.pingTimeoutEnabled()
-            pingInterval.setText(data.pingInterval().toString())
-            maxPingCount.setText(data.maxPingCount().toString())
-
-            autoWhoEnabled.isChecked = data.autoWhoEnabled()
-            autoWhoInterval.setText(data.autoWhoInterval().toString())
-            autoWhoNickLimit.setText(data.autoWhoNickLimit().toString())
-            autoWhoDelay.setText(data.autoWhoDelay().toString())
-
-            standardCtcp.isChecked = data.standardCtcp()
+        it?.let {
+          if (this.networkConfig == null) {
+            this.networkConfig = Pair(it, it.copy())
+            this.networkConfig?.let { (_, data) ->
+              pingTimeoutEnabled.isChecked = data.pingTimeoutEnabled()
+              pingInterval.setText(data.pingInterval().toString())
+              maxPingCount.setText(data.maxPingCount().toString())
+
+              autoWhoEnabled.isChecked = data.autoWhoEnabled()
+              autoWhoInterval.setText(data.autoWhoInterval().toString())
+              autoWhoNickLimit.setText(data.autoWhoNickLimit().toString())
+              autoWhoDelay.setText(data.autoWhoDelay().toString())
+
+              standardCtcp.isChecked = data.standardCtcp()
+            }
           }
         }
       })
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkserver/NetworkServerActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkserver/NetworkServerActivity.kt
new file mode 100644
index 0000000000000000000000000000000000000000..9a9281c6f9ca6bb77e961b83b0104284ee28182c
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkserver/NetworkServerActivity.kt
@@ -0,0 +1,24 @@
+package de.kuschku.quasseldroid.ui.coresettings.networkserver
+
+import android.content.Context
+import android.content.Intent
+import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
+import de.kuschku.quasseldroid.util.ui.SettingsActivity
+
+class NetworkServerActivity : SettingsActivity(NetworkServerFragment()) {
+  companion object {
+    fun launch(
+      context: Context,
+      server: INetwork.Server? = null
+    ) = context.startActivity(intent(context, server))
+
+    fun intent(
+      context: Context,
+      server: INetwork.Server? = null
+    ) = Intent(context, NetworkServerActivity::class.java).apply {
+      if (server != null) {
+        putExtra("server", server)
+      }
+    }
+  }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkserver/NetworkServerFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkserver/NetworkServerFragment.kt
new file mode 100644
index 0000000000000000000000000000000000000000..9cae167bf6370ec26907786573998fc028948dca
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkserver/NetworkServerFragment.kt
@@ -0,0 +1,133 @@
+package de.kuschku.quasseldroid.ui.coresettings.networkserver
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import android.support.v7.widget.SwitchCompat
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.EditText
+import android.widget.Spinner
+import butterknife.BindView
+import butterknife.ButterKnife
+import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
+import de.kuschku.quasseldroid.R
+import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
+import de.kuschku.quasseldroid.util.helper.setDependent
+
+class NetworkServerFragment : SettingsFragment(), SettingsFragment.Savable,
+                              SettingsFragment.Changeable {
+  @BindView(R.id.host)
+  lateinit var host: EditText
+
+  @BindView(R.id.port)
+  lateinit var port: EditText
+
+  @BindView(R.id.ssl_enabled)
+  lateinit var sslEnabled: SwitchCompat
+
+  @BindView(R.id.ssl_verify)
+  lateinit var sslVerify: SwitchCompat
+
+  @BindView(R.id.password)
+  lateinit var password: EditText
+
+  @BindView(R.id.proxy_enabled)
+  lateinit var proxyEnabled: SwitchCompat
+
+  @BindView(R.id.proxy_group)
+  lateinit var proxyGroup: ViewGroup
+
+  @BindView(R.id.proxy_type)
+  lateinit var proxyType: Spinner
+
+  @BindView(R.id.proxy_host)
+  lateinit var proxyHost: EditText
+
+  @BindView(R.id.proxy_port)
+  lateinit var proxyPort: EditText
+
+  @BindView(R.id.proxy_user)
+  lateinit var proxyUser: EditText
+
+  @BindView(R.id.proxy_pass)
+  lateinit var proxyPass: EditText
+
+  private var item: INetwork.Server? = null
+
+  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+                            savedInstanceState: Bundle?): View? {
+    val view = inflater.inflate(R.layout.settings_networkserver, container, false)
+    ButterKnife.bind(this, view)
+
+    (arguments?.getSerializable("server") as? INetwork.Server)?.let {
+      item = it
+    }
+
+    val typeAdapter = ProxyTypeAdapter(listOf(
+      ProxyTypeItem(
+        value = INetwork.ProxyType.Socks5Proxy,
+        name = R.string.settings_networkserver_proxy_type_socks5
+      ),
+      ProxyTypeItem(
+        value = INetwork.ProxyType.HttpProxy,
+        name = R.string.settings_networkserver_proxy_type_http
+      )
+    ))
+    proxyType.adapter = typeAdapter
+
+    item?.let { data ->
+      host.setText(data.host)
+      port.setText(data.port.toString())
+      sslEnabled.isChecked = data.useSsl
+      sslVerify.isChecked = data.sslVerify
+      password.setText(data.password)
+      proxyEnabled.isChecked = data.useProxy
+      proxyType.setSelection(typeAdapter.indexOf(data.proxyType) ?: 0)
+      proxyHost.setText(data.proxyHost)
+      proxyPort.setText(data.proxyPort.toString())
+      proxyUser.setText(data.proxyUser)
+      proxyPass.setText(data.proxyPass)
+    }
+
+    proxyEnabled.setDependent(proxyGroup)
+
+    return view
+  }
+
+  override fun onSave() = item.let { data ->
+    val intent = Intent()
+    intent.putExtra("old", data)
+    val new = INetwork.Server(
+      host = host.text.toString(),
+      port = port.text.toString().toIntOrNull() ?: data?.port ?: 0,
+      useSsl = sslEnabled.isChecked,
+      sslVerify = sslVerify.isChecked,
+      password = password.text.toString(),
+      useProxy = proxyEnabled.isChecked,
+      proxyType = proxyType.selectedItemId.toInt(),
+      proxyHost = proxyHost.text.toString(),
+      proxyPort = proxyPort.text.toString().toIntOrNull() ?: data?.proxyPort ?: 0,
+      proxyUser = proxyUser.text.toString(),
+      proxyPass = proxyPass.text.toString()
+    )
+    intent.putExtra("new", new)
+    requireActivity().setResult(Activity.RESULT_OK, intent)
+    true
+  }
+
+  override fun hasChanged() = item != INetwork.Server(
+    host = host.text.toString(),
+    port = port.text.toString().toIntOrNull() ?: item?.port ?: 0,
+    useSsl = sslEnabled.isChecked,
+    sslVerify = sslVerify.isChecked,
+    password = password.text.toString(),
+    useProxy = proxyEnabled.isChecked,
+    proxyType = proxyType.selectedItemId.toInt(),
+    proxyHost = proxyHost.text.toString(),
+    proxyPort = proxyPort.text.toString().toIntOrNull() ?: item?.proxyPort ?: 0,
+    proxyUser = proxyUser.text.toString(),
+    proxyPass = proxyPass.text.toString()
+  )
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkserver/NetworkServerFragmentProvider.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkserver/NetworkServerFragmentProvider.kt
new file mode 100644
index 0000000000000000000000000000000000000000..5c05de822c9049c0b3a0ae89b24d2521add73a05
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkserver/NetworkServerFragmentProvider.kt
@@ -0,0 +1,10 @@
+package de.kuschku.quasseldroid.ui.coresettings.networkserver
+
+import dagger.Module
+import dagger.android.ContributesAndroidInjector
+
+@Module
+abstract class NetworkServerFragmentProvider {
+  @ContributesAndroidInjector
+  abstract fun bindNetworkServerFragment(): NetworkServerFragment
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkserver/ProxyTypeAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkserver/ProxyTypeAdapter.kt
new file mode 100644
index 0000000000000000000000000000000000000000..378884151c04c7a62e97868ebd0911d91139ab28
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkserver/ProxyTypeAdapter.kt
@@ -0,0 +1,67 @@
+package de.kuschku.quasseldroid.ui.coresettings.networkserver
+
+import android.support.v7.widget.RecyclerView
+import android.support.v7.widget.ThemedSpinnerAdapter
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import butterknife.BindView
+import butterknife.ButterKnife
+import de.kuschku.quasseldroid.R
+import de.kuschku.quasseldroid.util.ui.ContextThemeWrapper
+import de.kuschku.quasseldroid.util.ui.RecyclerSpinnerAdapter
+
+class ProxyTypeAdapter(val data: List<ProxyTypeItem>) :
+  RecyclerSpinnerAdapter<ProxyTypeAdapter.ProxyTypeViewHolder>(),
+  ThemedSpinnerAdapter {
+
+  override fun isEmpty() = data.isEmpty()
+
+  override fun onBindViewHolder(holder: ProxyTypeViewHolder, position: Int) =
+    holder.bind(getItem(position))
+
+  override fun onCreateViewHolder(parent: ViewGroup, dropDown: Boolean)
+    : ProxyTypeViewHolder {
+    val inflater = LayoutInflater.from(
+      if (dropDown) ContextThemeWrapper(parent.context, dropDownViewTheme)
+      else parent.context
+    )
+    return ProxyTypeViewHolder(
+      inflater.inflate(R.layout.widget_spinner_item_toolbar, parent, false)
+    )
+  }
+
+  override fun getItem(position: Int) = data[position]
+
+  override fun getItemId(position: Int) = getItem(position).value.value.toLong()
+
+  override fun hasStableIds() = true
+
+  override fun getCount() = data.size
+
+  fun indexOf(value: Int): Int? {
+    for ((key, item) in data.withIndex()) {
+      if (item.value.value == value) {
+        return key
+      }
+    }
+    return null
+  }
+
+  class ProxyTypeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+    @BindView(android.R.id.text1)
+    lateinit var text: TextView
+
+    init {
+      ButterKnife.bind(this, itemView)
+    }
+
+    fun bind(activity: ProxyTypeItem?) {
+      activity?.let {
+        text.setText(it.name)
+      }
+    }
+  }
+}
+
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkserver/ProxyTypeItem.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkserver/ProxyTypeItem.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b2f7d8ecd2fbe7feeb4e022f19468acb16b126b3
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkserver/ProxyTypeItem.kt
@@ -0,0 +1,6 @@
+package de.kuschku.quasseldroid.ui.coresettings.networkserver
+
+import android.support.annotation.StringRes
+import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
+
+data class ProxyTypeItem(val value: INetwork.ProxyType, @StringRes val name: Int)
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ui/SettingsActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/util/ui/SettingsActivity.kt
index f3ec01f76d8655588f5ee95ad4ed61c3fa81f393..86ac9b86f203dfce42f7dbc0225c30550efea83d 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/ui/SettingsActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/ui/SettingsActivity.kt
@@ -2,7 +2,9 @@ package de.kuschku.quasseldroid.util.ui
 
 import android.os.Bundle
 import android.support.v4.app.Fragment
+import android.support.v4.app.NavUtils
 import android.support.v7.widget.Toolbar
+import android.view.MenuItem
 import butterknife.BindView
 import butterknife.ButterKnife
 import com.afollestad.materialdialogs.MaterialDialog
@@ -39,7 +41,7 @@ abstract class SettingsActivity(private val fragment: Fragment? = null) : Servic
     this.changeable = fragment as? SettingsFragment.Changeable
   }
 
-  override fun onBackPressed() {
+  private fun shouldNavigateAway(callback: () -> Unit) {
     val changeable = this.changeable
     if (changeable?.hasChanged() == true) {
       MaterialDialog.Builder(this)
@@ -50,10 +52,28 @@ abstract class SettingsActivity(private val fragment: Fragment? = null) : Servic
         .backgroundColorAttr(R.attr.colorBackgroundCard)
         .contentColorAttr(R.attr.colorTextPrimary)
         .onPositive { _, _ ->
-          super.onBackPressed()
+          callback()
         }
         .build()
         .show()
-    } else super.onBackPressed()
+    } else callback()
+  }
+
+  override fun onBackPressed() = shouldNavigateAway {
+    super.onBackPressed()
+  }
+
+  override fun onOptionsItemSelected(item: MenuItem?) = when (item?.itemId) {
+    android.R.id.home -> {
+      shouldNavigateAway {
+        if (supportParentActivityIntent == null) {
+          super.onBackPressed()
+        } else {
+          NavUtils.navigateUpFromSameTask(this)
+        }
+      }
+      true
+    }
+    else              -> super.onOptionsItemSelected(item)
   }
 }
diff --git a/app/src/main/res/layout/settings_network.xml b/app/src/main/res/layout/settings_network.xml
index 4154566b732902c0a7a0a3db53eb365e8795ea20..ff2f3b624d78f19fabe93d217cf6aebcf27fd9af 100644
--- a/app/src/main/res/layout/settings_network.xml
+++ b/app/src/main/res/layout/settings_network.xml
@@ -200,6 +200,7 @@
         <android.support.design.widget.TextInputEditText
           android:id="@+id/perform"
           style="@style/Widget.CoreSettings.EditText"
+          android:inputType="textMultiLine"
           tools:text="/mode -x" />
       </android.support.design.widget.TextInputLayout>
 
diff --git a/app/src/main/res/layout/settings_networkserver.xml b/app/src/main/res/layout/settings_networkserver.xml
new file mode 100644
index 0000000000000000000000000000000000000000..40fae516856d24a92d5e36aedbb5604b24e19101
--- /dev/null
+++ b/app/src/main/res/layout/settings_networkserver.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+  xmlns:app="http://schemas.android.com/apk/res-auto"
+  xmlns:tools="http://schemas.android.com/tools"
+  android:layout_width="match_parent"
+  android:layout_height="match_parent"
+  android:scrollbars="vertical">
+
+  <LinearLayout style="@style/Widget.CoreSettings.Wrapper">
+
+    <LinearLayout
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      android:minHeight="48dp">
+
+      <android.support.v7.widget.AppCompatImageView
+        style="@style/Widget.CoreSettings.PrimaryItemIcon"
+        app:srcCompat="@drawable/ic_server_network" />
+
+      <TextView
+        style="@style/Widget.CoreSettings.PrimaryItemSwitch"
+        android:text="@string/settings_networkserver_connection" />
+    </LinearLayout>
+
+    <LinearLayout
+      style="@style/Widget.CoreSettings.DependentGroup"
+      android:visibility="visible">
+
+      <android.support.design.widget.TextInputLayout
+        style="@style/Widget.CoreSettings.EditTextLayout"
+        android:hint="@string/settings_networkserver_host">
+
+        <android.support.design.widget.TextInputEditText
+          android:id="@+id/host"
+          style="@style/Widget.CoreSettings.EditText"
+          tools:text="irc.freenode.org" />
+      </android.support.design.widget.TextInputLayout>
+
+      <android.support.design.widget.TextInputLayout
+        style="@style/Widget.CoreSettings.EditTextLayout"
+        android:hint="@string/settings_networkserver_port">
+
+        <android.support.design.widget.TextInputEditText
+          android:id="@+id/port"
+          style="@style/Widget.CoreSettings.EditText"
+          android:inputType="number"
+          tools:text="6667" />
+      </android.support.design.widget.TextInputLayout>
+
+      <android.support.v7.widget.SwitchCompat
+        android:id="@+id/ssl_enabled"
+        style="@style/Widget.CoreSettings.PrimaryItemSwitch"
+        android:text="@string/settings_networkserver_ssl_enabled" />
+
+      <android.support.v7.widget.SwitchCompat
+        android:id="@+id/ssl_verify"
+        style="@style/Widget.CoreSettings.PrimaryItemSwitch"
+        android:text="@string/settings_networkserver_ssl_verify" />
+
+      <android.support.design.widget.TextInputLayout
+        style="@style/Widget.CoreSettings.EditTextLayout"
+        android:hint="@string/settings_networkserver_password"
+        app:passwordToggleEnabled="true">
+
+        <android.support.design.widget.TextInputEditText
+          android:id="@+id/password"
+          style="@style/Widget.CoreSettings.EditText"
+          android:inputType="textPassword"
+          tools:text="thisisasecurepassword" />
+      </android.support.design.widget.TextInputLayout>
+    </LinearLayout>
+
+    <LinearLayout
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      android:minHeight="48dp">
+
+      <android.support.v7.widget.AppCompatImageView
+        style="@style/Widget.CoreSettings.PrimaryItemIcon"
+        app:srcCompat="@drawable/ic_settings" />
+
+      <android.support.v7.widget.SwitchCompat
+        android:id="@+id/proxy_enabled"
+        style="@style/Widget.CoreSettings.PrimaryItemSwitch"
+        android:text="@string/settings_networkserver_proxy_enabled" />
+    </LinearLayout>
+
+    <LinearLayout
+      android:id="@+id/proxy_group"
+      style="@style/Widget.CoreSettings.DependentGroup"
+      tools:visibility="visible">
+
+      <TextView
+        style="@style/Widget.CoreSettings.EditTextHeader"
+        android:text="@string/settings_networkserver_proxy_type" />
+
+      <Spinner
+        android:id="@+id/proxy_type"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        tools:listitem="@layout/widget_spinner_item_toolbar" />
+
+      <android.support.design.widget.TextInputLayout
+        style="@style/Widget.CoreSettings.EditTextLayout"
+        android:hint="@string/settings_networkserver_proxy_host">
+
+        <android.support.design.widget.TextInputEditText
+          android:id="@+id/proxy_host"
+          style="@style/Widget.CoreSettings.EditText"
+          tools:text="localhost" />
+      </android.support.design.widget.TextInputLayout>
+
+      <android.support.design.widget.TextInputLayout
+        style="@style/Widget.CoreSettings.EditTextLayout"
+        android:hint="@string/settings_networkserver_proxy_port">
+
+        <android.support.design.widget.TextInputEditText
+          android:id="@+id/proxy_port"
+          style="@style/Widget.CoreSettings.EditText"
+          android:inputType="number"
+          tools:text="8080" />
+      </android.support.design.widget.TextInputLayout>
+
+      <android.support.design.widget.TextInputLayout
+        style="@style/Widget.CoreSettings.EditTextLayout"
+        android:hint="@string/settings_networkserver_proxy_user">
+
+        <android.support.design.widget.TextInputEditText
+          android:id="@+id/proxy_user"
+          style="@style/Widget.CoreSettings.EditText"
+          tools:text="justjanne" />
+      </android.support.design.widget.TextInputLayout>
+
+      <android.support.design.widget.TextInputLayout
+        style="@style/Widget.CoreSettings.EditTextLayout"
+        android:hint="@string/settings_networkserver_proxy_pass"
+        app:passwordToggleEnabled="true">
+
+        <android.support.design.widget.TextInputEditText
+          android:id="@+id/proxy_pass"
+          style="@style/Widget.CoreSettings.EditText"
+          android:inputType="textPassword"
+          tools:text="thisisasecurepassword" />
+      </android.support.design.widget.TextInputLayout>
+    </LinearLayout>
+  </LinearLayout>
+</android.support.v4.widget.NestedScrollView>
diff --git a/app/src/main/res/values-de/strings_settings.xml b/app/src/main/res/values-de/strings_settings.xml
index a19c1bbcf6dafda6ec1f54abecb4eb242fa27f66..1cf6b7cd1b088e99112d1d6a59fb508bce2e5e8f 100644
--- a/app/src/main/res/values-de/strings_settings.xml
+++ b/app/src/main/res/values-de/strings_settings.xml
@@ -14,16 +14,32 @@
   <string name="settings_network_perform">Befehle</string>
   <string name="settings_network_rejoin_channels">Beim Verbinden Kanäle wieder betreten</string>
   <string name="settings_network_autoreconnect_enabled">Automatisches Wiederverbinden</string>
-  <string name="settings_network_autoreconnect_interval">Zeit zwischen Verbindungsversuchen</string>
+  <string name="settings_network_autoreconnect_interval">Intervall</string>
   <string name="settings_network_autoreconnect_interval_unit">Sekunden</string>
   <string name="settings_network_autoreconnect_attempts">Maximale Anzahl an Verbindungsversuchen</string>
   <string name="settings_network_autoreconnect_unlimited">Unbegrenzt</string>
   <string name="settings_network_customratelimits_enabled">Benutzerdefinierte Nachrichtenrate</string>
   <string name="settings_network_customratelimits_burstsize">Anzahl Nachrichten pro Übertragung</string>
   <string name="settings_network_customratelimits_unlimited">Unbegrenzt</string>
-  <string name="settings_network_customratelimits_delay">Zeit zwischen Übertragungen</string>
+  <string name="settings_network_customratelimits_delay">Verzögerung</string>
   <string name="settings_network_customratelimits_interval_unit">Sekunden</string>
 
+  <string name="settings_networkserver_title">Netzwerk-Server</string>
+  <string name="settings_networkserver_connection">Verbindung</string>
+  <string name="settings_networkserver_host">Adresse</string>
+  <string name="settings_networkserver_port">Port</string>
+  <string name="settings_networkserver_ssl_enabled">SSL verwenden</string>
+  <string name="settings_networkserver_ssl_verify">SSL verifizieren</string>
+  <string name="settings_networkserver_password">Passwort</string>
+  <string name="settings_networkserver_proxy_enabled">Proxy verwenden</string>
+  <string name="settings_networkserver_proxy_type">Typ</string>
+  <string name="settings_networkserver_proxy_type_http">HTTP</string>
+  <string name="settings_networkserver_proxy_type_socks5">SOCKS 5</string>
+  <string name="settings_networkserver_proxy_host">Adresse</string>
+  <string name="settings_networkserver_proxy_port">Port</string>
+  <string name="settings_networkserver_proxy_user">Benutzername</string>
+  <string name="settings_networkserver_proxy_pass">Passwort</string>
+
   <string name="settings_identities_title">Identitäten</string>
   <string name="settings_identity_title">Identität</string>
   <string name="settings_identity_names">Namen</string>
diff --git a/app/src/main/res/values/strings_settings.xml b/app/src/main/res/values/strings_settings.xml
index 6a69c073622df04242069df04cb9d53423a1b7a3..b4ec6650922998d00a9a8ce899dbbb27814840b5 100644
--- a/app/src/main/res/values/strings_settings.xml
+++ b/app/src/main/res/values/strings_settings.xml
@@ -24,6 +24,22 @@
   <string name="settings_network_customratelimits_delay">Delay</string>
   <string name="settings_network_customratelimits_interval_unit">seconds</string>
 
+  <string name="settings_networkserver_title">Network Server</string>
+  <string name="settings_networkserver_connection">Connection</string>
+  <string name="settings_networkserver_host">Host</string>
+  <string name="settings_networkserver_port">Port</string>
+  <string name="settings_networkserver_ssl_enabled">Use SSL</string>
+  <string name="settings_networkserver_ssl_verify">Verify SSL</string>
+  <string name="settings_networkserver_password">Password</string>
+  <string name="settings_networkserver_proxy_enabled">Use Proxy</string>
+  <string name="settings_networkserver_proxy_type">Type</string>
+  <string name="settings_networkserver_proxy_type_http">HTTP</string>
+  <string name="settings_networkserver_proxy_type_socks5">SOCKS 5</string>
+  <string name="settings_networkserver_proxy_host">Host</string>
+  <string name="settings_networkserver_proxy_port">Port</string>
+  <string name="settings_networkserver_proxy_user">Username</string>
+  <string name="settings_networkserver_proxy_pass">Password</string>
+
   <string name="settings_identities_title">Identities</string>
   <string name="settings_identity_title">Identity</string>
   <string name="settings_identity_names">Names</string>
diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/VariantSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/VariantSerializer.kt
index c55df4dac28839f8bf691a5bfb08045cc3cfe06c..81bef0d9423b84b14a229d79e1ef65db39a077c7 100644
--- a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/VariantSerializer.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/VariantSerializer.kt
@@ -10,7 +10,7 @@ object VariantSerializer : Serializer<QVariant_> {
     IntSerializer.serialize(buffer, data.type.id, features)
     BoolSerializer.serialize(buffer, false, features)
     if (data is QVariant.Custom && data.type == Type.UserType) {
-      StringSerializer.C.serialize(buffer, data.qtype.name, features)
+      StringSerializer.C.serialize(buffer, data.qtype.typeName, features)
     }
     (data.serializer as Serializer<Any?>).serialize(buffer, data.data, features)
   }
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt
index b44f151012a2dc5a947a325d5ef3d34665ba3061..6e771258a6410ce04156a2addf38e617b137d81f 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt
@@ -453,13 +453,15 @@ class Network constructor(
   }
 
   override fun setServerList(serverList: QVariantList) {
-    val actualServerList = serverList.map {
+    setActualServerList(serverList.map {
       it.valueOrThrow<QVariantMap>()
-    }.map(Server.Companion::fromVariantMap)
+    }.map(Server.Companion::fromVariantMap))
+  }
 
-    if (_serverList == actualServerList)
+  fun setActualServerList(serverList: List<INetwork.Server>) {
+    if (_serverList == serverList)
       return
-    _serverList = actualServerList
+    _serverList = serverList
   }
 
   override fun setUseRandomServer(randomServer: Boolean) {
@@ -670,7 +672,7 @@ class Network constructor(
   }.toList()
 
   override fun initServerList(): QVariantList = _serverList.map {
-    QVariant.of(it, QType.Network_Server)
+    QVariant.of(it.toVariantMap(), QType.Network_Server)
   }.toList()
 
   override fun initIrcUsersAndChannels(): QVariantMap {
@@ -854,6 +856,12 @@ class Network constructor(
     live_ircChannels.onNext(_ircChannels)
   }
 
+  fun copy(): Network {
+    val identity = Network(this.networkId(), SignalProxy.NULL)
+    identity.fromVariantMap(this.toVariantMap())
+    return identity
+  }
+
   private var _networkId: NetworkId = networkId
     set(value) {
       field = value
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt
index af3653acd32c6e6fac8b1fbec967d3d36fa83d7e..c520ec73827287d51009f1166843c1b192773ec3 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt
@@ -41,10 +41,10 @@ class RpcHandler(
     backlogStorage.storeMessages(session, message)
   }
 
-  override fun createIdentity(identity: QVariantMap, additional: QVariantMap) =
+  override fun createIdentity(identity: Identity, additional: QVariantMap) =
     RPC(
       "2createIdentity(Identity,QVariantMap)",
-      ARG(identity, QType.Identity),
+      ARG(identity.toVariantMap(), QType.Identity),
       ARG(additional, Type.QVariantMap)
     )
 
@@ -57,7 +57,7 @@ class RpcHandler(
   override fun createNetwork(networkInfo: INetwork.NetworkInfo, channels: List<String>) =
     RPC(
       "2createNetwork(NetworkInfo,QStringList)",
-      ARG(networkInfo, QType.NetworkInfo),
+      ARG(networkInfo.toVariantMap(), QType.NetworkInfo),
       ARG(channels, Type.QStringList)
     )
 
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetwork.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetwork.kt
index 8e0a302c08e348910d2db28a5acc51e6bc61b6b0..889cad37716109fac13c8c2ce70b4e5879d93c90 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetwork.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetwork.kt
@@ -3,8 +3,11 @@ package de.kuschku.libquassel.quassel.syncables.interfaces
 import de.kuschku.libquassel.annotations.Slot
 import de.kuschku.libquassel.annotations.Syncable
 import de.kuschku.libquassel.protocol.*
+import de.kuschku.libquassel.protocol.primitive.serializer.StringSerializer
 import de.kuschku.libquassel.util.flag.Flag
 import de.kuschku.libquassel.util.flag.Flags
+import de.kuschku.libquassel.util.helpers.serializeString
+import java.io.Serializable
 import java.nio.ByteBuffer
 
 @Syncable(name = "Network")
@@ -220,7 +223,7 @@ interface INetwork : ISyncableObject {
     val proxyPort: UInt = 8080,
     val proxyUser: String = "",
     val proxyPass: String = ""
-  ) {
+  ) : Serializable {
     fun toVariantMap(): QVariantMap = mapOf(
       "Host" to QVariant.of(host, Type.QString),
       "Port" to QVariant.of(port, Type.UInt),
@@ -229,7 +232,7 @@ interface INetwork : ISyncableObject {
       "sslVerify" to QVariant.of(sslVerify, Type.Bool),
       "sslVersion" to QVariant.of(sslVersion, Type.Int),
       "UseProxy" to QVariant.of(useProxy, Type.Bool),
-      "ProxyType" to QVariant.of(proxyType, Type.Bool),
+      "ProxyType" to QVariant.of(proxyType, Type.Int),
       "ProxyHost" to QVariant.of(proxyHost, Type.QString),
       "ProxyPort" to QVariant.of(proxyPort, Type.UInt),
       "ProxyUser" to QVariant.of(proxyUser, Type.QString),
@@ -295,7 +298,73 @@ interface INetwork : ISyncableObject {
     var messageRateBurstSize: Int = 0,
     var messageRateDelay: Int = 0,
     var unlimitedMessageRate: Boolean = false
-  )
+  ) {
+    fun toVariantMap() = mapOf(
+      "NetworkId" to QVariant.of(networkId, QType.NetworkId),
+      "NetworkName" to QVariant.of(networkName, Type.QString),
+      "Identity" to QVariant.of(identity, QType.IdentityId),
+      "UseCustomEncodings" to QVariant.of(useCustomEncodings, Type.Bool),
+      "CodecForServer" to QVariant.of(
+        codecForServer.serializeString(StringSerializer.UTF8), Type.QByteArray
+      ),
+      "CodecForEncoding" to QVariant.of(
+        codecForEncoding.serializeString(StringSerializer.UTF8), Type.QByteArray
+      ),
+      "CodecForDecoding" to QVariant.of(
+        codecForDecoding.serializeString(StringSerializer.UTF8), Type.QByteArray
+      ),
+      "ServerList" to QVariant.of(serverList.map {
+        QVariant.of(it.toVariantMap(), QType.Network_Server)
+      }, Type.QVariantList),
+      "UseRandomServer" to QVariant.of(useRandomServer, Type.Bool),
+      "Perform" to QVariant.of(perform, Type.QStringList),
+      "UseAutoIdentify" to QVariant.of(useAutoIdentify, Type.Bool),
+      "AutoIdentifyService" to QVariant.of(autoIdentifyService, Type.QString),
+      "AutoIdentifyPassword" to QVariant.of(autoIdentifyPassword, Type.QString),
+      "UseSasl" to QVariant.of(useSasl, Type.Bool),
+      "SaslAccount" to QVariant.of(saslAccount, Type.QString),
+      "SaslPassword" to QVariant.of(saslPassword, Type.QString),
+      "UseAutoReconnect" to QVariant.of(useAutoReconnect, Type.Bool),
+      "AutoReconnectInterval" to QVariant.of(autoReconnectInterval, Type.UInt),
+      "AutoReconnectRetries" to QVariant.of(autoReconnectRetries, Type.Int),
+      "UnlimitedReconnectRetries" to QVariant.of(unlimitedReconnectRetries, Type.Bool),
+      "RejoinChannels" to QVariant.of(rejoinChannels, Type.Bool),
+      "UseCustomMessageRate" to QVariant.of(useCustomMessageRate, Type.Bool),
+      "MessageRateBurstSize" to QVariant.of(messageRateBurstSize, Type.UInt),
+      "MessageRateDelay" to QVariant.of(messageRateDelay, Type.UInt),
+      "UnlimitedMessageRate" to QVariant.of(unlimitedMessageRate, Type.Bool)
+    )
+
+    fun fromVariantMap(map: QVariantMap) {
+      networkId = map["NetworkId"].value(networkId)
+      networkName = map["NetworkName"].value(networkName)
+      identity = map["Identity"].value(identity)
+      useCustomEncodings = map["UseCustomEncodings"].value(useCustomEncodings)
+      codecForServer = map["CodecForServer"].value(codecForServer)
+      codecForEncoding = map["CodecForEncoding"].value(codecForEncoding)
+      codecForDecoding = map["CodecForDecoding"].value(codecForDecoding)
+      serverList = map["ServerList"].value(emptyList<QVariant_>()).map {
+        INetwork.Server.fromVariantMap(it.value(emptyMap()))
+      }
+      useRandomServer = map["UseRandomServer"].value(useRandomServer)
+      perform = map["Perform"].value(perform)
+      useAutoIdentify = map["UseAutoIdentify"].value(useAutoIdentify)
+      autoIdentifyService = map["AutoIdentifyService"].value(autoIdentifyService)
+      autoIdentifyPassword = map["AutoIdentifyPassword"].value(autoIdentifyPassword)
+      useSasl = map["UseSasl"].value(useSasl)
+      saslAccount = map["SaslAccount"].value(saslAccount)
+      saslPassword = map["SaslPassword"].value(saslPassword)
+      useAutoReconnect = map["UseAutoReconnect"].value(useAutoReconnect)
+      autoReconnectInterval = map["AutoReconnectInterval"].value(autoReconnectInterval)
+      autoReconnectRetries = map["AutoReconnectRetries"].value(autoReconnectRetries)
+      unlimitedReconnectRetries = map["UnlimitedReconnectRetries"].value(unlimitedReconnectRetries)
+      rejoinChannels = map["RejoinChannels"].value(rejoinChannels)
+      useCustomMessageRate = map["UseCustomMessageRate"].value(useCustomMessageRate)
+      messageRateBurstSize = map["MessageRateBurstSize"].value(messageRateBurstSize)
+      messageRateDelay = map["MessageRateDelay"].value(messageRateDelay)
+      unlimitedMessageRate = map["UnlimitedMessageRate"].value(unlimitedMessageRate)
+    }
+  }
 
   /**
    * IRCv3 capability names and values
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IRpcHandler.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IRpcHandler.kt
index e33a48a000b967f7208f362875006b36197f945e..46116ae6e778cfb2bb9e4a264204ccd5a4fe0b01 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IRpcHandler.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IRpcHandler.kt
@@ -7,6 +7,7 @@ import de.kuschku.libquassel.protocol.Message
 import de.kuschku.libquassel.protocol.NetworkId
 import de.kuschku.libquassel.protocol.QVariantMap
 import de.kuschku.libquassel.quassel.BufferInfo
+import de.kuschku.libquassel.quassel.syncables.Identity
 import de.kuschku.libquassel.session.Session
 import java.nio.ByteBuffer
 
@@ -44,9 +45,9 @@ interface IRpcHandler {
   @Slot("2disconnectFromCore()")
   fun disconnectFromCore()
 
-  fun createIdentity(identity: QVariantMap, additional: QVariantMap)
+  fun createIdentity(identity: Identity, additional: QVariantMap)
   fun removeIdentity(identityId: IdentityId)
-  fun createNetwork(networkInfo: INetwork.NetworkInfo, channels: List<String>)
+  fun createNetwork(networkInfo: INetwork.NetworkInfo, channels: List<String> = emptyList())
   fun removeNetwork(networkId: NetworkId)
   fun changePassword(peerPtr: Long, user: String, old: String, new: String)
   fun requestKickClient(id: Int)
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/Optional.kt b/lib/src/main/java/de/kuschku/libquassel/util/Optional.kt
index 390581dccb365cb615a6db858e60553660713001..428fd9bdcfcaf51e6a3783904d713677dd606bbc 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/Optional.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/Optional.kt
@@ -2,13 +2,13 @@ package de.kuschku.libquassel.util
 
 import java.io.Serializable
 
-interface Optional<T> : Serializable {
+interface Optional<T : Any> : Serializable {
   fun get(): T
   fun isPresent(): Boolean
   fun ifPresent(consumer: (T) -> Unit)
   fun filter(predicate: (T) -> Boolean): Optional<T>
-  fun <U> map(mapper: (T) -> U): Optional<U>
-  fun <U> flatMap(mapper: (T) -> Optional<U>): Optional<U>
+  fun <U : Any> map(mapper: (T) -> U): Optional<U>
+  fun <U : Any> flatMap(mapper: (T) -> Optional<U>): Optional<U>
   fun orElse(other: T): T
   fun orNull(): T?
   fun <X : Throwable> orElseThrow(supplier: () -> X): T
@@ -16,13 +16,13 @@ interface Optional<T> : Serializable {
   override fun hashCode(): Int
   override fun toString(): String
 
-  private class Present<T>(private val value: T) : Optional<T> {
+  private class Present<T : Any>(private val value: T) : Optional<T> {
     override fun get() = value
     override fun isPresent() = true
     override fun ifPresent(consumer: (T) -> Unit) = consumer(value)
     override fun filter(predicate: (T) -> Boolean) = if (predicate(value)) this else empty<T>()
-    override fun <U> map(mapper: (T) -> U) = ofNullable(mapper(value))
-    override fun <U> flatMap(mapper: (T) -> Optional<U>) = mapper(value)
+    override fun <U : Any> map(mapper: (T) -> U) = ofNullable(mapper(value))
+    override fun <U : Any> flatMap(mapper: (T) -> Optional<U>) = mapper(value)
     override fun orElse(other: T) = value
     override fun orNull(): T? = value
     override fun <X : Throwable> orElseThrow(supplier: () -> X) = value
@@ -31,13 +31,13 @@ interface Optional<T> : Serializable {
     override fun toString() = "Optional[$value]"
   }
 
-  private class Absent<T> : Optional<T> {
+  private class Absent<T : Any> : Optional<T> {
     override fun get() = throw NoSuchElementException("No value present")
     override fun isPresent() = false
     override fun ifPresent(consumer: (T) -> Unit) = Unit
     override fun filter(predicate: (T) -> Boolean) = this
-    override fun <U> map(mapper: (T) -> U) = empty<U>()
-    override fun <U> flatMap(mapper: (T) -> Optional<U>) = empty<U>()
+    override fun <U : Any> map(mapper: (T) -> U) = empty<U>()
+    override fun <U : Any> flatMap(mapper: (T) -> Optional<U>) = empty<U>()
     override fun orElse(other: T) = other
     override fun orNull(): T? = null
     override fun <X : Throwable> orElseThrow(supplier: () -> X) = throw supplier()
@@ -47,12 +47,12 @@ interface Optional<T> : Serializable {
   }
 
   companion object {
-    private val absent = Absent<Any?>()
+    private val absent = Absent<Any>()
 
     @Suppress("UNCHECKED_CAST")
-    fun <T> empty(): Optional<T> = absent as Absent<T>
+    fun <T : Any> empty(): Optional<T> = absent as Absent<T>
 
-    fun <T> of(value: T): Optional<T> = Present(value)
-    fun <T> ofNullable(value: T?): Optional<T> = value?.let(::Present) ?: empty()
+    fun <T : Any> of(value: T): Optional<T> = Present(value)
+    fun <T : Any> ofNullable(value: T?): Optional<T> = value?.let(::Present) ?: empty()
   }
-}
\ No newline at end of file
+}
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/helpers/ObservableHelper.kt b/lib/src/main/java/de/kuschku/libquassel/util/helpers/ObservableHelper.kt
index 656e6fa4c5695d2efe3355fb36ca8aa1342ff99a..4843ccfa9e2807e325d7239c70c616cd389995d7 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/helpers/ObservableHelper.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/helpers/ObservableHelper.kt
@@ -9,21 +9,20 @@ fun <T> Observable<T>.or(default: T): T = try {
   default
 }
 
-val <T> Observable<T>.value
+val <T : Any> Observable<T>.value
   get() = this.map { Optional.of(it) }.blockingMostRecent(Optional.empty()).firstOrNull()?.orNull()
 
-fun <T, U> Observable<Optional<T>>.mapMap(mapper: (T) -> U): Observable<Optional<U>> = map {
-  it.map(mapper)
-}
+fun <T : Any, U : Any> Observable<Optional<T>>.mapMap(mapper: (T) -> U): Observable<Optional<U>> =
+  map { it.map(mapper) }
 
-fun <T, U> Observable<Optional<T>>.mapMapNullable(
+fun <T : Any, U : Any> Observable<Optional<T>>.mapMapNullable(
   mapper: (T) -> U?): Observable<Optional<U>> = map {
   it.flatMap {
     Optional.ofNullable(mapper(it))
   }
 }
 
-fun <T, U> Observable<Optional<T>>.mapSwitchMap(
+fun <T : Any, U : Any> Observable<Optional<T>>.mapSwitchMap(
   mapper: (T) -> Observable<U>): Observable<Optional<U>> = switchMap {
   if (it.isPresent()) {
     it.map(mapper).get().map { Optional.of(it) }
@@ -32,7 +31,7 @@ fun <T, U> Observable<Optional<T>>.mapSwitchMap(
   }
 }
 
-fun <T, U> Observable<Optional<T>>.mapSwitchMapEmpty(
+fun <T : Any, U : Any> Observable<Optional<T>>.mapSwitchMapEmpty(
   mapper: (T) -> Observable<U>): Observable<U> = switchMap {
   if (it.isPresent()) {
     it.map(mapper).get()
@@ -41,11 +40,11 @@ fun <T, U> Observable<Optional<T>>.mapSwitchMapEmpty(
   }
 }
 
-fun <T, U> Observable<Optional<T>>.flatMapSwitchMap(
+fun <T : Any, U : Any> Observable<Optional<T>>.flatMapSwitchMap(
   mapper: (T) -> Observable<Optional<U>>): Observable<Optional<U>> = switchMap {
   it.map(mapper).orElse(Observable.just(Optional.empty()))
 }
 
-fun <T> Observable<Optional<T>>.mapOrElse(orElse: T): Observable<T> = map {
+fun <T : Any> Observable<Optional<T>>.mapOrElse(orElse: T): Observable<T> = map {
   it.orElse(orElse)
-}
\ No newline at end of file
+}
diff --git a/lib/src/test/java/de/kuschku/libquassel/ConnectionUnitTest.kt b/lib/src/test/java/de/kuschku/libquassel/ConnectionUnitTest.kt
index 8d7514cb88f3ef8f90f70eb589d6c9c311c251f6..a1292b3b6dce4bb2f0bee608e7bf7589bd5c7e18 100644
--- a/lib/src/test/java/de/kuschku/libquassel/ConnectionUnitTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/ConnectionUnitTest.kt
@@ -3,7 +3,9 @@ package de.kuschku.libquassel
 import de.kuschku.libquassel.protocol.*
 import de.kuschku.libquassel.quassel.ProtocolFeature
 import de.kuschku.libquassel.quassel.QuasselFeatures
+import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
 import de.kuschku.libquassel.session.BacklogStorage
+import de.kuschku.libquassel.session.ConnectionState
 import de.kuschku.libquassel.session.Session
 import de.kuschku.libquassel.session.SocketAddress
 import de.kuschku.libquassel.util.compatibility.reference.JavaHandlerService
@@ -46,12 +48,31 @@ class ConnectionUnitTest {
 
       override fun getAcceptedIssuers(): Array<X509Certificate> = emptyArray()
     }, SocketAddress(host, port), JavaHandlerService(), object : BacklogStorage {
-      override fun storeMessages(vararg messages: Message, initialLoad: Boolean) = Unit
-      override fun storeMessages(messages: Iterable<Message>, initialLoad: Boolean) = Unit
+      override fun updateIgnoreRules(session: Session) = Unit
+      override fun storeMessages(session: Session, vararg messages: Message,
+                                 initialLoad: Boolean) = Unit
+
+      override fun storeMessages(session: Session, messages: Iterable<Message>,
+                                 initialLoad: Boolean) = Unit
+
       override fun clearMessages(bufferId: BufferId, idRange: IntRange) = Unit
       override fun clearMessages(bufferId: BufferId) = Unit
       override fun clearMessages() = Unit
     }, user to pass, {}, {})
+    session.state.subscribe {
+      if (it == ConnectionState.CONNECTED) {
+        session.rpcHandler?.createNetwork(INetwork.NetworkInfo(
+          networkName = "QuakeNet",
+          identity = session.identities.values.firstOrNull()?.id()!!,
+          serverList = listOf(
+            INetwork.Server(
+              host = "irc.quakenet.org",
+              port = 6667
+            )
+          )
+        ), emptyList())
+      }
+    }
     session.join()
   }
 }
diff --git a/lib/src/test/java/de/kuschku/libquassel/SerializerUnitTest.kt b/lib/src/test/java/de/kuschku/libquassel/SerializerUnitTest.kt
index 8f68cdbab3ebd2152a4378980015f35bb72d361e..766c4517a19a84f9805083405b1f3a46c3a40605 100644
--- a/lib/src/test/java/de/kuschku/libquassel/SerializerUnitTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/SerializerUnitTest.kt
@@ -2,6 +2,7 @@ package de.kuschku.libquassel
 
 import de.kuschku.libquassel.protocol.primitive.serializer.*
 import de.kuschku.libquassel.quassel.QuasselFeatures
+import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
 import de.kuschku.libquassel.util.nio.ChainedByteBuffer
 import org.junit.Assert.assertArrayEquals
 import org.junit.Assert.assertEquals
@@ -103,6 +104,30 @@ class SerializerUnitTest {
     assertEquals("Test", roundTrip(StringSerializer.C, "Test"))
   }
 
+  @Test
+  fun networkInfoSerializer() {
+    val info = INetwork.NetworkInfo(
+      networkName = "QuakeNet",
+      identity = 5,
+      serverList = listOf(
+        INetwork.Server(
+          host = "irc.quakenet.org",
+          port = 6667
+        )
+      )
+    )
+    val info2 = info.copy()
+    info2.fromVariantMap(roundTrip(VariantMapSerializer, info.toVariantMap()))
+    assertEquals(info, info2)
+  }
+
+  @Test
+  fun captureSerializer() {
+    val data = byteArrayOf(
+
+    )
+  }
+
   companion object {
     fun <T> roundTrip(serializer: Serializer<T>, value: T,
                       features: QuasselFeatures = QuasselFeatures.all()): T {