bitdeals git user 2701c57200
Build docker image and push to registry.bitdeals.org / main-build-job (push) Successful in 2m12s
cap total connections, and document the P2P port 8444
The daemon has always listened on 8444 and nothing published it, so every
node built from this image was outbound-only. Publishing it is now a
documented choice rather than an omission -- including the two things that
are not obvious from the config: peers are told the port from `port` in
keys.dat rather than the one you mapped it to (so only 8444:8444 works),
and the node's own address is never configured at all, because every peer
replaces the hardcoded 127.0.0.1 in the version message with the IP it
sees on the socket.

An open port needs a brake, hence BITMESSAGE_MAXTOTALCONNECTIONS. It
defaults to the PyBitmessage stock 200, so nothing changes for existing
users of the image. The key is inserted when the stock config lacks it
instead of trusting the substitution: the PyBitmessage clone is unpinned,
and a silent no-op would ship a node that looks capped and is not.

The API port in the example compose moves to loopback, which is what the
README already prescribed.
2026-08-02 14:48:01 +00:00
2026-03-18 11:42:32 +03:00

Intro

Русская версия: README.ru-RU.md

PyBitmessage is a client of the Bitmessages P2P communication protocol used to send encrypted messages to another person or to many subscribers.

PyBitmessage client running as a daemon in docker container with XML-RPC API enabled.

This repository covers the docker deployment only.

Usage

The container generates a Bitmessage Deterministic Addresses based on a BITMESSAGE_SEED_PHRASE variable.

Here are some example snippets to help you get started creating a container.

The container has two ports and they are not interchangeable. 8442 is the XML-RPC API: it controls the daemon completely and has no TLS, so set your own credentials and keep it on loopback. 8444 is the Bitmessage P2P port: publish it to let other nodes connect in, leave it unpublished to stay outbound-only. The daemon listens on both inside the container either way.

docker-compose

services:
  pybitmessage:
    build:
      context: https://git.bitdeals.org/private/bitmessage.git
      dockerfile: ./docker/Dockerfile
    image: registry.bitdeals.org/bitmessage
    environment:
      - BITMESSAGE_API_USER=CHANGE_ME
      - BITMESSAGE_API_PASSWORD=CHANGE_ME
      - BITMESSAGE_SEED_PHRASE=bitmessage_seed_phrase
      - BITMESSAGE_SEED_ADDRESSES=1
      - BITMESSAGE_TTL=172800
      - BITMESSAGE_STOPRESENDINGAFTERXDAYS=60
      - BITMESSAGE_MAXTOTALCONNECTIONS=40
    ports:
      - 127.0.0.1:8442:8442   # API — loopback only
      - 8444:8444             # P2P — omit this line to stay outbound-only
    volumes:
      - bitmessage:/home/bitmessage

volumes:
  bitmessage:

docker cli

docker run -d \
  -e BITMESSAGE_API_USER=CHANGE_ME \
  -e BITMESSAGE_API_PASSWORD=CHANGE_ME \
  -e BITMESSAGE_SEED_PHRASE=bitmessage_seed_phrase \
  -e BITMESSAGE_SEED_ADDRESSES=1 \
  -e BITMESSAGE_TTL=172800 \
  -e BITMESSAGE_STOPRESENDINGAFTERXDAYS=60 \
  -e BITMESSAGE_MAXTOTALCONNECTIONS=40 \
  -p 127.0.0.1:8442:8442 \
  -p 8444:8444 \
  -v bitmessage:/home/bitmessage \
  registry.bitdeals.org/bitmessage

Parameters

Container images are configured using parameters passed at runtime.

Parameter Function
-p 127.0.0.1:8442 API port. The daemon always binds 0.0.0.0 inside the container, so what you publish decides who reaches it
-p 8444 Bitmessage P2P port. Optional: without it the node still connects out to peers, it just cannot be connected to. Must be published as 8444:8444 — see Notes
-v /home/bitmessage Data directory: keys.dat (identity, settings) and messages.dat. Without it the node is a new node after every update
-e BITMESSAGE_API_USER XML-RPC API user. Default: bitmessage_api_user — change it
-e BITMESSAGE_API_PASSWORD XML-RPC API password. Default: bitmessage_api_password — change it, see Notes
-e BITMESSAGE_SEED_PHRASE Create Deterministic Addresses password. Default: regenerated on every start, giving different addresses each time. Only used when BITMESSAGE_SEED_ADDRESSES is above 0
-e BITMESSAGE_SEED_ADDRESSES Number of Deterministic Addresses to generate. Default: 0
-e BITMESSAGE_TTL The expiration of newly send messages, in seconds. Default: 172800
-e BITMESSAGE_STOPRESENDINGAFTERXDAYS Stop resending unreceived message after X days. Default: 30
-e BITMESSAGE_APIVARIANT provides xml or json-RPC API. Default: legacy
-e BITMESSAGE_MAXTOTALCONNECTIONS Cap on all connections at once, inbound and outbound together (maxoutboundconnections is 8, so this minus 8 is the inbound headroom). Default: 200, the PyBitmessage stock value — lower it when the P2P port is published

Notes

  • % cannot be used in the API password: it breaks PyBitmessage's own config reader, and every API call then returns 500 while keys.dat looks correct. Other characters are fine, the container escapes them.
  • Clients must percent-encode the credentials — they go into http://user:password@host:port/, where @, #, / and : change how the URL parses. The scripts in this image do; yours has to as well.
  • The container turns healthy once the daemon has a network connection, which on a new node takes a few minutes. The start period also covers the startup VACUUM of messages.dat.
  • The P2P port must be published as 8444:8444. The daemon tells peers the port from its own config (port in keys.dat), not the port you mapped it to, so 8555:8444 advertises a port nobody can reach. A different host port needs extport in keys.dat, which this container does not template.
  • Your own address is never configured. The version message carries a hardcoded 127.0.0.1 that every peer discards in favour of the IP it sees on the socket, and it takes the port from that same message. So a node with 8444 published is found by the network on its own, as soon as it connects out — there is no host IP or DNS name to set anywhere. The one exception is a Tor hidden service, which needs an explicit onionhostname.
  • Publishing 8444 is a deliberate security trade-off. The daemon runs on Python 2 and already parses untrusted data from its outbound peers, so an open port does not create that exposure — it changes who may connect, when, and how many. The pre-handshake parser becomes reachable by anyone, and the practical risk is resource exhaustion rather than code execution. Keep BITMESSAGE_MAXTOTALCONNECTIONS low and put memory and CPU limits on the container.
S
Description
PyBitmessage dockerfile
Readme
104 KiB
Languages
Shell 59.5%
Dockerfile 26.6%
Python 13.9%