Skip to content

Commit

Permalink
feat: add mainnet Docker Compose skeleton (#1086)
Browse files Browse the repository at this point in the history
* feat: add mainnet Docker Compose skeleton

* Fix log group

* Add chains override

* Add back `public_endpoints`

* Update `signer-config.toml`

* Rename and prepare Stacks config

* Add warning to README

* Add `container_name`

* Fix `bitcoin` config

* Update README

* Add `events_observer`

* Fix Bitcoin BITCOIN_DATA

* Fix nit

* Add note

* Remove unused variable

* Point to config

* Use anchors for port forwarding

* Fix broken link

* Fix port forwarding

* Drop `coinstatsindex`

* Add Docker and Compose version

* Bump to RC1 and add metrics

* Bump testnet config as well

* Bump to RC2

* Bump to RC3

* Bump testnet too

* Push metrics to Cloudwatch

* Restart on failure

* Bump Stacks node version

* Bump to RC4

* Bump in testnet as well
  • Loading branch information
aldur authored Dec 19, 2024
1 parent 6b7e313 commit a91c2d0
Show file tree
Hide file tree
Showing 15 changed files with 624 additions and 7 deletions.
3 changes: 1 addition & 2 deletions blocklist-client/src/config/default.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@
host = "127.0.0.1"
port = 3030


[assessment]
assessment_method = "sanctions"
assessment_method = "sanctions"
1 change: 1 addition & 0 deletions docker/mainnet/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.env
106 changes: 106 additions & 0 deletions docker/mainnet/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# sBTC signers: `mainnet` Docker Compose

This `README` details how to set up a sBTC signer through Docker Compose for a
`mainnet` deployment.

## Requirements

[This documentation page](https://docs.stacks.co/guides-and-tutorials/sbtc/how-to-run-sbtc-signer)
details how to setup Bitcoin and Stacks full nodes.

The [`./nodes` folder](./nodes/) contains a Docker Compose override which shows
how to run the Bitcoin and Stacks full nodes.

### Chainstate archives

In case you need to quickly sync a Bitcoin or Stacks full-node, here are two
archives you can use.

Warning: restoring from the archive will require 2x disk space (to download the
archive first and then unzip its contents).

| Network | Archive |
| ------- | ---------------------------------------------------------------------------------------------------- |
| Bitcoin | [archive](https://bitcoin-chainstate-prod.s3.us-east-1.amazonaws.com/data.tar.gz) |
| Stacks | [archive](https://archive.hiro.so/mainnet/stacks-blockchain/mainnet-stacks-blockchain-latest.tar.gz) |

Extract to `/mnt/bitcoin` and `/mnt/stacks` if using the provided Docker Compose
configuration for the nodes as well.

## Configuration

All configuration is handled through environmental variables, which are parsed
at the beginning of the provided `docker-compose.yml` file:

```bash
$ cat docker-compose.yml | grep Required | cut -d " " -f 5

${POSTGRES_PASSWORD}
${BITCOIN_RPC_USERNAME}
${BITCOIN_RPC_PASSWORD}
${BITCOIN_RPC_HOST}
${STACKS_RPC_HOST}
${SIGNER_SIGNER__PRIVATE_KEY}
${EMILY_API_KEY}
${BLOCKLIST_CLIENT_RISK_ANALYSIS__API_KEY}
${STREAM_NAME}
${AWS_ACCESS_KEY_ID}
${AWS_SECRET_ACCESS_KEY}
```

`docker-compose` will pick them up from a `.env` file in the same folder as the `docker-compose.yml` file.
You can create the `.env` structure as follows:

```bash
cat docker-compose.yml | grep Required | cut -d " " -f 5 | sed -E 's/\$\{([^}]+)\}/\1=/g' | tee .env

POSTGRES_PASSWORD=
BITCOIN_RPC_USERNAME=
BITCOIN_RPC_PASSWORD=
BITCOIN_RPC_HOST=
STACKS_RPC_HOST=
SIGNER_SIGNER__PRIVATE_KEY=
EMILY_API_KEY=
BLOCKLIST_CLIENT_RISK_ANALYSIS__API_KEY=
STREAM_NAME=
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
```

## Best practices

Please refer to [this documentation
page](https://docs.stacks.co/guides-and-tutorials/sbtc/best-practices-for-running-an-sbtc-signer)
for best practices.

## Run the stack

You will need a recent-enough version of Docker and Docker Compose. The
following have been confirmed to work:

```bash
$ docker --version
Docker version 27.4.0, build bde2b89

$ docker compose version
Docker Compose version v2.31.0
```

After creating the `.env` that includes the configuration, you can use the
following to spin up the stack.

```bash
sudo docker compose --env-file .env up
```

### Run the Stacks and Bitcoin nodes too

Alternatively, you can run the full stack (including Bitcoin and Stacks nodes)
as follows:

```bash
sudo docker compose --env-file .env -f docker-compose.yml -f nodes/docker-compose.chains.yml up
```

This requires the chain-state for Bitcoin and Stacks to be present,
respectively, at `/mnt/bitcoin` and `/mnt/stacks`.
108 changes: 108 additions & 0 deletions docker/mainnet/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
x-common-vars:
# Postgres
- &POSTGRES_PASSWORD ${POSTGRES_PASSWORD} # Required
- &POSTGRES_DB ${POSTGRES_DB:-signer}
- &POSTGRES_USER ${POSTGRES_USER:-postgres}
- &POSTGRES_HOST ${POSTGRES_HOST:-postgres}
- &POSTGRES_PORT ${POSTGRES_PORT:-5432}
# Bitcoin RPC
- &BITCOIN_RPC_USERNAME ${BITCOIN_RPC_USERNAME} # Required
- &BITCOIN_RPC_PASSWORD ${BITCOIN_RPC_PASSWORD} # Required
- &BITCOIN_RPC_HOST ${BITCOIN_RPC_HOST} # Required
- &BITCOIN_RPC_PORT ${BITCOIN_RPC_PORT:-8332}
# Bitcoin ZMQ endpoint
- &BITCOIN_ZMQ_HOST ${BITCOIN_ZMQ_HOST:-${BITCOIN_RPC_HOST}}
- &BITCOIN_ZMQ_PORT ${BITCOIN_ZMQ_PORT:-28332}
# Stacks RPC
- &STACKS_RPC_HOST ${STACKS_RPC_HOST} # Required
- &STACKS_RPC_PORT ${STACKS_RPC_PORT:-20443}
# Signer private key
- &SIGNER_SIGNER__PRIVATE_KEY ${SIGNER_SIGNER__PRIVATE_KEY} # Required
# Emily
- &EMILY_API_KEY ${EMILY_API_KEY} # Required
# Blocklist client
- &BLOCKLIST_CLIENT_RISK_ANALYSIS__API_KEY ${BLOCKLIST_CLIENT_RISK_ANALYSIS__API_KEY} # Required
# Vector, Cloudwatch log streaming
- &STREAM_NAME ${STREAM_NAME} # Required
- &AWS_ACCESS_KEY_ID ${AWS_ACCESS_KEY_ID} # Required
- &AWS_SECRET_ACCESS_KEY ${AWS_SECRET_ACCESS_KEY} # Required

services:
postgres:
container_name: postgres
restart: on-failure
image: postgres:16.3-alpine
stop_grace_period: 5s
environment:
POSTGRES_DB: *POSTGRES_DB
POSTGRES_USER: *POSTGRES_USER
POSTGRES_PASSWORD: *POSTGRES_PASSWORD
volumes:
- ./postgres/data:/var/lib/postgresql/data

sbtc-signer:
container_name: sbtc-signer
restart: on-failure
image: blockstack/sbtc:signer-0.0.9-rc4
entrypoint:
- /bin/bash
- -c
- |
envsubst < /signer-config.toml.in > /signer-config.toml
/usr/local/bin/signer -c /signer-config.toml --migrate-db -o json | tee /logs/sbtc_signer.logs
depends_on:
- postgres
environment:
RUST_LOG: info,signer=debug
# Bitcoin RPC
BITCOIN_RPC_USERNAME: *BITCOIN_RPC_USERNAME
BITCOIN_RPC_PASSWORD: *BITCOIN_RPC_PASSWORD
BITCOIN_RPC_HOST: *BITCOIN_RPC_HOST
BITCOIN_RPC_PORT: *BITCOIN_RPC_PORT
# Bitcoin ZMQ endpoint
BITCOIN_ZMQ_HOST: *BITCOIN_ZMQ_HOST
BITCOIN_ZMQ_PORT: *BITCOIN_ZMQ_PORT
# Stacks RPC
STACKS_RPC_HOST: *STACKS_RPC_HOST
STACKS_RPC_PORT: *STACKS_RPC_PORT
# Signer private key
SIGNER_SIGNER__PRIVATE_KEY: *SIGNER_SIGNER__PRIVATE_KEY
# Emily
EMILY_API_KEY: *EMILY_API_KEY
# Postgres
POSTGRES_DB: *POSTGRES_DB
POSTGRES_USER: *POSTGRES_USER
POSTGRES_PASSWORD: *POSTGRES_PASSWORD
POSTGRES_HOST: *POSTGRES_HOST
POSTGRES_PORT: *POSTGRES_PORT
volumes:
- ./sbtc-signer/signer-config.toml.in:/signer-config.toml.in:ro
- ./logs:/logs
ports:
- "4122:4122" # P2P communication between sBTC signers
- "8801:8801" # So that Stacks event-observer can reach the sBTC signer
- "9184:9184" # Prometheus metrics

blocklist-client:
restart: on-failure
container_name: blocklist-client
image: blockstack/sbtc:blocklist-client-0.0.9-rc4
entrypoint: "/usr/local/bin/blocklist-client"
environment:
BLOCKLIST_CLIENT_RISK_ANALYSIS__API_KEY: *BLOCKLIST_CLIENT_RISK_ANALYSIS__API_KEY
BLOCKLIST_CLIENT_RISK_ANALYSIS__API_URL: https://public.chainalysis.com
BLOCKLIST_CLIENT_ASSESSMENT__ASSESSMENT_METHOD: sanctions
BLOCKLIST_CLIENT_SERVER__HOST: "0.0.0.0"
BLOCKLIST_CLIENT_SERVER__PORT: "3032"

vector:
container_name: vector
image: timberio/vector:0.42.0-debian
volumes:
- ./logs:/logs
- ./vector/vector.yaml:/etc/vector/vector.yaml:ro
environment:
STREAM_NAME: *STREAM_NAME
AWS_ACCESS_KEY_ID: *AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY: *AWS_SECRET_ACCESS_KEY
VECTOR_LOG: INFO
Empty file added docker/mainnet/logs/.gitkeep
Empty file.
75 changes: 75 additions & 0 deletions docker/mainnet/nodes/docker-compose.chains.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
x-common-vars:
# Bitcoin RPC
- &BITCOIN_RPC_USERNAME ${BITCOIN_RPC_USERNAME} # Required
- &BITCOIN_RPC_PASSWORD ${BITCOIN_RPC_PASSWORD} # Required
- &BITCOIN_RPC_PORT ${BITCOIN_RPC_PORT:-8332}
- &BITCOIN_ZMQ_PORT ${BITCOIN_ZMQ_PORT:-28332}
# Stacks RPC
- &STACKS_RPC_PORT ${STACKS_RPC_PORT:-20443}

services:
bitcoin:
image: bitcoin/bitcoin:28.0
container_name: bitcoin
restart: on-failure:3
ports:
- name: bitcoin_rpc
target: *BITCOIN_RPC_PORT
published: *BITCOIN_RPC_PORT
- name: bitcoin_zmq
target: *BITCOIN_ZMQ_PORT
published: *BITCOIN_ZMQ_PORT
- "8333:8333" # I2P
- "8334:8334" # P2P
volumes:
- /mnt/bitcoin:/bitcoin
environment:
BITCOIN_RPC_USERNAME: *BITCOIN_RPC_USERNAME
BITCOIN_RPC_PASSWORD: *BITCOIN_RPC_PASSWORD
BITCOIN_RPC_PORT: *BITCOIN_RPC_PORT
BITCOIN_ZMQ_PORT: *BITCOIN_ZMQ_PORT
BITCOIN_DATA: /bitcoin/data
entrypoint:
- /bin/bash
- -c
- |
set -e
bitcoind \
-server \
-datadir=$${BITCOIN_DATA} \
-rpcbind=0.0.0.0 \
-rpcuser=$${BITCOIN_RPC_USERNAME} \
-rpcpassword=$${BITCOIN_RPC_PASSWORD} \
-rpcport=$${BITCOIN_RPC_PORT} \
-rpcallowip=0.0.0.0/0 \
-rpcallowip=::/0 \
-txindex \
-zmqpubhashblock="tcp://*:$${BITCOIN_ZMQ_PORT}" \
-zmqpubrawblock="tcp://*:$${BITCOIN_ZMQ_PORT}"
stacks-blockchain:
image: blockstack/stacks-blockchain:3.1.0.0.2
container_name: stacks-blockchain
restart: on-failure:3
ports:
- name: stacks_rpc
target: *STACKS_RPC_PORT
published: *STACKS_RPC_PORT
- 20444:20444 # P2P
- 9153:9153 # Metrics
volumes:
- ./nodes/stacks/Config.toml.in:/stacks/Config.toml.in:ro
- /mnt/stacks:/stacks
environment:
BITCOIN_RPC_USERNAME: *BITCOIN_RPC_USERNAME
BITCOIN_RPC_PASSWORD: *BITCOIN_RPC_PASSWORD
BITCOIN_RPC_PORT: *BITCOIN_RPC_PORT
STACKS_RPC_PORT: *STACKS_RPC_PORT
entrypoint:
- /bin/bash
- -c
- |
set -ex
apt-get update && apt-get install -y gettext --no-install-recommends
envsubst < /stacks/Config.toml.in > /stacks/Config.toml
/bin/stacks-node start --config /stacks/Config.toml
25 changes: 25 additions & 0 deletions docker/mainnet/nodes/stacks/Config.toml.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[node]
working_dir = "/stacks"
rpc_bind = "0.0.0.0:$STACKS_RPC_PORT"
p2p_bind = "0.0.0.0:20444"
prometheus_bind = "0.0.0.0:9153"

bootstrap_node = "02196f005965cebe6ddc3901b7b1cc1aa7a88f305bb8c5893456b8f9a605923893@seed.mainnet.hiro.so:20444,02539449ad94e6e6392d8c1deb2b4e61f80ae2a18964349bc14336d8b903c46a8c@cet.stacksnodes.org:20444,02ececc8ce79b8adf813f13a0255f8ae58d4357309ba0cedd523d9f1a306fcfb79@sgt.stacksnodes.org:20444,0303144ba518fe7a0fb56a8a7d488f950307a4330f146e1e1458fc63fb33defe96@est.stacksnodes.org:20444"

[burnchain]
chain = "bitcoin"
mode = "mainnet"
peer_host = "bitcoin"
username = "$BITCOIN_RPC_USERNAME"
password = "$BITCOIN_RPC_PASSWORD"
rpc_port = $BITCOIN_RPC_PORT
peer_port = 8333

[connection_options]
private_neighbors = false

[[events_observer]]
endpoint = "sbtc-signer:8801"
events_keys = [
"SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-registry::print",
]
Empty file.
1 change: 1 addition & 0 deletions docker/mainnet/sbtc-signer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.toml
Loading

0 comments on commit a91c2d0

Please sign in to comment.