diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 7643783a82f60b3b876fe58a9314fb50520df486..f6631329795d70f75db972aac4a1f206dfdaf754 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -1,6 +1,11 @@
 <component name="ProjectCodeStyleConfiguration">
   <code_scheme name="Project" version="173">
     <JetCodeStyleSettings>
+      <option name="PACKAGES_TO_USE_STAR_IMPORTS">
+        <value />
+      </option>
+      <option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
+      <option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
       <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
     </JetCodeStyleSettings>
     <codeStyleSettings language="XML">
diff --git a/mailbox/build.gradle b/mailbox/build.gradle
index f6fe2964fe6b7a4ec8d82c172f1348161bf1dd29..1e313bb4db1b61bc056b0d14b851689cfa8dcc5d 100644
--- a/mailbox/build.gradle
+++ b/mailbox/build.gradle
@@ -16,6 +16,7 @@ android {
         targetSdkVersion 30
         versionCode 1
         versionName "1.0"
+        multiDexEnabled true // only needed when minSdkVersion < 21
 
         testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
     }
@@ -29,16 +30,23 @@ android {
     compileOptions {
         sourceCompatibility JavaVersion.VERSION_1_8
         targetCompatibility JavaVersion.VERSION_1_8
+        coreLibraryDesugaringEnabled true
     }
     kotlinOptions {
         jvmTarget = '1.8'
     }
+    packagingOptions {
+        exclude 'META-INF/*'
+        // Due to https://github.com/Kotlin/kotlinx.coroutines/issues/2023
+        exclude 'META-INF/licenses/*'
+        exclude '**/attach_hotspot_windows.dll'
+    }
 }
 
 dependencies {
     implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
     implementation 'androidx.appcompat:appcompat:1.3.1'
-    implementation "androidx.activity:activity-ktx:1.2.4"
+    implementation "androidx.activity:activity-ktx:1.3.0"
     implementation "androidx.fragment:fragment-ktx:1.3.6"
 
     def lifecycle_version = "2.3.1"
@@ -47,10 +55,21 @@ dependencies {
     implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
     implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
 
-    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
+    implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
     implementation "com.google.dagger:hilt-android:$hilt_version"
     kapt "com.google.dagger:hilt-compiler:$hilt_version"
 
+    // Java 8
+    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
+    // Multidex needed if we target API < 21
+    def multidex_version = "2.0.1"
+    implementation "androidx.multidex:multidex:$multidex_version"
+
+    def ktorVersion = '1.6.2'
+    implementation "io.ktor:ktor-server-core:$ktorVersion"
+    implementation "io.ktor:ktor-server-netty:$ktorVersion"
+    implementation "ch.qos.logback:logback-classic:1.2.5"
+
     testImplementation 'junit:junit:4.13.2'
 
     androidTestImplementation 'androidx.test.ext:junit:1.1.3'
diff --git a/mailbox/src/main/AndroidManifest.xml b/mailbox/src/main/AndroidManifest.xml
index 9342203e8b08b5809989fe1c470b1e9adf76e6e1..0e535a95782692fe221e63d110bd0f2681c52fde 100644
--- a/mailbox/src/main/AndroidManifest.xml
+++ b/mailbox/src/main/AndroidManifest.xml
@@ -2,6 +2,9 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="org.briarproject.mailbox">
 
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
 
     <application
diff --git a/mailbox/src/main/java/org/briarproject/mailbox/MailboxApplication.kt b/mailbox/src/main/java/org/briarproject/mailbox/MailboxApplication.kt
index cc46087350518193bc455a354cc73ba0ae9a5e4a..72f53354ea774fdd788292aa6d9ed7ac7632e282 100644
--- a/mailbox/src/main/java/org/briarproject/mailbox/MailboxApplication.kt
+++ b/mailbox/src/main/java/org/briarproject/mailbox/MailboxApplication.kt
@@ -1,10 +1,10 @@
 package org.briarproject.mailbox
 
-import android.app.Application
+import androidx.multidex.MultiDexApplication
 import dagger.hilt.android.HiltAndroidApp
 
 @HiltAndroidApp
-class MailboxApplication : Application() {
+class MailboxApplication : MultiDexApplication() {
 
     override fun onCreate() {
         super.onCreate()
diff --git a/mailbox/src/main/java/org/briarproject/mailbox/MailboxNotificationManager.kt b/mailbox/src/main/java/org/briarproject/mailbox/MailboxNotificationManager.kt
index 96869014364a7fd79fc275da4628493a66906ef0..476aaaa040e4063c423d7f474704e382bd245359 100644
--- a/mailbox/src/main/java/org/briarproject/mailbox/MailboxNotificationManager.kt
+++ b/mailbox/src/main/java/org/briarproject/mailbox/MailboxNotificationManager.kt
@@ -14,7 +14,9 @@ import androidx.core.app.NotificationCompat.PRIORITY_MIN
 import androidx.core.content.ContextCompat.getSystemService
 import dagger.hilt.android.qualifiers.ApplicationContext
 import javax.inject.Inject
+import javax.inject.Singleton
 
+@Singleton
 class MailboxNotificationManager @Inject constructor(
     @ApplicationContext private val ctx: Context,
 ) {
diff --git a/mailbox/src/main/java/org/briarproject/mailbox/MailboxService.kt b/mailbox/src/main/java/org/briarproject/mailbox/MailboxService.kt
index 71e14e59152d4a6fc9d2485013c6ffc49439db3b..be22c09ac7b0bd3c973b98601fcdc7c59e14edf7 100644
--- a/mailbox/src/main/java/org/briarproject/mailbox/MailboxService.kt
+++ b/mailbox/src/main/java/org/briarproject/mailbox/MailboxService.kt
@@ -7,6 +7,7 @@ import android.os.IBinder
 import androidx.core.content.ContextCompat
 import dagger.hilt.android.AndroidEntryPoint
 import org.briarproject.mailbox.MailboxNotificationManager.Companion.NOTIFICATION_MAIN_ID
+import org.briarproject.mailbox.server.WebServerManager
 import javax.inject.Inject
 
 @AndroidEntryPoint
@@ -25,10 +26,14 @@ class MailboxService : Service() {
     }
 
     @Inject
-    lateinit var notificationManager: MailboxNotificationManager
+    internal lateinit var notificationManager: MailboxNotificationManager
+    @Inject
+    internal lateinit var webServerManager: WebServerManager
 
     override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
         startForeground(NOTIFICATION_MAIN_ID, notificationManager.serviceNotification)
+        // TODO handle inside LifecycleManager
+        webServerManager.start()
         return START_NOT_STICKY
     }
 
@@ -36,4 +41,9 @@ class MailboxService : Service() {
         return null
     }
 
+    override fun onDestroy() {
+        // TODO handle inside LifecycleManager
+        webServerManager.stop()
+        super.onDestroy()
+    }
 }
diff --git a/mailbox/src/main/java/org/briarproject/mailbox/server/Routing.kt b/mailbox/src/main/java/org/briarproject/mailbox/server/Routing.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0225cdc73862036e637aa15493651f301c3e814a
--- /dev/null
+++ b/mailbox/src/main/java/org/briarproject/mailbox/server/Routing.kt
@@ -0,0 +1,15 @@
+package org.briarproject.mailbox.server
+
+import android.os.Build
+import io.ktor.application.Application
+import io.ktor.application.call
+import io.ktor.http.ContentType
+import io.ktor.response.respondText
+import io.ktor.routing.get
+import io.ktor.routing.routing
+
+internal fun Application.configureRouting() = routing {
+    get("/") {
+        call.respondText("All good here in ${Build.MODEL}", ContentType.Text.Plain)
+    }
+}
diff --git a/mailbox/src/main/java/org/briarproject/mailbox/server/WebServerManager.kt b/mailbox/src/main/java/org/briarproject/mailbox/server/WebServerManager.kt
new file mode 100644
index 0000000000000000000000000000000000000000..13c5afc2c3c96cf1e8b8c5eb11986a944e78407b
--- /dev/null
+++ b/mailbox/src/main/java/org/briarproject/mailbox/server/WebServerManager.kt
@@ -0,0 +1,46 @@
+package org.briarproject.mailbox.server
+
+import android.content.Context
+import dagger.hilt.android.qualifiers.ApplicationContext
+import io.ktor.application.install
+import io.ktor.features.CallLogging
+import io.ktor.server.engine.embeddedServer
+import io.ktor.server.netty.Netty
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.launch
+import java.util.logging.Logger.getLogger
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+internal class WebServerManager @Inject constructor(
+    @ApplicationContext private val ctx: Context,
+) {
+
+    internal companion object {
+        private const val PORT = 8888
+        private val LOG = getLogger(WebServerManager::class.java.name)
+    }
+
+    private val server by lazy {
+        embeddedServer(Netty, PORT, watchPaths = emptyList()) {
+            install(CallLogging)
+            configureRouting()
+        }
+    }
+
+    fun start() {
+        // hangs if not starting inside a coroutine
+        GlobalScope.launch(Dispatchers.IO) {
+            LOG.info("starting")
+            server.start(wait = true)
+            LOG.info("started")
+        }
+    }
+
+    fun stop() {
+        server.stop(1_000, 2_000)
+    }
+
+}