signalblast
Signalblast is a bot that sends encrypted messages anonymously over Signal to a list of subscribers. Subscribers don't see who else is on the list, and they don't see who sent a broadcast: every message comes from the bot.
A server is required to host the bot, see the installation instructions below.
The idea for this bot came from Signalboost, which unfortunately is no longer alive.
Usage
Send these commands to the bot in a private chat. Commands are not case sensitive.
!subscribesign up to the list!unsubscribestop receiving messages!broadcast <message>send a message to every subscriber. Any message that isn't a command is broadcast too, so!broadcastis only needed for messages that start with!!admin <message>send a message only to the admins, e.g. to get technical support!helpshow the available commands
Broadcasts can be edited and deleted for everyone in Signal as usual, for up to 24 hours. Messages that start with ! but aren't a command are never broadcast, the bot replies with the help instead.
Admin commands
!add admin <password>become an admin, the password isSIGNALBLAST_PASSWORD. There can be several admins!remove admin <password> <admin id>remove an admin!list adminsshow the ids of the admins!banreply!banto a broadcast, or to a message from a user, to ban its sender. This works for broadcasts from the last 24 hours (so the admin must be subscribed to receive them) and for messages from the last 7 days!list bansshow the banned users, numbered, with the start of the message they were banned for!lift ban <number>lift a ban!versionshow the versions of signalblast, signalbot and signal-cli-rest-api
Messages that users send with !admin reach every admin as User wrote: …. To answer, reply to the message, without any command. The user receives it as Admin: … and answers the same way, by replying to it, and so on. The other admins get a copy of every reply. Each message the bot sends in a conversation is a reply to the message it answers, so every chat shows the conversation as a thread. Replying to any message of a conversation continues it, it is never broadcast.
Privacy
- Subscribers never learn who else is subscribed, or who sent a broadcast.
- Admins never learn who a subscriber is either: users who write to the admins appear as
User, and bans and answers work by replying to messages. - The bot's database keeps only:
- who sent each broadcast, for 24 hours, so that broadcasts can be edited and deleted
- which user each message between users and admins belongs to, for 7 days, so that replies reach the right person. The content of the messages is not stored.
- both are also used to let admins ban a sender just by replying to their message.
- Whoever hosts the bot can, in principle, see who everyone is and what they send, since every message passes through their server. By default the bot does not record this. However, there is currently no easy way to prove that the host has not modified the bot. Ways to address this are discussed in #39.
Installation
Option 1: docker compose
This uses the images from https://hub.docker.com/r/eradorta/signalblast
- Install docker.
- Set up signal-cli-rest-api for the bot's phone number as specified here.
- Download the docker-compose.yaml and .env.example files, the latter is downloaded as
.env.curl -fsSLO https://raw.githubusercontent.com/Gara-Dorta/signalblast/main/docker-compose.yaml curl -fsSL -o .env https://raw.githubusercontent.com/Gara-Dorta/signalblast/main/.env.example
- Fill in
SIGNALBLAST_PHONE_NUMBERin.env. The rest are optional, uncomment the ones you want to set, see configuration. You'll likely wantSIGNALBLAST_PASSWORD, otherwise nobody can become an admin. - Create a data folder
mkdir -p $HOME/.local/share/signalblast
- Run via docker compose on the folder where the
docker-compose.yamlfile is located:docker compose up
- Optional: restart the containers automatically when signalblast can't send messages.
- Set
SIGNALBLAST_HEALTHCHECK_RECEIVERin your.envfile, it will receive a "Ping" message every 8 hours. The signalblast container is reported as unhealthy after 3 failed pings in a row, so a problem is detected within a day. - Docker doesn't restart unhealthy containers on its own, and the error is often only recoverable by restarting both signal-cli-rest-api and signalblast. Install the watchdog as a systemd user timer that does that, it runs as your user (which must be able to run docker):
curl -fsSL https://raw.githubusercontent.com/Gara-Dorta/signalblast/main/docker/install_watchdog.sh | bash
- Uninstall it with:
curl -fsSL https://raw.githubusercontent.com/Gara-Dorta/signalblast/main/docker/install_watchdog.sh | bash -s -- --uninstall
- Alternatively, Docker Swarm and Podman (
--health-on-failure=restart) can restart the signalblast container natively, but they won't restart signal-cli-rest-api.
- Set
Option 2: python environment
- Set up signal-cli-rest-api as specified here.
- Install signalblast in a new virtual environment, uv is recommended
uv tool install signalblast
- Set the configuration as environment variables or in a
.envfile in the folder you run it from, then run it withsignalblast
Configuration
signalblast reads its settings from environment variables, or from a .env file in the working directory. Empty values are treated as unset.
The only required variable is the phone number of the bot:
| Variable | Description |
|---|---|
SIGNALBLAST_PHONE_NUMBER |
The phone number of the bot |
The rest are optional:
| Variable | Default | Description |
|---|---|---|
SIGNALBLAST_PASSWORD |
The password to become an admin. It is stored hashed, so it only needs to be set on the first start or to change it. Without it nobody can become an admin | |
SIGNALBLAST_SIGNAL_SERVICE |
localhost:8080 |
The address of signal-cli-rest-api |
SIGNALBLAST_DATA_DIR |
~/.local/share/signalblast |
Where the database is stored |
SIGNALBLAST_INSTRUCTIONS_URL |
A link with instructions, shown in the help | |
SIGNALBLAST_EXPIRATION_TIME |
4 weeks | The disappearing messages timer of the chats with the subscribers in seconds, 0 leaves the timer of the chats unchanged, -1 disables it |
SIGNALBLAST_HEALTHCHECK_RECEIVER |
The contact or group that receives the health check pings, the health check is disabled without it | |
SIGNALBLAST_HEALTHCHECK_PORT |
15556 |
The port of the health check endpoint, on localhost |
SIGNALBLAST_LOG_LEVEL |
INFO |
DEBUG, INFO, WARNING or ERROR |
SIGNALBLAST_LOG_FILE |
Log to this file, rotated weekly, instead of the console |
Development
- Set up signal-cli-rest-api as specified in the installation section.
- Clone the repo
- Install uv
- Install the repo and the dependencies in a new virtual environment with
uv sync - Install the prek hooks with
uv run prek install, they runruffandty - Run the tests with
uv run pytest - Run
signal-cli-rest-apiwithdocker compose up signal-cli-rest-api - Run the bot
uv run signalblast - Optional: install signalbot as an editable dependency with
uv add --editable ../signalbot/, but don't commit that change
Docker compose
The docker compose scripts will automatically get and set the signalblast version from the git history.
docker/compose_build.sh and docker/compose_up.sh build and run the image from the local code.
Metadata
Release files for signalblast 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| signalblast-1.0.1.tar.gz | 108.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| signalblast-1.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 154.0 kB
Release files / signalblast-1.0.1.tar.gz
| Download URL | signalblast-1.0.1.tar.gz |
|---|---|
| Size | 108.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2cb0b8cca778bc1d091db30a1cbd450f09fa541ca98607b073686613d409a6d6
|
|
BLAKE2b-256 checksum How to use checksums |
2aa597c53faeddb9d62281d57cc1170e8eb06f61480d7a28dff2c548b52c2e09
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.
Transparency logRelease files / signalblast-1.0.1-py3-none-any.whl
| Download URL | signalblast-1.0.1-py3-none-any.whl |
|---|---|
| Size | 45.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8eab580b58161b3cbfcdf6afd9b2d1e4afc4dac83660c7a58c567fc1dbe97f76
|
|
BLAKE2b-256 checksum How to use checksums |
f3d69c7779fbc3c2c3a618a76ac4050633c16d2f37ac0cd779fc8d03db5cd75d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.
Transparency log