Home

Awesome

MollySocket

MollySocket allows getting signal notifications via UnifiedPush. It works like a linked device, which doesn't have an encryption key, connected to the Signal server. Everytime it receives an encrypted event, it notifies your mobile via UnifiedPush.

Overview

---
title: Message flow
---
graph TD
    
    MS[fa:fa-tablets MollySocket]
    S[fa:fa-comment Signal Server]
    P[fa:fa-server Push server]
    subgraph "fa:fa-mobile Android"
        D[fa:fa-tower-broadcast Distributor App]
        MA[fa:fa-tablets Molly Android]
    end
    MS -- 1. Persistent connection --> S
    MS -- 2. 'Notifications present' --> P
    P -- 3. 'Notications present for Molly' --> D
    D -- 4. 'Check Signal servers' --> MA
    MA -- 5. 'Got messages?' --> S
    S -- 6. Messages --> MA

Setup

  1. You need the right flavor of Molly to use UnifiedPush: https://github.com/mollyim/mollyim-android-unifiedpush.
  2. You can install MollySocket via:
    1. Docker/Podman: docker pull ghcr.io/mollyim/mollysocket:latest
    2. Crates.io: cargo install mollysocket (see INSTALL.md for the setup)
    3. Direct download: https://github.com/mollyim/mollysocket/releases (see INSTALL.md for the setup)
  3. A distributor app (easiest is ntfy)

You can optionally install your own push server like ntfy or NextPush. For beginners, you can use a free service like ntfy.sh (do consider donating if you have the means).

Web Server

MollySocket exposes a web server so that Molly can send the information it needs to operate. You must configure TLS with a reverse proxy in front of MollySocket. Molly can only connect to the server over HTTPS.

It is possible to use MollySocket without the web server, but you will have to manually register the information MollySocket needs: see the Air Gapped mode on Android settings.

Configuration

The configuration file uses the TOML format. Below is an overview of configuration options. You can configure each parameter using either the conf file, the environment variable or the cli option (if available).

Parameter (conf. file)Environment variableCli OptionDescriptionDefaultExamples
RUST_LOG *-v/-vv/-vvvVerbosityerrorRUST_LOG=info, RUST_LOG=debug
MOLLY_CONF-c *Path to the configuration file, optional/etc/mollysocket.conf
hostMOLLY_HOST *Listening address of the web server127.0.0.10.0.0.0
portMOLLY_PORT *Listening port of the web server80208080
webserverMOLLY_WEBSERVER *Wether to start the web servertruefalse
allowed_endpointsMOLLY_ALLOWED_ENDPOINTS *List of UnifiedPush servers["*"]["*"],["https://yourdomain.tld","https://ntfy.sh"]
allowed_uuidsMOLLY_ALLOWED_UUIDS *UUIDs of signal accounts that may use this server["*"]["*"], ["abcdef-12345-tuxyz-67890"]
dbMOLLY_DB *Path to the DBdb.sqlite"/data/ms.sqlite"
vapid_privkeyMOLLY_VAPID_PRIVKEY *VAPID key, see VAPID keyNone"DSqYuWchrB6yIMYJtidvqANeRQic4uWy34afzZRsZnI"
vapid_key_fileMOLLY_VAPID_KEY_FILE *File with VAPID key, see VAPID keyNone"/etc/ms_vapid_key"

* Takes the precedence

VAPID key

VAPID key is used to authorize mollysocket server to send requests to your push server, if it supports it.

To generate a new key, you can run this command mollysocket vapid gen. Or using docker, docker-compose run mollysocket vapid gen.

This value can be passed to mollysocket via a file, location given with vapid_key_file parameter, or directly in the vapid_privkey parameter. The key file takes the precedence.

With docker-compose

The easiest way to pass the VAPID key when using docker compose is to pass it with the MOLLY_VAPID_PRIVKEY environment variable. See docker-compose.yml.

With a systemd service

If you use a systemd service for MollySocket, you may wish to use systemd-creds to store securely the VAPID key.

<sup>If you have installed your systemd service in user mode, adds --user to systemd-creds commands.</sup>

$ # Service installed in user mode:
$ # mollysocket vapid gen | systemd-creds --user encrypt --name=ms_vapid -p - -
$
# # Service installed in system mode:
# mollysocket vapid gen | systemd-creds encrypt --name=ms_vapid -p - -
SetCredentialEncrypted=ms_vapid: \
        k6iUCUh0RJCQyvL8k8q1UyAAAAABAAAADAAAABAAAAC1lFmbWAqWZ8dCCQkAAAAAgAAAA \
        AAAAAALACMA0AAAACAAAAAAfgAg9uNpGmj8LL2nHE0ixcycvM3XkpOCaf+9rwGscwmqRJ \
        cAEO24kB08FMtd/hfkZBX8PqoHd/yPTzRxJQBoBsvo9VqolKdy9Wkvih0HQnQ6NkTKEdP \
        HQ08+x8sv5sr+Mkv4ubp3YT1Jvv7CIPCbNhFtag1n5y9J7bTOKt2SQwBOAAgACwAAABIA \
        ID8H3RbsT7rIBH02CIgm/Gv1ukSXO3DMHmVQkDG0wEciABAAII6LvrmL60uEZcp5qnEkx \
        SuhUjsDoXrJs0rfSWX4QAx5PwfdFuxPusgE==

This will output SetCredentialEncrypted you can use in your systemd unit file:

[Service]
SetCredentialEncrypted=ms_vapid: \
        k6iUCUh0RJCQyvL8k8q1UyAAAAABAAAADAAAABAAAAC1lFmbWAqWZ8dCCQkAAAAAgAAAA \
        AAAAAALACMA0AAAACAAAAAAfgAg9uNpGmj8LL2nHE0ixcycvM3XkpOCaf+9rwGscwmqRJ \
        cAEO24kB08FMtd/hfkZBX8PqoHd/yPTzRxJQBoBsvo9VqolKdy9Wkvih0HQnQ6NkTKEdP \
        HQ08+x8sv5sr+Mkv4ubp3YT1Jvv7CIPCbNhFtag1n5y9J7bTOKt2SQwBOAAgACwAAABIA \
        ID8H3RbsT7rIBH02CIgm/Gv1ukSXO3DMHmVQkDG0wEciABAAII6LvrmL60uEZcp5qnEkx \
        SuhUjsDoXrJs0rfSWX4QAx5PwfdFuxPusgE==
Environment=MOLLY_VAPID_KEY_FILE=%d/ms_vapid

Alternatively, you can store the VAPID key in cleartext in the systemd unit file:

[Service]
Environment=MOLLY_VAPID_PRIVKEY=DSqYuWchrB6yIMYJtidvqANeRQic4uWy34afzZRsZnI

allowed_endpoints

These are the UnifiedPush endpoints that MollySocket may use to push notifications with.

⚠️ If you self-host your push server, add your push server to the allowed_endpoints. ⚠️

That's because, for security reasons, endpoints on your local network must be allowed explicitly. You just have to set the scheme (https), the domain and the port if required. For instance allowed_endpoints=['https://push.mydomain.tld']

allowed_uuids

You can allow registration for all accounts by setting allowed_uuids to ['*']. Else set your account ids in the array: ['account_id1','account_id2'].

The account IDs are showing in the Molly application under Settings > Notifications > UnifiedPush. You need to activate UnifiedPush first before your account ID is shown.

Troubleshoot

You haven't entered the right url.

This must be the one where MollySocket is reachable. To test it, open the link you have entered in a browser: you should see a json containing the version of MollySocket. For instance {"mollysocket":{"version":"1.2.0"}}.

If you can access the web server, make sure it is accessible over HTTPS. Molly can't connect to the server over HTTP.

You have restricted the allowed account ID who can use your MollySocket server.

Add your account ID[1] to allowed_uuids to allow your account, or add a wildcard ["*"] to allow all the accounts to use your server. See Configuration to configure your server correctly.

[1] Your account ID can be copied on the Android app, under the UnifiedPush settings

You have restricted the allowed UnifiedPush endpoints, or you are using a self-hosted server you haven't whitelisted.

Add your server to the allowed_endpoints: ["https://push.mydomain.tld"]. This is NOT your MollySocket URL but the one from your push provider. See Configuration to configure your server correctly.

There might be 3 reasons for that:

$ # If you use docker-compose:
$ docker compose run mollysocket <paste the parameters here>
$ # Else, if you use the binary:
$ mollysocket <paste the parameters here>
$ # Replace the UUID with your account Id
$ # If you use docker-compose:
$ docker compose run mollysocket connection ping c8d44128-5c99-4810-a7d3-71c079891c27
$ # Else, if you use the binary:
$ mollysocket connection ping c8d44128-5c99-4810-a7d3-71c079891c27
$ # Replace the UUID with your account Id
$ # If you use docker-compose:
$ docker compose run mollysocket connection ping c8d44128-5c99-4810-a7d3-71c079891c27
$ # Else, if you use the binary:
$ mollysocket connection ping c8d44128-5c99-4810-a7d3-71c079891c27

If you use air-gapped mode, then Molly (android) can't test the setup and it assumes you have correctly setup everything. You should double check that the account ID is accepted by your mollysocket server and the endpoint is allowed by your mollysocket server (check the output logs).

If you are using Molly version >= 7.1.3-1.up1 and MollySocket version >= 1.3.0, you can run this command:

$ # Replace the UUID with your account Id
$ # If you use docker-compose:
$ docker compose run mollysocket connection ping c8d44128-5c99-4810-a7d3-71c079891c27
$ # Else, if you use the binary:
$ mollysocket connection ping c8d44128-5c99-4810-a7d3-71c079891c27

If you receive a test notification (image bellow), then you should check that Molly and your distributor have unrestricted battery usage. You should check if you have additional configuration for your device regarding battery management: https://dontkillmyapp.com/.

<img src="https://github.com/mollyim/mollysocket/assets/31284753/b8def045-d80a-4165-a7a6-2aa721044c2e" width="400rem">

If you don't receive a test notification, then your MollySocket server can't reach your push server or your phone don't have network access.

You can get further troubleshooting information on this page: https://unifiedpush.org/users/troubleshooting/.

About security

Relative to Signal security

MollySocket never has any encryption key

MollySocket receives the credentials for a linked device and does not receive any encryption key. Which means:

License

AGPLv3: see LICENSE.txt.

Disclaimer

This project is NOT sponsored by or affiliated to Signal Messenger or Signal Foundation.

The software is produced independently of Signal and carries no guarantee about quality, security or anything else. Use at your own risk.