Compare commits
15
Commits
e270e0f616
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58e3f22982
|
||
|
|
2701c57200
|
||
|
|
335ee52c0d
|
||
|
|
a79d881647
|
||
|
|
6641a452b5
|
||
|
|
a8c8861cad
|
||
|
|
c957096762
|
||
|
|
ccac2e970a
|
||
|
|
7761772dda
|
||
|
|
28327d8604
|
||
|
|
ed91f1ba49
|
||
|
|
1f6e63ddad
|
||
|
|
6253ed1f5f
|
||
|
|
9a88767eaf
|
||
|
|
7ed94e64f3
|
@@ -0,0 +1,37 @@
|
||||
name: Build docker image and push to registry.bitdeals.org
|
||||
run-name: docker build and docker push
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
|
||||
jobs:
|
||||
main-build-job:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
VERSION: 1.0
|
||||
COMMIT: ${{ gitea.sha }}
|
||||
REPOSITORY: ${{ gitea.repository }}
|
||||
#registry.bitdeals.org
|
||||
REGISTRY: 10.0.3.111:5000
|
||||
USER: ${{ secrets.DOCKER_USERNAME }}
|
||||
PASS: ${{ secrets.DOCKER_PASSWORD }}
|
||||
steps:
|
||||
- name: Checkout repository code
|
||||
uses: actions/checkout@v6
|
||||
- name: Build docker app image
|
||||
run: |
|
||||
docker build . \
|
||||
--file "$(find ./Dockerfile ./docker/Dockerfile -print -quit 2>/dev/null)" \
|
||||
--label "git-commit=$COMMIT" \
|
||||
--tag "${REGISTRY}/${REPOSITORY##*/}:${VERSION}.${COMMIT::7}" \
|
||||
--tag "${REGISTRY}/${REPOSITORY##*/}:latest"
|
||||
- name: Docker login
|
||||
run: |
|
||||
docker login --username "$USER" --password "$PASS" "$REGISTRY"
|
||||
- name: Push images to registry
|
||||
run: |
|
||||
docker push "${REGISTRY}/${REPOSITORY##*/}:${VERSION}.${COMMIT::7}" ; \
|
||||
docker push "${REGISTRY}/${REPOSITORY##*/}:latest"
|
||||
|
||||
@@ -1,45 +1,67 @@
|
||||
# Intro
|
||||
|
||||
> Русская версия: [README.ru-RU.md](README.ru-RU.md)
|
||||
|
||||
[PyBitmessage](https://bitmessage.org/) 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
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
pybitmessage:
|
||||
image: bitdeals/pybitmessage
|
||||
build:
|
||||
context: https://git.bitdeals.org/private/bitmessage.git
|
||||
dockerfile: ./docker/Dockerfile
|
||||
image: registry.bitdeals.org/bitmessage
|
||||
environment:
|
||||
- BITMESSAGE_API_USER=bitmessage_api_user
|
||||
- BITMESSAGE_API_PASSWORD=bitmessage_api_password
|
||||
- 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:
|
||||
- 8442:8442
|
||||
- 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
|
||||
|
||||
```sh
|
||||
docker run -d \
|
||||
-e BITMESSAGE_API_USER=bitmessage_api_user \
|
||||
-e BITMESSAGE_API_PASSWORD=bitmessage_api_password \
|
||||
-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
|
||||
-p 8442:8442 \
|
||||
bitdeals/pybitmessage
|
||||
-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
|
||||
@@ -48,11 +70,63 @@ Container images are configured using parameters passed at runtime.
|
||||
|
||||
|Parameter|Function|
|
||||
|:--------|:-------|
|
||||
|-p 8442|XML-RPC API port TCP|
|
||||
|-e BITMESSAGE_API_USER=|XML-RPC API user. Default: `bitmessage_api_user`|
|
||||
|-e BITMESSAGE_API_PASSWORD=|XML-RPC API password. Default: `bitmessage_api_password`|
|
||||
|-e BITMESSAGE_SEED_PHRASE|Create Deterministic Addresses password. Default: `bitmessage_seed_phrase`|
|
||||
|-e BITMESSAGE_SEED_ADDRESSES|Number of Deterministic Addresses to generate. Default: `1`|
|
||||
|-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: `60`|
|
||||
|-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|
|
||||
|-e BITMESSAGE_TRUSTED_PEER|`host:port` of the one peer this node may connect out to; it dials nothing else. Default: empty — the node chooses its own peers. See Notes|
|
||||
|-e BITMESSAGE_SEND_OUTGOING|Whether the node dials out at all, `True` or `False`. Default: `True`. `False` gives a node that only accepts inbound connections — the hub of a private contour|
|
||||
|-e BITMESSAGE_KNOWN_NODES|Comma-separated `host:port` list, written into `knownnodes.dat` on every start in place of whatever was there. Default: empty — the file is left as it is. Also switches the DNS bootstrap off, see Notes|
|
||||
|
||||
# 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`.
|
||||
- **A private contour needs its peers pinned, and a star to pin them into.**
|
||||
PyBitmessage refuses a candidate whose network group (the /16 for IPv4) is
|
||||
already represented among its outbound connections. Every container of one
|
||||
compose project lives in a single /16, so each node keeps exactly one outbound
|
||||
connection, to a peer it picked at random — which as often as not leaves the
|
||||
contour split into components. Give one node `BITMESSAGE_SEND_OUTGOING=False`
|
||||
so it becomes a hub that only accepts (the check looks at outbound connections
|
||||
only, so inbound are not capped by it), point the rest at it with
|
||||
`BITMESSAGE_TRUSTED_PEER=<hub-ip>:8444`, and objects travel spoke → hub →
|
||||
spokes. Use IP addresses, not service names: the sybil check parses the host
|
||||
as an IP, and the `addr` exchange between nodes carries IPs anyway.
|
||||
- **`BITMESSAGE_KNOWN_NODES` is what keeps a private contour private.** A node
|
||||
whose `knownnodes.dat` names a peer outside PyBitmessage's built-in default
|
||||
list stops asking `bootstrap8080.bitmessage.org` for more; without it even a
|
||||
pinned node resolves the public bootstrap host on every start. The file is
|
||||
rewritten on each start, so the variable, not the container's history, is what
|
||||
the node believes on boot.
|
||||
- **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.
|
||||
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
# Общие сведения
|
||||
|
||||
> English version: [README.md](README.md)
|
||||
|
||||
[PyBitmessage](https://bitmessage.org/) — клиент P2P-протокола обмена сообщениями Bitmessage, служащий для отправки шифрованных сообщений как одному адресату, так и множеству подписчиков.
|
||||
|
||||
Клиент PyBitmessage, работающий демоном в docker-контейнере с включённым XML-RPC API.
|
||||
|
||||
Репозиторий описывает только развёртывание в docker.
|
||||
|
||||
# Использование
|
||||
|
||||
Контейнер создаёт детерминированные адреса Bitmessage на основе переменной `BITMESSAGE_SEED_PHRASE`.
|
||||
|
||||
Ниже — примеры, с которых удобно начать создание контейнера.
|
||||
|
||||
У контейнера два порта, и они не взаимозаменяемы. **8442** — XML-RPC API: он
|
||||
полностью управляет демоном и не имеет TLS, поэтому задайте свои учётные данные
|
||||
и оставьте его на loopback. **8444** — P2P-порт Bitmessage: опубликуйте его,
|
||||
чтобы к узлу могли подключаться другие, или не публикуйте, и тогда узел работает
|
||||
только на исходящих. Внутри контейнера демон слушает оба в любом случае.
|
||||
|
||||
## docker-compose
|
||||
|
||||
```yaml
|
||||
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
|
||||
- 8444:8444 # P2P — уберите строку, чтобы остаться на исходящих
|
||||
volumes:
|
||||
- bitmessage:/home/bitmessage
|
||||
|
||||
volumes:
|
||||
bitmessage:
|
||||
```
|
||||
|
||||
## docker cli
|
||||
|
||||
```sh
|
||||
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
|
||||
```
|
||||
|
||||
# Параметры
|
||||
|
||||
Образы контейнера настраиваются параметрами, передаваемыми при запуске.
|
||||
|
||||
|Параметр|Назначение|
|
||||
|:--------|:-------|
|
||||
|-p 127.0.0.1:8442|Порт API. Внутри контейнера демон всегда слушает `0.0.0.0`, поэтому доступность определяет то, что опубликовано|
|
||||
|-p 8444|P2P-порт Bitmessage. Необязательный: без него узел всё равно подключается к пирам сам, просто к нему подключиться нельзя. Публиковать только как `8444:8444` — см. «Замечания»|
|
||||
|-v /home/bitmessage|Каталог данных: `keys.dat` (личность, настройки) и `messages.dat`. Без него после каждого обновления это новый узел|
|
||||
|-e BITMESSAGE_API_USER|Пользователь XML-RPC API. По умолчанию: `bitmessage_api_user` — измените|
|
||||
|-e BITMESSAGE_API_PASSWORD|Пароль XML-RPC API. По умолчанию: `bitmessage_api_password` — измените, см. «Замечания»|
|
||||
|-e BITMESSAGE_SEED_PHRASE|Парольная фраза для создания детерминированных адресов. По умолчанию: генерируется заново при каждом старте, то есть адреса каждый раз другие. Используется только при `BITMESSAGE_SEED_ADDRESSES` больше `0`|
|
||||
|-e BITMESSAGE_SEED_ADDRESSES|Количество создаваемых детерминированных адресов. По умолчанию: `0`|
|
||||
|-e BITMESSAGE_TTL|Срок жизни вновь отправляемых сообщений, в секундах. По умолчанию: `172800`|
|
||||
|-e BITMESSAGE_STOPRESENDINGAFTERXDAYS|Прекратить повторную отправку недоставленного сообщения через X дней. По умолчанию: `30`|
|
||||
|-e BITMESSAGE_APIVARIANT|Предоставляемый API: xml или json-RPC. По умолчанию: `legacy`|
|
||||
|-e BITMESSAGE_MAXTOTALCONNECTIONS|Предел одновременных соединений, входящих и исходящих вместе (`maxoutboundconnections` равен 8, то есть это значение минус 8 — запас на входящие). По умолчанию: `200`, штатное значение PyBitmessage — снижайте, если P2P-порт опубликован|
|
||||
|-e BITMESSAGE_TRUSTED_PEER|`host:port` единственного пира, к которому узел подключается наружу; больше ни к кому. По умолчанию: пусто — узел выбирает пиров сам. См. «Замечания»|
|
||||
|-e BITMESSAGE_SEND_OUTGOING|Подключается ли узел наружу вообще: `True` или `False`. По умолчанию: `True`. При `False` получается узел, который только принимает входящие, — центр приватного контура|
|
||||
|-e BITMESSAGE_KNOWN_NODES|Список `host:port` через запятую; записывается в `knownnodes.dat` при каждом старте вместо того, что там было. По умолчанию: пусто — файл не трогается. Заодно выключает бутстрап по DNS, см. «Замечания»|
|
||||
|
||||
# Замечания
|
||||
|
||||
- `%` в пароле API использовать нельзя: он ломает собственный чтец конфигурации
|
||||
PyBitmessage, и любой вызов API отвечает `500`, притом что `keys.dat`
|
||||
выглядит правильным. Остальные символы допустимы, контейнер их экранирует.
|
||||
- Клиенты обязаны кодировать учётные данные — они попадают в
|
||||
`http://user:password@host:port/`, где `@`, `#`, `/` и `:` меняют разбор URL.
|
||||
Скрипты этого образа кодируют, ваш клиент должен тоже.
|
||||
- Контейнер становится здоровым, когда у демона появилось сетевое соединение,
|
||||
— на новом узле это несколько минут. Начальный период ожидания заодно
|
||||
покрывает стартовый `VACUUM` файла `messages.dat`.
|
||||
- **P2P-порт публикуется только как `8444:8444`.** Пирам демон сообщает порт из
|
||||
собственной конфигурации (`port` в `keys.dat`), а не тот, в который вы его
|
||||
отобразили, поэтому `8555:8444` объявляет сети порт, где никого нет. Для
|
||||
другого порта на хосте нужен `extport` в `keys.dat`, а его этот контейнер не
|
||||
подставляет.
|
||||
- **Свой адрес нигде не указывается.** В version-сообщении демон шлёт
|
||||
захардкоженный `127.0.0.1`, который каждый пир отбрасывает и берёт вместо него
|
||||
IP, увиденный на сокете, а порт — из того же сообщения. Поэтому узел с
|
||||
опубликованным 8444 сеть находит сама, как только он подключится наружу:
|
||||
ни IP, ни DNS-имя хоста задавать негде. Единственное исключение — скрытый
|
||||
сервис Tor, которому нужен явный `onionhostname`.
|
||||
- **Приватному контуру нужны назначенные пиры и звезда, в которую их назначать.**
|
||||
PyBitmessage отвергает кандидата, чья сетевая группа (для IPv4 — /16) уже
|
||||
представлена среди его исходящих соединений. Все контейнеры одного
|
||||
compose-проекта живут в одной /16, поэтому каждый узел удерживает ровно одно
|
||||
исходящее соединение — со случайно выбранным пиром, и контур чаще всего
|
||||
распадается на компоненты. Задайте одному узлу
|
||||
`BITMESSAGE_SEND_OUTGOING=False`, и он станет хабом, который только принимает
|
||||
(проверка смотрит лишь на исходящие, входящие она не ограничивает), остальные
|
||||
направьте на него через `BITMESSAGE_TRUSTED_PEER=<ip-хаба>:8444` — объекты
|
||||
пойдут спица → хаб → спицы. Адреса задавайте IP, а не именами сервисов:
|
||||
проверка разбирает хост как IP, да и обмен `addr` между узлами оперирует IP.
|
||||
- **`BITMESSAGE_KNOWN_NODES` — то, что делает приватный контур приватным.** Узел,
|
||||
у которого в `knownnodes.dat` есть пир не из встроенного списка PyBitmessage,
|
||||
перестаёт спрашивать адреса у `bootstrap8080.bitmessage.org`; без этого даже
|
||||
узел с назначенным пиром при каждом старте резолвит публичный бутстрап-хост.
|
||||
Файл переписывается на каждом старте, поэтому во что узел верит при загрузке,
|
||||
определяет переменная, а не история контейнера.
|
||||
- **Публикация 8444 — осознанный компромисс по безопасности.** Демон работает на
|
||||
Python 2 и уже разбирает недоверенные данные от своих исходящих пиров, так что
|
||||
открытый порт эту поверхность не создаёт — он меняет то, *кто* может
|
||||
подключиться, *когда* и *сколько их*. Разбор до рукопожатия становится доступен
|
||||
кому угодно, а реальный риск — исчерпание ресурсов, а не выполнение кода.
|
||||
Держите `BITMESSAGE_MAXTOTALCONNECTIONS` низким и ограничьте контейнер по
|
||||
памяти и CPU.
|
||||
+13
-4
@@ -1,16 +1,25 @@
|
||||
services:
|
||||
bitmessage:
|
||||
image: bitdeals/pybitmessage:0.6.3.2-ubuntu
|
||||
build: ./docker
|
||||
build:
|
||||
context: ./docker
|
||||
dockerfile: Dockerfile
|
||||
image: registry.bitdeals.org/bitmessage
|
||||
environment:
|
||||
- BITMESSAGE_API_USER=bitmessage_api_user
|
||||
- BITMESSAGE_API_PASSWORD=bitmessage_api_password
|
||||
- BITMESSAGE_SEED_PHRASE=bitmessage_seed_phrase
|
||||
- BITMESSAGE_SEED_PHRASE=
|
||||
- BITMESSAGE_SEED_ADDRESSES=1
|
||||
- BITMESSAGE_TTL=172800
|
||||
- BITMESSAGE_STOPRESENDINGAFTERXDAYS=60
|
||||
- BITMESSAGE_MAXTOTALCONNECTIONS=40
|
||||
ports:
|
||||
- 8442:8442
|
||||
# The API controls the daemon completely and has no TLS, so it never
|
||||
# leaves loopback -- the README has said so all along, this file did not.
|
||||
- 127.0.0.1:8442:8442
|
||||
# P2P. Only 8444:8444 works — the daemon announces its own configured
|
||||
# port to peers, not the one you mapped it to. Drop this line to run
|
||||
# outbound-only.
|
||||
- 8444:8444
|
||||
volumes:
|
||||
- bitmessage:/home/bitmessage
|
||||
volumes:
|
||||
|
||||
+44
-11
@@ -3,23 +3,53 @@ FROM ubuntu:bionic
|
||||
|
||||
SHELL ["/bin/bash", "-exo", "pipefail", "-c"]
|
||||
|
||||
RUN apt-get update
|
||||
|
||||
# Install dependencies
|
||||
RUN apt-get install -yq --no-install-suggests --no-install-recommends \
|
||||
# Install dependencies. update and install share a layer on purpose: split
|
||||
# across two, a cached update feeds install package lists that may be months
|
||||
# stale, and the install then fails or pulls something unintended.
|
||||
RUN apt-get update \
|
||||
&& apt-get install -yq --no-install-suggests --no-install-recommends \
|
||||
build-essential libcap-dev libssl-dev \
|
||||
python-all-dev python-msgpack python-pip python-setuptools \
|
||||
git
|
||||
|
||||
## Do not use cache when building next layers of the image.
|
||||
ARG NOCACHE=0
|
||||
|
||||
WORKDIR /root/PyBitmessage
|
||||
RUN git clone https://github.com/Bitmessage/PyBitmessage .
|
||||
|
||||
# Install
|
||||
RUN pip2 install jsonrpclib .
|
||||
|
||||
FROM ubuntu:bionic-20220401
|
||||
# Raise the SQL-thread startup timeout from the stock 60 s.
|
||||
#
|
||||
# PyBitmessage kills the daemon outright if the SQL thread is not ready within
|
||||
# sql_timeout seconds (class_objectProcessor.py -> os._exit(1)). The startup
|
||||
# VACUUM of a messages.dat that has grown to a few hundred MB does not fit in
|
||||
# 60 s, and since the process dies mid-VACUUM lastvacuumtime is never updated,
|
||||
# so every later start retries the same doomed VACUUM and the node never comes
|
||||
# back. Measured: 26 s for a 264 MB database on an idle host, and the last
|
||||
# start that did survive used 36 s of the 60.
|
||||
#
|
||||
# The greps are load-bearing: the clone above is unpinned, so if upstream ever
|
||||
# moves or renames the constant, a silent no-op sed would ship an image that
|
||||
# looks fixed and is not. Fail the build instead. The .pyc is refreshed because
|
||||
# at runtime /usr/local is root-owned while the daemon runs as bitmessage, so a
|
||||
# stale one can only be recompiled to memory on every start.
|
||||
RUN f=/usr/local/lib/python2.7/dist-packages/pybitmessage/helper_sql.py \
|
||||
&& grep -q '^sql_timeout = 60$' "$f" \
|
||||
&& sed -i 's/^sql_timeout = 60$/sql_timeout = 600/' "$f" \
|
||||
&& grep -q '^sql_timeout = 600$' "$f" \
|
||||
&& rm -f "${f}c" \
|
||||
&& python -c "import py_compile; py_compile.compile('$f')"
|
||||
|
||||
EXPOSE 8442
|
||||
FROM ubuntu:bionic
|
||||
|
||||
# 8442 is the XML-RPC API (keep it on loopback), 8444 the Bitmessage P2P port.
|
||||
# The daemon listens on both regardless; publishing 8444 is what makes the node
|
||||
# reachable for inbound peers.
|
||||
EXPOSE 8442/tcp
|
||||
EXPOSE 8444/tcp
|
||||
|
||||
ENV USER_UID=2000
|
||||
ENV USER_GID=2000
|
||||
@@ -27,9 +57,9 @@ ENV HOME=/home/bitmessage
|
||||
ENV BITMESSAGE_HOME=${HOME}
|
||||
|
||||
COPY --from=0 /usr/local/ /usr/local/
|
||||
COPY --from=0 /root/PyBitmessage/docker/healthy_check.py /usr/local/bin/
|
||||
COPY --from=0 /root/PyBitmessage/docker/seed_addr_gen.py /usr/local/bin/
|
||||
COPY --from=0 /root/PyBitmessage/docker/run.sh /usr/local/bin/
|
||||
COPY ./docker/healthy_check.py /usr/local/bin/
|
||||
COPY ./docker/seed_addr_gen.py /usr/local/bin/
|
||||
COPY ./docker/run.sh /usr/local/bin/
|
||||
|
||||
# Install dependencies
|
||||
RUN apt-get update \
|
||||
@@ -47,7 +77,10 @@ RUN su bitmessage -c "pybitmessage -t"
|
||||
|
||||
CMD ["sh", "/usr/local/bin/run.sh"]
|
||||
|
||||
## Check PyBitmessage active network connections
|
||||
HEALTHCHECK --retries=0 --interval=15s \
|
||||
## Check PyBitmessage active network connections.
|
||||
## The start period covers the startup VACUUM of messages.dat, which takes tens
|
||||
## of seconds once the database reaches a few hundred MB; without it the
|
||||
## container reports unhealthy for that whole window on every restart.
|
||||
HEALTHCHECK --retries=0 --interval=15s --start-period=180s \
|
||||
CMD ["python", "/usr/local/bin/healthy_check.py"]
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import sys
|
||||
import os
|
||||
import urllib
|
||||
import xmlrpclib
|
||||
import json
|
||||
|
||||
@@ -9,7 +10,13 @@ api_user=os.getenv('BITMESSAGE_API_USER', 'bitmessage_api_user') ;
|
||||
api_password=os.getenv('BITMESSAGE_API_PASSWORD', 'bitmessage_api_password') ;
|
||||
api_port=os.getenv('BITMESSAGE_API_PORT', '8442') ;
|
||||
|
||||
api_link="http://{}:{}@127.0.0.1:{}/".format(api_user, api_password, api_port)
|
||||
# Credentials go into a URL, so they must be percent-encoded: '@' splits the
|
||||
# userinfo, '#' truncates the rest, '/' and ':' change what is parsed as host
|
||||
# and port. Without this a strong password fails here while being perfectly
|
||||
# valid in keys.dat. (A '%' in the password is a separate matter -- it breaks
|
||||
# PyBitmessage's own config reader and makes every API call return 500.)
|
||||
api_link="http://{}:{}@127.0.0.1:{}/".format(
|
||||
urllib.quote(api_user, safe=''), urllib.quote(api_password, safe=''), api_port)
|
||||
|
||||
api = xmlrpclib.ServerProxy(api_link)
|
||||
|
||||
|
||||
+159
-29
@@ -1,48 +1,178 @@
|
||||
#!/bin/sh
|
||||
|
||||
export BITMESSAGE_API_USER=${BITMESSAGE_API_USER:-bitmessage_api_user}
|
||||
export BITMESSAGE_API_PASSWORD=${BITMESSAGE_API_PASSWORD:-bitmessage_api_password}
|
||||
export BITMESSAGE_SEED_ADDRESSES=${BITMESSAGE_SEED_ADDRESSES:-1}
|
||||
export BITMESSAGE_API_PORT=${BITMESSAGE_API_PORT:-8442}
|
||||
export BITMESSAGE_TTL=${BITMESSAGE_TTL:-172800}
|
||||
export BITMESSAGE_STOPRESENDINGAFTERXDAYS=${BITMESSAGE_STOPRESENDINGAFTERXDAYS:-30}
|
||||
set -eu
|
||||
|
||||
SEED_FILE="address_seed.txt"
|
||||
test -e "$SEED_FILE" || gosu bitmessage touch "$SEED_FILE"
|
||||
export BITMESSAGE_API_USER="${BITMESSAGE_API_USER:-bitmessage_api_user}"
|
||||
export BITMESSAGE_API_PASSWORD="${BITMESSAGE_API_PASSWORD:-bitmessage_api_password}"
|
||||
export BITMESSAGE_SEED_ADDRESSES="${BITMESSAGE_SEED_ADDRESSES:-0}"
|
||||
export BITMESSAGE_API_PORT="${BITMESSAGE_API_PORT:-8442}"
|
||||
export BITMESSAGE_TTL="${BITMESSAGE_TTL:-172800}"
|
||||
export BITMESSAGE_STOPRESENDINGAFTERXDAYS="${BITMESSAGE_STOPRESENDINGAFTERXDAYS:-30}"
|
||||
export BITMESSAGE_APIVARIANT="${BITMESSAGE_APIVARIANT:-legacy}"
|
||||
export BITMESSAGE_MAXTOTALCONNECTIONS="${BITMESSAGE_MAXTOTALCONNECTIONS:-200}"
|
||||
export BITMESSAGE_TRUSTED_PEER="${BITMESSAGE_TRUSTED_PEER:-}"
|
||||
export BITMESSAGE_SEND_OUTGOING="${BITMESSAGE_SEND_OUTGOING:-True}"
|
||||
export BITMESSAGE_KNOWN_NODES="${BITMESSAGE_KNOWN_NODES:-}"
|
||||
|
||||
# Save seed to file, or use saved seed
|
||||
if [ -n "$BITMESSAGE_SEED_PHRASE" ]
|
||||
# Reject anything but a plain number: this value is written into keys.dat, and
|
||||
# unlike the credentials below it has no business containing characters that
|
||||
# esc() would have to neutralise. A typo here would otherwise land in the config
|
||||
# as a key the daemon silently ignores.
|
||||
case "$BITMESSAGE_MAXTOTALCONNECTIONS" in
|
||||
'' | *[!0-9]*)
|
||||
echo "BITMESSAGE_MAXTOTALCONNECTIONS must be a positive integer" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# sendoutgoingconnections is read with safeGetBoolean, which would take "yes" or
|
||||
# "1" too; keys.dat is written by hand often enough that it is worth keeping one
|
||||
# spelling in it. Anything else is a typo, and a typo here reads as False --
|
||||
# a node that quietly never dials out.
|
||||
case "$BITMESSAGE_SEND_OUTGOING" in
|
||||
[Tt]rue) BITMESSAGE_SEND_OUTGOING=True ;;
|
||||
[Ff]alse) BITMESSAGE_SEND_OUTGOING=False ;;
|
||||
*)
|
||||
echo "BITMESSAGE_SEND_OUTGOING must be True or False" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# host:port with a numeric port -- the form both consumers need. PyBitmessage
|
||||
# does check trustedpeer itself, but by sys.exit() from a constructor deep in
|
||||
# the network thread: the container dies with the reason buried in the daemon
|
||||
# log. Fail here, where the message is the first thing in `docker logs`.
|
||||
check_peer() {
|
||||
case "$1" in
|
||||
*:*) ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
[ -n "${1%:*}" ] || return 1
|
||||
case "${1##*:}" in
|
||||
'' | *[!0-9]*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
if [ -n "$BITMESSAGE_TRUSTED_PEER" ] && ! check_peer "$BITMESSAGE_TRUSTED_PEER"
|
||||
then
|
||||
export BITMESSAGE_SEED_PHRASE
|
||||
grep -q "$BITMESSAGE_SEED_PHRASE" "$SEED_FILE" \
|
||||
|| echo "$BITMESSAGE_SEED_PHRASE" >> "$SEED_FILE"
|
||||
else
|
||||
OLD_SEED="$(tail -n1 $SEED_FILE)"
|
||||
NEW_SEED="$(cat /dev/random | tr -dc "a-z" | head -c32)"
|
||||
export BITMESSAGE_SEED_PHRASE="${OLD_SEED:-$NEW_SEED}"
|
||||
echo "BITMESSAGE_TRUSTED_PEER must be host:port" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "${BITMESSAGE_SEED_PHRASE:-}" ]
|
||||
then
|
||||
BITMESSAGE_SEED_PHRASE="$(cat /dev/random | tr -dc "a-z" | head -c32)"
|
||||
export BITMESSAGE_SEED_PHRASE
|
||||
fi
|
||||
|
||||
# Escape a value for use on the right-hand side of the sed expressions below.
|
||||
# There, a backslash starts an escape, "&" stands for the whole match, and "|"
|
||||
# ends the replacement because it is the delimiter. Unescaped, a password
|
||||
# containing "&" was silently rewritten into something else and one containing
|
||||
# "|" made sed fail outright.
|
||||
esc() {
|
||||
printf '%s' "$1" | sed -e 's/[\\&|]/\\&/g'
|
||||
}
|
||||
|
||||
# this command must be run as root (for bind mounts to container)
|
||||
if [ -f keys.dat ]
|
||||
then
|
||||
chown bitmessage:bitmessage keys.dat
|
||||
chmod 600 keys.dat
|
||||
fi
|
||||
|
||||
# set config values
|
||||
gosu bitmessage sed -i -e "s|\(apiinterface = \).*|\10\.0\.0\.0|g" \
|
||||
-e "s|\(apivariant = \).*|\1legacy|g" \
|
||||
-e "s|\(apiusername = \).*|\1$BITMESSAGE_API_USER|g" \
|
||||
-e "s|\(apipassword = \).*|\1$BITMESSAGE_API_PASSWORD|g" \
|
||||
-e "s|\(apiport = \).*|\1$BITMESSAGE_API_PORT|g" \
|
||||
-e "s|\(apienabled = \).*|\1True|g" \
|
||||
-e "s|\(ttl = \).*|\1$BITMESSAGE_TTL|g" \
|
||||
-e "s|\(stopresendingafterxdays = \).*|\1$BITMESSAGE_STOPRESENDINGAFTERXDAYS|g" \
|
||||
-e "s|\(udp = \).*|\1False|g" keys.dat
|
||||
# maxtotalconnections is the only brake on a node whose P2P port (8444) is
|
||||
# published: it caps inbound sockets at the total minus maxoutboundconnections.
|
||||
# The substitution below is a no-op when the key is missing, which would ship a
|
||||
# node that looks capped and is not -- and the PyBitmessage clone in the
|
||||
# Dockerfile is unpinned, so the stock config is whatever upstream generates
|
||||
# today. Add the key rather than trust the substitution alone; line 1 is the
|
||||
# [bitmessagesettings] header the daemon reads it from.
|
||||
if ! grep -q "^maxtotalconnections = " keys.dat
|
||||
then
|
||||
gosu bitmessage sed -i "1a maxtotalconnections = $BITMESSAGE_MAXTOTALCONNECTIONS" keys.dat
|
||||
fi
|
||||
|
||||
# trustedpeer is absent from the stock keys.dat entirely, so the substitution
|
||||
# below is a no-op until the key exists -- same trap as maxtotalconnections.
|
||||
# The key is added even when the value is empty, which is how it can be taken
|
||||
# back off a node that was pinned before: safeGet returns "" and connectionpool
|
||||
# falls back to chooseConnection. That empty case is also why the anchors here
|
||||
# stop at "=" instead of "= ": with nothing to the right there is no trailing
|
||||
# space to match, and the substitution would never fire again.
|
||||
if ! grep -q "^trustedpeer =" keys.dat
|
||||
then
|
||||
gosu bitmessage sed -i "1a trustedpeer = $(esc "$BITMESSAGE_TRUSTED_PEER")" keys.dat
|
||||
fi
|
||||
|
||||
# Set config values. Every expression is anchored to the start of the line and
|
||||
# names its key in the replacement, so no backreference is involved and nothing
|
||||
# in another section can match. With set -e a failure here now stops the
|
||||
# container instead of leaving the daemon on its previous settings unnoticed --
|
||||
# including the case of a bind mount with no keys.dat at all.
|
||||
gosu bitmessage sed -i \
|
||||
-e "s|^apiinterface = .*|apiinterface = 0.0.0.0|" \
|
||||
-e "s|^apivariant = .*|apivariant = $(esc "$BITMESSAGE_APIVARIANT")|" \
|
||||
-e "s|^apiusername = .*|apiusername = $(esc "$BITMESSAGE_API_USER")|" \
|
||||
-e "s|^apipassword = .*|apipassword = $(esc "$BITMESSAGE_API_PASSWORD")|" \
|
||||
-e "s|^apiport = .*|apiport = $(esc "$BITMESSAGE_API_PORT")|" \
|
||||
-e "s|^apienabled = .*|apienabled = True|" \
|
||||
-e "s|^ttl = .*|ttl = $(esc "$BITMESSAGE_TTL")|" \
|
||||
-e "s|^stopresendingafterxdays = .*|stopresendingafterxdays = $(esc "$BITMESSAGE_STOPRESENDINGAFTERXDAYS")|" \
|
||||
-e "s|^maxtotalconnections = .*|maxtotalconnections = $BITMESSAGE_MAXTOTALCONNECTIONS|" \
|
||||
-e "s|^trustedpeer =.*|trustedpeer = $(esc "$BITMESSAGE_TRUSTED_PEER")|" \
|
||||
-e "s|^sendoutgoingconnections = .*|sendoutgoingconnections = $BITMESSAGE_SEND_OUTGOING|" \
|
||||
-e "s|^udp = .*|udp = False|" keys.dat
|
||||
|
||||
# BITMESSAGE_KNOWN_NODES pins the peers the daemon starts from, and is rewritten
|
||||
# on every start: in a private contour the seed *is* the topology, and a file
|
||||
# left over from an earlier run names nodes that may no longer exist. Seeding it
|
||||
# also switches off the DNS bootstrap -- json_deserialize_knownnodes raises
|
||||
# knownNodesActual for any peer that is neither DEFAULT_NODES nor "self", and
|
||||
# connectionpool calls startBootstrappers only while that flag is down, so the
|
||||
# node never reaches bootstrap8080.bitmessage.org.
|
||||
#
|
||||
# Writing it "only when the file is missing" would have been a permanent no-op:
|
||||
# the image ships a knownnodes.dat, produced by the `pybitmessage -t` run in the
|
||||
# Dockerfile, and a named volume inherits it on first use.
|
||||
if [ -n "$BITMESSAGE_KNOWN_NODES" ]
|
||||
then
|
||||
now="$(date +%s)"
|
||||
nodes=""
|
||||
oldifs="$IFS"
|
||||
IFS=","
|
||||
for peer in $BITMESSAGE_KNOWN_NODES
|
||||
do
|
||||
IFS="$oldifs"
|
||||
if ! check_peer "$peer"
|
||||
then
|
||||
echo "BITMESSAGE_KNOWN_NODES entry '$peer' must be host:port" >&2
|
||||
exit 1
|
||||
fi
|
||||
[ -z "$nodes" ] || nodes="$nodes,"
|
||||
nodes="$nodes
|
||||
{\"stream\": 1, \"peer\": {\"host\": \"${peer%:*}\", \"port\": ${peer##*:}},
|
||||
\"info\": {\"lastseen\": $now, \"rating\": 0, \"self\": false}}"
|
||||
IFS=","
|
||||
done
|
||||
IFS="$oldifs"
|
||||
printf '[%s\n]\n' "$nodes" > knownnodes.dat
|
||||
chown bitmessage:bitmessage knownnodes.dat
|
||||
chmod 600 knownnodes.dat
|
||||
fi
|
||||
|
||||
# generate address from seed
|
||||
for i in {1..4}
|
||||
if [ "$BITMESSAGE_SEED_ADDRESSES" -gt 0 ]
|
||||
then
|
||||
# Four attempts, not a bash {1..4}: this runs under dash, where brace
|
||||
# expansion is literal and the loop would have run once. The call is
|
||||
# idempotent (createDeterministicAddresses returns nothing for an address
|
||||
# that already exists), so these are retries while the API comes up.
|
||||
for i in 1 2 3 4
|
||||
do
|
||||
sleep 15
|
||||
gosu bitmessage /usr/bin/python /usr/local/bin/seed_addr_gen.py
|
||||
done &
|
||||
fi
|
||||
|
||||
exec gosu bitmessage pybitmessage -d
|
||||
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import os
|
||||
import urllib
|
||||
import xmlrpclib
|
||||
|
||||
api_user=os.getenv('BITMESSAGE_API_USER', 'bitmessage_api_user') ;
|
||||
api_password=os.getenv('BITMESSAGE_API_PASSWORD', 'bitmessage_api_password') ;
|
||||
api_port=os.getenv('BITMESSAGE_API_PORT', '8442') ;
|
||||
addr_num=os.getenv('BITMESSAGE_SEED_ADDRESSES', '1') ;
|
||||
addr_num=os.getenv('BITMESSAGE_SEED_ADDRESSES', '0') ;
|
||||
addr_seed=os.getenv('BITMESSAGE_SEED_PHRASE') ;
|
||||
|
||||
api_link="http://{}:{}@127.0.0.1:{}/".format(api_user, api_password, api_port)
|
||||
# Percent-encode the credentials before they go into the URL -- see the same
|
||||
# note in healthy_check.py.
|
||||
api_link="http://{}:{}@127.0.0.1:{}/".format(
|
||||
urllib.quote(api_user, safe=''), urllib.quote(api_password, safe=''), api_port)
|
||||
|
||||
api = xmlrpclib.ServerProxy(api_link)
|
||||
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
# Last Modified: Fri Oct 13 05:01:46 2023
|
||||
include <tunables/global>
|
||||
|
||||
/**/PyBitmessage*.AppImage {
|
||||
include <abstractions/apparmor_api/find_mountpoint>
|
||||
include <abstractions/base>
|
||||
include <abstractions/fonts>
|
||||
include <abstractions/openssl>
|
||||
include <abstractions/user-tmp>
|
||||
|
||||
capability dac_read_search,
|
||||
capability sys_admin,
|
||||
|
||||
network inet dgram,
|
||||
network inet stream,
|
||||
network inet6 dgram,
|
||||
network inet6 stream,
|
||||
network netlink raw,
|
||||
|
||||
mount fstype=fuse.PyBitmessage*.AppImage options=(ro, nosuid, nodev),
|
||||
umount,
|
||||
|
||||
/dev/fuse rw,
|
||||
/etc/fuse.conf r,
|
||||
/etc/gai.conf r,
|
||||
/etc/host.conf r,
|
||||
/etc/hosts r,
|
||||
/etc/nsswitch.conf r,
|
||||
/etc/python2.7/sitecustomize.py r,
|
||||
/etc/resolv.conf r,
|
||||
/etc/xdg/Trolltech.conf rk,
|
||||
/proc/filesystems r,
|
||||
/sys/devices/system/cpu/online r,
|
||||
|
||||
/tmp/*/*/.mount_PyBitm*/ r,
|
||||
/tmp/*/*/.mount_PyBitm*/** r,
|
||||
/tmp/*/*/.mount_PyBitm*/AppRun mrix,
|
||||
/tmp/*/*/.mount_PyBitm*/lib/x86_64-linux-gnu/lib*.so* mr,
|
||||
/tmp/*/*/.mount_PyBitm*/usr/bin/pybitmessage mrix,
|
||||
/tmp/*/*/.mount_PyBitm*/usr/bin/qt.conf mrk,
|
||||
/tmp/*/*/.mount_PyBitm*/usr/lib/python2.7/**.so mr,
|
||||
/tmp/*/*/.mount_PyBitm*/usr/bin/python2.7 rix,
|
||||
/tmp/*/*/.mount_PyBitm*/usr/lib/x86_64-linux-gnu/**/lib*.so* mr,
|
||||
/tmp/*/*/.mount_PyBitm*/usr/lib/x86_64-linux-gnu/lib*.so* mr,
|
||||
/tmp/*/*/.mount_PyBitm*/lib/x86_64/lib*.so mr,
|
||||
/proc/*/cmdline r,
|
||||
/usr/share/themes/** r,
|
||||
owner /run/*/*/sni-qt_python2*/ rw,
|
||||
owner /run/*/*/sni-qt_python2*/icons/ rw,
|
||||
|
||||
/tmp/.mount_PyBitm*/ r,
|
||||
/tmp/.mount_PyBitm*/** r,
|
||||
/tmp/.mount_PyBitm*/AppRun mrix,
|
||||
/tmp/.mount_PyBitm*/lib/x86_64-linux-gnu/lib*.so* mr,
|
||||
/tmp/.mount_PyBitm*/usr/bin/pybitmessage mrix,
|
||||
/tmp/.mount_PyBitm*/usr/bin/qt.conf mrk,
|
||||
/tmp/.mount_PyBitm*/usr/lib/python2.7/**.so mr,
|
||||
/tmp/.mount_PyBitm*/usr/lib/x86_64-linux-gnu/**/lib*.so* mr,
|
||||
/tmp/.mount_PyBitm*/usr/lib/x86_64-linux-gnu/lib*.so* mr,
|
||||
/usr/bin/dash mrix,
|
||||
/usr/bin/fusermount mrix,
|
||||
/usr/bin/fusermount3 mrix,
|
||||
/usr/bin/python2.7 r,
|
||||
/usr/bin/stat mrix,
|
||||
/usr/sbin/ldconfig mrix,
|
||||
/usr/share/icons/ r,
|
||||
/usr/share/icons/Adwaita/* r,
|
||||
/usr/share/icons/Adwaita/** r,
|
||||
/usr/share/icons/gnome/* r,
|
||||
/usr/share/icons/hicolor/* rk,
|
||||
/usr/share/mime/* r,
|
||||
/usr/share/pixmaps/ r,
|
||||
/usr/share/themes/Adwaita/** r,
|
||||
owner /**/PyBitmessage*.AppImage mr,
|
||||
owner /etc/passwd r,
|
||||
owner @{HOME}/tmp* w,
|
||||
owner /run/systemd/userdb/ r,
|
||||
owner /run/*/*/sni-qt_python2_*/ rw,
|
||||
owner /run/*/*/sni-qt_python2_*/icons/ rw,
|
||||
owner /usr/local/share/fonts/** r,
|
||||
owner @{HOME}/.cache/fontconfig/*-le64.cache-7 r,
|
||||
owner @{HOME}/.config/PyBitmessage/ r,
|
||||
owner @{HOME}/.config/PyBitmessage/debug.log w,
|
||||
owner @{HOME}/.config/PyBitmessage/keys.dat rw,
|
||||
owner @{HOME}/.config/PyBitmessage/keys.dat.*.bak w,
|
||||
owner @{HOME}/.config/PyBitmessage/knownnodes.dat rw,
|
||||
owner @{HOME}/.config/PyBitmessage/messages.dat rwk,
|
||||
owner @{HOME}/.config/PyBitmessage/messages.dat-journal rw,
|
||||
owner @{HOME}/.config/PyBitmessage/pybitmessageqt.conf rwk,
|
||||
owner @{HOME}/.config/PyBitmessage/singleton.lock rwk,
|
||||
owner @{HOME}/.config/Trolltech.conf rwk,
|
||||
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
[Unit]
|
||||
Description=Bitmessage appimage service
|
||||
Documentation=https://bitmessage.org/wiki/API_Reference
|
||||
ConditionPathExists=/home/bitmessage/PyBitmessage.AppImage
|
||||
After=network.target
|
||||
Wants=network.target
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
ExecStart=/home/bitmessage/PyBitmessage.AppImage --daemon
|
||||
WorkingDirectory=/home/bitmessage
|
||||
PIDFile=/home/bitmessage/.config/PyBitmessage/singleton.lock
|
||||
KillMode=process
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
#Nice=19
|
||||
|
||||
SyslogIdentifier=bitmessage
|
||||
User=bitmessage
|
||||
Group=bitmessage
|
||||
PrivateTmp=yes
|
||||
|
||||
#ProtectHome=tmpfs
|
||||
#BindPaths=/home/bitmessage/.config/PyBitmessage/
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
#Be careful when downloading form https://artifacts.bitmessage.at. It's just a dump of binaries, it doesn't separate the official with development binaries.
|
||||
#
|
||||
#To find out which is the latest official one, go to github and click on the icon indicating the latest official build result.
|
||||
#
|
||||
#Peter Surda
|
||||
#Bitmessage developer
|
||||
#
|
||||
|
||||
set -ex
|
||||
|
||||
IMAGE_LIST="https://artifacts.bitmessage.at/appimage"
|
||||
LAST_IMAGE="$(wget -q $IMAGE_LIST -O- | grep -oP '[[:digit:]]{5}' | tail -n1)"
|
||||
|
||||
IMAGE_FILENAME="$(wget -q $IMAGE_LIST/$LAST_IMAGE -O- | grep -oE '"PyBitmessage-.*-x86_64.AppImage"')"
|
||||
IMAGE_FILENAME=${IMAGE_FILENAME:1:-1}
|
||||
|
||||
URL="$IMAGE_LIST/$LAST_IMAGE/$IMAGE_FILENAME"
|
||||
|
||||
DEST_FILE="$HOME/$IMAGE_FILENAME"
|
||||
HARD_LINK="$HOME/PyBitmessage.AppImage"
|
||||
|
||||
if ! [ -f $DEST_FILE ]; then
|
||||
wget -c $URL -O $DEST_FILE
|
||||
chmod u+x $DEST_FILE
|
||||
cp -v -fl $DEST_FILE $HARD_LINK
|
||||
fi
|
||||
|
||||
#remove old appimage files
|
||||
ls -1 -tc $HOME/PyBitmessage-.*-x86_64.AppImage 2>/dev/null \
|
||||
| tail -n +3 \
|
||||
| xargs -I{} rm -f $HOME/{}
|
||||
|
||||
Reference in New Issue
Block a user