I finally started using Molly to send and receive messages via Signal. Molly is a hardened fork of Signal for Android, offering features such as an encrypted message database, automatic locking, shredding no longer needed secrets from RAM, notifications via UnifiedPush, and Tor / SOCKS proxy support. This is by no means an alternative to Signal itself, but rather an alternative (and hardened) Android client for Signal.
While these extra security features are great, my main motivation to use Molly was battery saving, actually. I’m on GrapheneOS, which does offer sandboxed Google Play (opt-in), yet I’ve chosen not to use it. This means I’m not using Google’s Firebase Cloud Messaging (FCM) for notifications either, which Signal by default heavily relies on. However, it continues to make me very glad I can still use a secure and open source mobile operating system (GrapheneOS) in 2025, without needing to rely on proprietary and privacy-impairing functionality.
|
ℹ️
|
Signal resorting to FCM is not necessarily a bad thing. Signal is doing a tremendous job making carefully considered choices to make it easy for the largest part of the population (ergo including non-technical people) to use Signal with the least amount of effort. This means your partner, children, (grand)parents, coworkers, and friends alike with wildly different skills and interests, should all be able to use an open source and privacy-respecting messaging application, without the need of a CS degree, fulfilling a great societal and social need. |
Molly however offers notifications via UnifiedPush, which is particularly interesting for Android users not using Google Play (and FCM). Signal resorts to highly inefficient non-FCM push mechanisms when FCM is not available, draining a lot of battery power as a result. UnifiedPush is a privacy-preserving decentralized push notification system, which is much more energy efficient than non-FCM notifications.
Molly currently comes in two flavours: Molly and Molly-FOSS. Both offer UnifiedPush, but regular Molly also supports FCM, and Google Maps for location sharing. Molly-FOSS drops FCM, and replaces Google Maps with OpenStreetMap, further preserving user privacy.
|
ℹ️
|
For the remainder of this post, when talking about Molly, I’m talking about Molly-FOSS, unless stated otherwise. |
During my initial configuration, I found this blog post by mrusme, and this blog post by Norbert Tretkowski to be very helpful.
When using Molly with UnifiedPush, a few additional pieces of the puzzle are still required:
-
MollySocket, linking your Signal account to UnifiedPush, behind a secure (HTTPS) reverse proxy (e.g. Caddy, or Nginx).
-
A UnifiedPush provider and distributor, e.g. ntfy, or NextPush with UnifiedPush Provider (if you’re already using Nextcloud)
I’m already using Nextcloud, so I opted to use the UnifiedPush Provider app on Nextcloud, and NextPush on Android. This is what the whole flow looks like:
First, consider installing Molly via Accrescent, a private and secure app store, also available from the GrapheneOS App Store. Then install the UnifiedPush Provider app on your Nextcloud, and the NextPush app on your Android phone.
To run MollySocket I chose to run it in a Docker container. There’s an example Docker compose file, which I’ve edited like so:
services:
mollysocket:
image: ghcr.io/mollyim/mollysocket:1
container_name: mollysocket
restart: always
volumes:
- ./data:/data
working_dir: /data
command: server
environment:
- MOLLY_DB="/data/mollysocket.db"
# Do not add space in the array ["http://a.tld","*"]
- MOLLY_ALLOWED_ENDPOINTS=["https://molly.domain.tld","*"]
# Replace the UUID with Molly's, in Settings -> Notifications -> UnifiedPush -> Account ID
- MOLLY_ALLOWED_UUIDS=["aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"]
# TODO:
#- MOLLY_VAPID_PRIVKEY="paste output of `docker exec mollysocket mollysocket vapid gen` here"
- MOLLY_VAPID_PRIVKEY="aaaaaaaaaaa-bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
- MOLLY_HOST=0.0.0.0
- MOLLY_PORT=8020
- RUST_LOG=info
ports:
- 192.168.1.1:8020:8020/tcp
networks: {}Once you run the above container, you can generate the VAPID key by using the docker exec mollysocket mollysocket vapid gen command.
Edit your compose file accordingly, and restart the container.
Next, place it behind your reverse proxy, like you probably already use for Nextcloud. There’s an example for Caddy as well, which I’ve edited like so:
molly.domain.tld {
reverse_proxy h2c://192.168.1.1:8020
}|
ℹ️
|
Don’t forget to configure your DNS RRs accordingly. |
Reload Caddy, and browse to the new website using your web browser. You should be seeing a page similar to this:
You can scan the code with Molly when configuring UnifiedPush (Settings → Notifications → UnifiedPush → MollySocket server). Also select NextPush as the Distributor app, just below there. You should then also be seeing an Account ID (UUID). You can test the configuration by pressing the Test configuration button at the bottom.
|
💡
|
Once you’ve got your Account ID (UUID), you can also test the configuration from the container itself: docker exec mollysocket mollysocket connection ping <UUID>
|
If everything works as expected, edit your Docker compose file with this UUID, and restart the container again. You should now have setup everything you need to use Molly with UnifiedPush.
I myself noticed huge improvements on battery life the next few days:
If something is not working as expected yet, please consult the Troubleshooting section, or the aforementioned blog posts which helped me as well.