Skip to main content

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.

  • !subscribe sign up to the list
  • !unsubscribe stop receiving messages
  • !broadcast <message> send a message to every subscriber. Any message that isn't a command is broadcast too, so !broadcast is only needed for messages that start with !
  • !admin <message> send a message only to the admins, e.g. to get technical support
  • !help show 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 is SIGNALBLAST_PASSWORD. There can be several admins
  • !remove admin <password> <admin id> remove an admin
  • !list admins show the ids of the admins
  • !ban reply !ban to 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 bans show the banned users, numbered, with the start of the message they were banned for
  • !lift ban <number> lift a ban
  • !version show 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 don't see who else is subscribed, or who sent a broadcast.
  • Admins don't see who the subscribers are either. Messages to the admins arrive from User, and admins answer and ban people by replying to their messages, never by name or number.
  • The bot doesn't store the content of messages. Its database only remembers who sent what, and only for as long as it needs to:
    • the sender of each broadcast, for 24 hours, so that broadcasts can be edited and deleted
    • the user that each message between a user and the admins belongs to, for 7 days, so that replies reach the right person

Every message passes through the server that hosts the bot, so whoever runs it could, in principle, see who everyone is and what they send. The bot doesn't record this, but there is no easy way yet to prove from the outside that the host runs an unmodified bot. If you can get access to the server, you can check that it runs an unmodified, signed release, see verify the container. Notet that there are attacks that verify ca not rule out, they are listed there.

Installation

Option 1: docker compose

This uses the images from https://hub.docker.com/r/eradorta/signalblast

  • Set up signal-cli-rest-api for the bot's phone number as specified here.
  • Stop the signal-cli-rest-api container.
  • 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_NUMBER in .env. The rest are optional, uncomment the ones you want to set, see configuration. You'll likely want SIGNALBLAST_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.yaml file is located:
    docker compose up
    
  • Optional: restart the containers automatically when signalblast can't send messages.
    • Set SIGNALBLAST_HEALTHCHECK_RECEIVER in your .env file, 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.
  • To update, download the latest docker-compose.yaml and pull the images.
    curl -fsSLO https://raw.githubusercontent.com/Gara-Dorta/signalblast/main/docker-compose.yaml
    docker compose pull
    docker compose up -d
    

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 .env file in the folder you run it from, then run it with
    signalblast
    

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 signal-cli-rest-api: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

Reproducible builds

The PyPI wheel and the docker image are reproducible and they are also signed. Release tags are signed with the SSH key in .github/allowed_signers.

To check that a release on PyPI and Docker Hub was built from the code in its git tag, rebuild and compare it, and check its signatures, with:

scripts/verify-release.sh v1.2.3

Only the image for the platform of your machine is built and checked for reprocibility. Add --all-platforms to rebuild all of them, which needs QEMU. Add --signatures-only to only check the signatures, which is much faster as nothing is built.

For convinience, each github release also has the hashes of the PyPI files in SHA256SUMS and the digests of the docker image in IMAGE-DIGESTS.

Verify the container

The checks below make tampering harder and easier to spot but not impossible. Most importantly, they only show what the containers run when the checks run, a host could run modified containers in between checks.

To verify the containers, run:

scripts/verify-container.sh

It checks that:

  • the signalblast image is a signed release.
  • signalblast talks to the signal-cli-rest-api specified in the docker-compose.yaml.
  • the signal-cli-rest-api image is the one pinned in the docker-compose.yaml. This image is not signed, so this only shows that it is the image published on Docker Hub.
  • both containers run their image unmodified:
    • with its command and health check.
    • with only the variables and mounts of their services in that docker-compose.yaml added, and /tmp.
    • with no files changed outside /tmp.
  • the Signal account of the bot has no linked devices, as they would receive every message.

Run with --rebuild to also run scripts/verify-release.sh ((reproducibility checks) for that release.

The verify-container.sh script will find the default container and version. Additionaly, it also supports checking against different container names and versions, e.g. scripts/verify-container.sh my-other-container v1.2.3.

Metadata

Release files for signalblast 1.0.8

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for signalblast 1.0.8
File Size Uploaded Provenance
signalblast-1.0.8.tar.gz 132.2 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for signalblast 1.0.8
File Interpreter ABI Platform
signalblast-1.0.8-py3-none-any.whl Python 3 none any Details

Total release size: 178.6 kB

Release files / signalblast-1.0.8.tar.gz

Download URL signalblast-1.0.8.tar.gz
Size 132.2 kB
Tags Source
SHA-256 checksum
How to use checksums
2ffc3ca0a862db1487e541f148f6e7df30bd1c97c16894a8a5bde4a543180336
BLAKE2b-256 checksum
How to use checksums
b2f26f25c96f407a61971f738013f819de3fdd96fac26c46dead89ef3b0d8daf
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 19, 2026.

Transparency log

Release files / signalblast-1.0.8-py3-none-any.whl

Download URL signalblast-1.0.8-py3-none-any.whl
Size 46.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8a3a02a87f4ac44f8a072c9f4e8a09cc863dd18920cfae6256986f003bc3cce5
BLAKE2b-256 checksum
How to use checksums
a26b2bab2aedf5812aa5c7c8f05819edd554e255cf6134ec0c519ac80707af61
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 19, 2026.

Transparency log

Security for signalblast 1.0.8

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for signalblast-1.0.8.tar.gz

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 19, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page