PlainApp addresses a common challenge for power users and developers who want to manage their Android phone remotely without relying on cloud services. It transforms an Android device into a self-hosted server accessible from any browser on the local network. The standout technical aspect lies in its layered encryption approach: combining TLS with an additional application-layer encryption using the XChaCha20-Poly1305 cipher. This design provides end-to-end encryption without needing cloud-based certificate authorities or public certificates.
What plainapp does and its architecture
At its core, PlainApp is an Android application written in Kotlin, targeting devices running Android 9.0 (API level 28) and above. The app runs a local web server on the phone, which serves a Progressive Web App (PWA) accessible via any modern browser on the same local network.
The PWA provides a desktop-like experience, allowing users to interact with their phone’s features remotely. PlainApp exposes capabilities like file system browsing and management, access to SMS and call logs, screen mirroring with remote input control, notification mirroring, and media streaming.
Beyond direct phone management, it includes standalone utilities such as an RSS reader, Markdown note-taking, peer-to-peer file sharing, and casting support for DLNA and Chromecast devices.
This all works without any cloud dependency: no external servers are involved, and all communication stays within the local network. The device functions as the server, and the browser acts as the client.
Security-wise, the app uses a local-first architecture. All data and processing remain on the phone, with encrypted communication to the browser client. The choice of Kotlin for Android development aligns with modern Android development best practices and allows integration with native APIs for phone features and media streaming.
How plainapp secures communication with layered encryption
The most technically interesting part of PlainApp is its approach to securing communication between the phone server and browser client.
First, it uses TLS to establish a secure channel over the local network. But unlike typical TLS usage, which relies on public certificate authorities and certificates, PlainApp operates purely within the local network and avoids any cloud-based trust infrastructure.
On top of TLS, PlainApp adds an application-layer authenticated encryption using the XChaCha20-Poly1305 cipher. XChaCha20-Poly1305 is a modern AEAD (Authenticated Encryption with Associated Data) cipher known for strong security guarantees and good performance on mobile devices.
This double-layered encryption means that even if the TLS channel were somehow compromised, the application data remains protected by the additional AEAD layer. It also allows PlainApp to implement end-to-end encryption between the phone and the browser client without needing public certificates.
The tradeoff is increased complexity in encryption management and key exchange. The app must securely generate, store, and exchange encryption keys locally, without relying on external PKI infrastructure.
This design reflects a zero-cloud dependency philosophy: all trust and encryption material are generated and managed on the device itself. The local network acts as the transport layer, secured by TLS, while the AEAD cipher protects the application data end-to-end.
An example conceptual snippet illustrating layered encryption might look like this:
// Pseudocode illustrating combined TLS + XChaCha20-Poly1305 usage
val tlsSocket = createLocalNetworkTlsSocket()
val xchachaCipher = XChaCha20Poly1305(secretKey)
fun sendEncrypted(data: ByteArray) {
val encryptedData = xchachaCipher.encrypt(data, associatedData = someContext)
tlsSocket.write(encryptedData)
}
fun receiveDecrypted(): ByteArray {
val encryptedData = tlsSocket.read()
return xchachaCipher.decrypt(encryptedData, associatedData = someContext)
}
This layered approach is not common in typical mobile apps but provides a security model tailored to the local network, self-hosted use case.
Explore the project
PlainApp’s source code and documentation are hosted on GitHub at https://github.com/plainhub/plain-app.
The repository contains the Kotlin Android application code, which requires Android 9.0 or higher to run.
The README outlines the feature set and architectural principles, emphasizing local operation without cloud dependencies. It also mentions the creation of a keystore for encryption purposes, though specific key sizes or algorithms beyond the layered TLS + XChaCha20-Poly1305 approach are not detailed.
Since the app serves a PWA, a key part of the user experience is the web client served from the phone itself. The repository likely includes web assets and service workers to enable the installable PWA experience on desktop and mobile browsers.
To get started with the project, one would typically build the Android app using standard Kotlin/Android tooling (Android Studio or Gradle). Running the app on a compatible Android device sets up the local server and encryption keys.
From there, users connect via a browser on the same network, access the PWA, and interact with their phone’s features remotely.
Verdict
PlainApp is a solid example of self-hosted Android phone management that prioritizes privacy and local network security.
It is particularly suited for users who want remote access to their phone without involving cloud services. The local-first architecture paired with the layered encryption approach shows a pragmatic balance between security and usability.
The complexity of managing encryption keys and the network-bound scope means it may not fit all use cases — for example, remote access outside the local network or enterprise deployments requiring centralized management.
Also, the requirement for Android 9.0+ limits compatibility with older devices.
For developers and privacy-focused users interested in local network encryption patterns, PlainApp offers valuable insights. Its use of TLS combined with XChaCha20-Poly1305 AEAD encryption is worth understanding even if you don’t adopt the app itself.
The codebase can serve as an example of layered encryption in a mobile app context and a practical implementation of a self-hosted PWA server on Android.
→ GitHub Repo: plainhub/plain-app ⭐ 4,601 · Kotlin