diff --git a/docs/operate/.gitbook.yaml b/docs/operate/.gitbook.yaml index 9c25db3cbb..f81466218e 100644 --- a/docs/operate/.gitbook.yaml +++ b/docs/operate/.gitbook.yaml @@ -4,8 +4,8 @@ redirects: # nodes-and-miners to run-a-node redirects guides-and-tutorials/nodes-and-miners: README.md - guides-and-tutorials/nodes-and-miners/run-a-node-with-docker: run-a-node/run-a-node-with-docker.md - guides-and-tutorials/nodes-and-miners/run-a-node-with-digital-ocean: run-a-node/run-a-node-with-digital-ocean.md + guides-and-tutorials/nodes-and-miners/run-a-node-with-docker: readme/run-a-node-with-docker.md + guides-and-tutorials/nodes-and-miners/run-a-node-with-digital-ocean: readme/run-a-node-with-digital-ocean.md # guides-and-tutorials/run-a-miner to operate/run-a-miner redirects guides-and-tutorials/run-a-miner/mine-mainnet-stacks-tokens: run-a-miner/mine-mainnet-stacks-tokens.md diff --git a/docs/operate/SUMMARY.md b/docs/operate/SUMMARY.md index 16332ea770..b262e76421 100644 --- a/docs/operate/SUMMARY.md +++ b/docs/operate/SUMMARY.md @@ -7,6 +7,7 @@ * [Run a Node with Quicknode](readme/run-a-node-with-quicknode.md) * [Run a Bitcoin Node](readme/run-a-bitcoin-node.md) * [Run a Pruned Bitcoin Node](readme/run-a-pruned-bitcoin-node.md) + * [Run a Node Behind a Proxy](readme/run-a-node-behind-a-proxy.md) * [Run a Miner](run-a-miner/README.md) * [Miner Prerequisites](run-a-miner/miner-prerequisites.md) * [Miner Costs and Fees](run-a-miner/miner-costs-and-fees.md) diff --git a/docs/operate/readme/run-a-node-behind-a-proxy.md b/docs/operate/readme/run-a-node-behind-a-proxy.md new file mode 100644 index 0000000000..882f9fc33b --- /dev/null +++ b/docs/operate/readme/run-a-node-behind-a-proxy.md @@ -0,0 +1,289 @@ +# Run a Node Behind a Proxy + +{% hint style="warning" %} +Running a publicly accessible node exposes your infrastructure to the open internet. The proxy configurations below are starting points, not complete security solutions. **Do this at your own risk.** You are responsible for securing and maintaining your own infrastructure. +{% endhint %} + +If you plan to run a Stacks node with publicly accessible RPC endpoints, it is strongly recommended at a minimum to place the node behind a reverse proxy with rate limiting. Without rate limiting, a public node can be overwhelmed by excessive requests, leading to degraded performance or denial of service. + +This guide provides minimal, production-tested configurations for two popular reverse proxies. **Choose one — you do not need both:** + +- [**Nginx**](#nginx) — simpler configuration, widely used, good baseline rate limiting. +- [**HAProxy**](#haproxy) — more advanced abuse detection via stick tables, HTTP proxying with automatic IP blocking. + +### Ports overview + +A Stacks node deployment typically exposes the following services: + +| Service | Default Port | Protocol | Proxy? | +| ----------- | ------------ | -------- | --------------- | +| Stacks RPC | 20443 | HTTP | Yes | +| Stacks P2P | 20444 | TCP | No | +| Stacks API | 3999 | HTTP | Yes, if running | +| Bitcoin RPC | 8332 | HTTP | Yes, if exposed | +| Bitcoin P2P | 8333 | TCP | No | + +{% hint style="info" %} +The **P2P ports** (20444, 8333) use custom binary protocols for peer-to-peer communication, not HTTP. You can leave them open directly to the network. The proxy configurations below focus on the **RPC/API ports** which serve HTTP traffic and are the primary target for abuse. + +**Optional:** P2P ports can also benefit from rate-limiting. While unlikely, a denial-of-service attack could flood the P2P port so the node only communicates with malicious peers. Adding connection-rate limits on P2P ports won't hurt and provides an extra layer of protection. +{% endhint %} + +## Configure the Stacks node + +Before setting up the proxy, configure your Stacks node so its RPC endpoint is not directly reachable from the public internet (i.e. for stacks-node configuration -`rpc_bind = "127.0.0.1:30443"`). The proxy will be the only public-facing service. + +Since the proxy needs to listen on the standard public ports (e.g. `20443`), the node itself must bind to **different** ports to avoid conflicts. The examples below use offset ports (`30443`, `33999`) for the node's RPC and API, while the proxy owns the public-facing ports (`20443`, `3999`). P2P stays on its standard port and is not proxied. + +### Bare metal + +In your node's configuration file (e.g. `Stacks.toml`), bind the RPC to a localhost address on an offset port: + +{% code title="Stacks.toml" %} + +```toml +[node] +rpc_bind = "127.0.0.1:30443" # Only accessible from localhost, offset port +p2p_bind = "0.0.0.0:20444" # Standard port, open directly to the network +# data_url = "http://:20443" # Uncomment if peers need to reach your RPC +``` + +{% endcode %} + +The proxy will listen on port `20443` and forward RPC traffic to the offset port. P2P binds directly on the standard port `20444` and does not go through the proxy. + +### Docker (stacks-blockchain-docker) + +When running with [stacks-blockchain-docker](https://github.com/stacks-network/stacks-blockchain-docker), the node's ports are controlled by the Docker Compose configuration. By default, ports are exposed on all interfaces (`0.0.0.0`). To restrict the RPC and API to localhost (so only the proxy can reach them), edit `compose-files/common.yaml` and change the port mappings. P2P is published directly on the standard port: + +{% code title="compose-files/common.yaml (port changes)" %} + +```yaml +services: + stacks-blockchain: + ports: + - 127.0.0.1:30443:20443 # RPC: only localhost, host port 30443 + - 0.0.0.0:20444:20444 # P2P: open directly, standard port + - 127.0.0.1:9153:9153 # Metrics: only localhost + stacks-blockchain-api: + ports: + - 127.0.0.1:33999:3999 # API: only localhost, host port 33999 +``` + +{% endcode %} + +The format is `host_ip:host_port:container_port`. The node inside the container keeps its default ports — only the **host** side changes. Offset host ports (`30443`, `33999`) are necessary because the proxy already occupies the standard ports (`20443`, `3999`) on the host. Binding to `127.0.0.1` ensures the container ports are only reachable from the host (where the proxy runs), not from the public internet. P2P is published directly on the standard port `20444`. + +{% hint style="info" %} +Inter-container communication (e.g. the API receiving events from the blockchain node) uses Docker's internal network and service names, not published host ports. These port mapping changes do not affect container-to-container traffic. +{% endhint %} + +## Nginx + +Nginx can serve as a reverse proxy with rate limiting using the `limit_req` module. The configuration below rate-limits the Stacks RPC and Stacks API endpoints. + +**Rate limit parameters explained:** + +- **`rate=5r/s`** — allows a sustained average of 5 requests per second per client IP. Requests beyond this rate are delayed or rejected. +- **`burst=20`** — permits up to 20 requests to queue above the base rate before Nginx starts rejecting. This absorbs short traffic spikes without immediately dropping legitimate requests. +- **`nodelay`** — queued burst requests are forwarded immediately rather than being spaced out over time. Without `nodelay`, excess requests would be throttled to match the base rate. + +The Stacks API zone uses a higher rate (`10r/s`) and larger burst (`40`) because API endpoints typically see more traffic than the node RPC. + +{% code title="Install Nginx" %} + +```bash +sudo apt-get update +sudo apt-get install -y nginx +``` + +{% endcode %} + +{% code title="/etc/nginx/sites-available/stacks-node" %} + +```nginx +limit_req_zone $binary_remote_addr zone=stacks_rpc:10m rate=5r/s; +limit_req_zone $binary_remote_addr zone=stacks_api:10m rate=10r/s; + +server { + listen 20443; + + # Stacks RPC + location / { + limit_req zone=stacks_rpc burst=20 nodelay; + proxy_pass http://127.0.0.1:30443; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } +} + +server { + listen 3999; + + # Stacks API (if running) + location / { + limit_req zone=stacks_api burst=40 nodelay; + proxy_pass http://127.0.0.1:33999; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } +} +``` + +{% endcode %} + +Enable the site and restart Nginx: + +{% code title="Enable and start Nginx" %} + +```bash +sudo ln -s /etc/nginx/sites-available/stacks-node /etc/nginx/sites-enabled/ +sudo nginx -t +sudo systemctl restart nginx +``` + +{% endcode %} + +### Verify + +{% code title="Test the RPC endpoint through the proxy" %} + +```bash +curl -s localhost:20443/v2/info | jq +``` + +{% endcode %} + +## HAProxy + +HAProxy provides fine-grained connection tracking and abuse detection via [stick tables](https://www.haproxy.com/blog/introduction-to-haproxy-stick-tables). The configuration below proxies Stacks RPC and API traffic over HTTP, automatically rejecting clients that exceed request rate thresholds. + +{% hint style="info" %} +Adjust `maxconn`, rate thresholds (`ge 25`), stick-table sizes, and expiry times to suit your traffic patterns. The values below are conservative defaults. +{% endhint %} + +{% code title="Install HAProxy" %} + +```bash +sudo apt-get update +sudo apt-get install -y haproxy +``` + +{% endcode %} + +{% code title="/etc/haproxy/haproxy.cfg" %} + +``` +global + log /dev/log local0 + log /dev/log local1 notice + maxconn 512 + chroot /var/lib/haproxy + stats socket /run/haproxy/admin.sock mode 660 level admin + stats timeout 30s + user haproxy + group haproxy + daemon + +defaults + log global + mode http + option httplog + option dontlognull + timeout connect 5000 + timeout client 50000 + timeout server 50000 + timeout http-request 10s + +# ------------------------------------------- +# Abuse tracking table (shared across all frontends) +# Keeps 100k entries, each expiring after 30m. +# All frontends share this table, so a client that +# exceeds the rate limit on any service is blocked +# from all services. To isolate rate limits per +# service, create separate stick-table backends. +# ------------------------------------------- +backend Abuse + stick-table type ip size 100K expire 30m store gpc0,http_req_rate(10s) + +# ------------------------------------------- +# Stacks RPC (public: 20443 -> node: 30443) +# ------------------------------------------- +frontend stacks_rpc + bind *:20443 + http-request track-sc0 src table Abuse + http-request deny deny_status 429 if { src_get_gpc0(Abuse) gt 0 } + http-request deny deny_status 429 if { src_http_req_rate(Abuse) ge 25 } { src_inc_gpc0(Abuse) ge 0 } + default_backend stacks_rpc_back + +backend stacks_rpc_back + server stacks-node 127.0.0.1:30443 maxconn 100 check inter 10s + +# ------------------------------------------- +# Stacks API (public: 3999 -> node: 33999) +# ------------------------------------------- +frontend stacks_api + bind *:3999 + http-request track-sc0 src table Abuse + http-request deny deny_status 429 if { src_get_gpc0(Abuse) gt 0 } + http-request deny deny_status 429 if { src_http_req_rate(Abuse) ge 25 } { src_inc_gpc0(Abuse) ge 0 } + default_backend stacks_api_back + +backend stacks_api_back + server stacks-api 127.0.0.1:33999 maxconn 100 check inter 10s + +# ------------------------------------------- +# Bitcoin RPC (optional, if you expose it) +# ------------------------------------------- +frontend btc_rpc + bind *:8332 + http-request track-sc0 src table Abuse + http-request deny deny_status 429 if { src_get_gpc0(Abuse) gt 0 } + http-request deny deny_status 429 if { src_http_req_rate(Abuse) ge 25 } { src_inc_gpc0(Abuse) ge 0 } + default_backend btc_rpc_back + +backend btc_rpc_back + server bitcoin 127.0.0.1:8332 maxconn 100 check inter 10s +``` + +{% endcode %} + +{% code title="Enable and start HAProxy" %} + +```bash +sudo systemctl enable haproxy +sudo systemctl start haproxy +``` + +{% endcode %} + +### Verify + +{% code title="Test the RPC endpoint through the proxy" %} + +```bash +curl -s localhost:20443/v2/info | jq +``` + +{% endcode %} + +{% hint style="info" %} +**How the abuse table works:** HAProxy tracks each client IP's HTTP request rate. When a client exceeds the threshold (e.g. 25 HTTP requests in 10 seconds), its `gpc0` counter is incremented and all subsequent requests from that IP are denied with HTTP 429. The stick-table entry expires after 30 minutes, lifting the block automatically. +{% endhint %} + +## Firewall considerations + +Additionally, a host-level firewall adds defense in depth: only the proxy's listening ports and the P2P ports should be reachable from the public internet, while the node's RPC stays accessible only via the proxy (localhost). How you configure this depends on your environment — cloud providers, bare-metal hosts, and container setups all handle firewalling differently. + +{% hint style="info" %} +Refer to your provider's or operating system's firewall documentation for specifics: + +- **AWS** — [Security Groups](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-security-groups.html) +- **GCP** — [VPC Firewall Rules](https://cloud.google.com/firewall/docs/firewalls) +- **Azure** — [Network Security Groups](https://learn.microsoft.com/en-us/azure/virtual-network/network-security-groups-overview) +- **Digital Ocean** — [Cloud Firewalls](https://docs.digitalocean.com/products/networking/firewalls/) +- **Linux (bare metal)** — [UFW](https://help.ubuntu.com/community/UFW), [iptables](https://wiki.archlinux.org/title/Iptables), or [nftables](https://wiki.nftables.org/) +- **Docker** — Docker manipulates `iptables` directly and can bypass host firewall rules. See the [Docker packet filtering docs](https://docs.docker.com/engine/network/packet-filtering-firewalls/) for how to enforce restrictions. +{% endhint %} diff --git a/docs/operate/readme/run-a-node-with-docker.md b/docs/operate/readme/run-a-node-with-docker.md index e070ef1498..abb23033c6 100644 --- a/docs/operate/readme/run-a-node-with-docker.md +++ b/docs/operate/readme/run-a-node-with-docker.md @@ -23,6 +23,23 @@ MacOS with an ARM (M-series chip) processor is NOT recommended The way Docker for Mac on an Arm CPU is designed makes the I/O incredibly slow, and blockchains are _**very**_ heavy on I/O. This only seems to affect MacOS with the M-series chip, other Arm based systems like Raspberry Pi work as expected. {% endhint %} +### Storage + +A fully synced Stacks node can use significant disk space and will continue to grow. If your boot drive doesn't have enough room, mount a dedicated disk and symlink the `persistent-data` directory before starting the node: + +{% code title="Point persistent-data to an external disk" %} +```bash +# If persistent-data already exists, move its contents first +mv persistent-data/mainnet /mnt/stacks-data/mainnet +rmdir persistent-data + +# Create the symlink +ln -s /mnt/stacks-data persistent-data +``` +{% endcode %} + +The Docker volumes write to `persistent-data//`, so the symlink redirects all chainstate, database, and event data to the external disk transparently. + ### Quickstart The `` placeholder used below can be replaced with one of: diff --git a/docs/operate/run-a-node/run-a-bitcoin-node.md b/docs/operate/run-a-node/run-a-bitcoin-node.md deleted file mode 100644 index b935cf30e2..0000000000 --- a/docs/operate/run-a-node/run-a-bitcoin-node.md +++ /dev/null @@ -1,236 +0,0 @@ -# Run a Bitcoin Node - -{% stepper %} -{% step %} -### Requirements - -This guide is written for a Unix based system. It's reasonable to expect some modifications will be required for other operating systems. - -When started, the Bitcoin node will take several days to reach chain tip. - -* Bitcoin Core >= v25.0 - * https://github.com/bitcoin/bitcoin - * https://bitcoincore.org/en/download/ -* Host with a minimum of: - * 2 vCPU (a single dedicated cpu for the bitcoind process) - * 4GB Memory (during sync, more available memory will improve sync time) - * 1TB free disk space -* User account: `bitcoin:bitcoin` -* Chainstate directory located at: `/bitcoin/mainnet` - * `bitcoin` user must have read/write access. -* Config directory located at: `/etc/bitcoin` - * `bitcoin` user must have at least read access -{% endstep %} - -{% step %} -### Add bitcoin user and set file ownership - -Run the following commands: - -{% code title="Create directories and add user" %} -```shell -$ sudo mkdir -p /bitcoin/mainnet -$ sudo mkdir /etc/bitcoin -$ sudo useradd bitcoin -d /bitcoin -$ sudo chown -R bitcoin:bitcoin /bitcoin /etc/bitcoin/ -``` -{% endcode %} -{% endstep %} - -{% step %} -### Bitcoin config - -Below is a sample config used to sync a bitcoin node - feel free to adjust as needed. - -{% hint style="info" %} -If using the [systemd unit below](run-a-bitcoin-node.md#systemd-unit-file), save this file as `/etc/bitcoin/bitcoin.conf` -{% endhint %} - -* `btuser:btcpass` is hardcoded as an rpcauth user/password ([generated using this script](https://github.com/bitcoin/bitcoin/tree/master/share/rpcauth)). -* Only localhost access is allowed (`127.0.0.1`) on the standard mainnet ports. -* `dbcache` is set to the maximum of 16GB. -* Wallet (and wallet rpc calls) are disabled. - -{% code title="Sample /etc/bitcoin/bitcoin.conf" %} -``` -## [rpc] - -# Accept command line and JSON-RPC commands. -server=1 - -# Allow JSON-RPC connections from specified source. -rpcallowip=127.0.0.1/0 - -# Bind to given address to listen for JSON-RPC connections. -rpcbind=127.0.0.1:8332 - -# Username and HMAC-SHA-256 hashed password for JSON-RPC connections. - -# Use the script at https://github.com/bitcoin/bitcoin/tree/master/share/rpcauth to generate - -# Note: may be specified multiple times for different users. -rpcauth=btcuser:18857b4df4b1f0f5e6b1d7884617ab39$de6e02e1da8ee138ee702e13e0637e24679d844756216b066c3aeac4bcac5e10 # btuser:btcpass - -# Optional: rpcwhitelist can restrict listed RPC calls to specific rpcauth users. - -# Uncomment the below the restrict the `limited` user to a small subset of `get` commands - -# rpcauth=limited:350c91a60895b567c4662c27e63e9a41$25188b0f51f2f974dcdc75c1e0d41174e8f7ae19fb96927abf68ac5bc1e8897b # limited:limited - -# rpcwhitelist=limited:getblockchaininfo,getblock,getblockcount,getblockhash,getblockheader,getnetworkinfo - -# rpcwhitelistdefault=0 - -## [core] - -# Specify data directory -datadir=/bitcoin/mainnet - -# Do not keep transactions in the mempool longer than hours (default: 336) -mempoolexpiry=24 - -# Bind to given address and always listen on it (default: 0.0.0.0) -bind=127.0.0.1:8333 - -# Maximum database cache size MiB (4 to 16384, default: 450). In addition, unused mempool memory is shared for this cache -dbcache=16384 - -# Maintain a full transaction index, used by the getrawtransaction rpc call -txindex=1 - -## [wallet] - -# Do not load the wallet and disable wallet RPC calls -disablewallet=1 -``` -{% endcode %} -{% endstep %} - -{% step %} -### Systemd unit file - -Reference: https://github.com/bitcoin/bitcoin/blob/master/contrib/init/bitcoind.service - -Save the following as your systemd unit (for example `/etc/systemd/system/bitcoin.service`): - -{% code title="bitcoind.service" %} -``` -[Unit] -Description=Bitcoin daemon -Documentation=https://github.com/bitcoin/bitcoin/blob/master/doc/init.md - -# https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/ -After=network-online.target -Wants=network-online.target - -[Service] -ExecStart=/usr/bin/bitcoind -pid=/run/bitcoind/bitcoind.pid \ - -conf=/etc/bitcoin/bitcoin.conf \ - -startupnotify='systemd-notify --ready' \ - -shutdownnotify='systemd-notify --stopping' - -# Make sure the config directory is readable by the service user -PermissionsStartOnly=true -ExecStartPre=/bin/chgrp bitcoin /etc/bitcoin - -# Process management -#################### - -Type=notify -NotifyAccess=all -PIDFile=/run/bitcoind/bitcoind.pid - -Restart=on-failure -TimeoutStartSec=infinity -TimeoutStopSec=600 - -# Directory creation and permissions -#################################### - -# Run as bitcoin:bitcoin -User=bitcoin -Group=bitcoin - -# /run/bitcoind -RuntimeDirectory=bitcoind -RuntimeDirectoryMode=0710 - -# /etc/bitcoin -ConfigurationDirectory=bitcoin -ConfigurationDirectoryMode=0710 - -# /var/lib/bitcoind -StateDirectory=bitcoind -StateDirectoryMode=0710 - -# Hardening measures -#################### - -# Provide a private /tmp and /var/tmp. -PrivateTmp=true - -# Mount /usr, /boot/ and /etc read-only for the process. -ProtectSystem=full - -# Deny access to /home, /root and /run/user -ProtectHome=true - -# Disallow the process and all of its children to gain - -# new privileges through execve(). -NoNewPrivileges=true - -# Use a new /dev namespace only populated with API pseudo devices - -# such as /dev/null, /dev/zero and /dev/random. -PrivateDevices=true - -# Deny the creation of writable and executable memory mappings. -MemoryDenyWriteExecute=true - -# Restrict ABIs to help ensure MemoryDenyWriteExecute is enforced -SystemCallArchitectures=native - -[Install] -WantedBy=multi-user.target -``` -{% endcode %} -{% endstep %} - -{% step %} -### Enable and start the Bitcoin service - -Run: - -{% code title="Enable and start service" %} -```shell -$ sudo systemctl daemon-reload -$ sudo systemctl enable bitcoin.service -$ sudo systemctl start bitcoin.service -``` -{% endcode %} -{% endstep %} - -{% step %} -### Track sync progress - -{% hint style="info" %} -Once started, you may track the sync progress: -{% endhint %} - -{% code title="Tail debug log and query RPC" %} -``` -$ sudo tail -f /bitcoin/mainnet/debug.log -2024-12-05T19:35:31Z UpdateTip: new best=00000000000000000058990a84cc8f8eab25dbbd572f123f9190cea7256d7349 height=509258 version=0x20000000 log2_work=88.128280 tx=299522737 date='2018-02-15T03:42:14Z' progress=0.295203 cache=43.5MiB(172740txo) -... -$ bitcoin-cli \ - -rpcconnect=127.0.0.1 \ - -rpcport=8332 \ - -rpcuser=btcuser \ - -rpcpassword=btcpass \ - getblockcount -509016 -``` -{% endcode %} -{% endstep %} -{% endstepper %} diff --git a/docs/operate/run-a-node/run-a-node-with-a-hosted-provider.md b/docs/operate/run-a-node/run-a-node-with-a-hosted-provider.md deleted file mode 100644 index 5a10fe2d30..0000000000 --- a/docs/operate/run-a-node/run-a-node-with-a-hosted-provider.md +++ /dev/null @@ -1,19 +0,0 @@ -# Run a Node with a Hosted Provider - -We're always looking for new hosting providers that enable anyone to run the Stacks Blockchain. Below, you'll find some examples of the current providers that are known to support running a node. - -### Quicknode - -Please refer to the Quicknode Section for instructions on launching an instance with Quicknode. - -### Stacks on Render - -The [render-stacks](https://github.com/stacksfoundation/render-stacks) GitHub repo has instructions so anyone can deploy a Stacks node to the hosted [Render](https://render.com/) service in one click. - -{% hint style="warning" %} -While it is possible to use the free plan with some modifications, it is recommended to run this on a paid plan. -{% endhint %} - -### Stacks on Fly - -The [fly-stacks](https://github.com/stacksfoundation/fly-stacks) GitHub repo has instructions so anyone can deploy a Stacks node to the hosted [Fly](https://fly.io/) service. diff --git a/docs/operate/run-a-node/run-a-node-with-digital-ocean.md b/docs/operate/run-a-node/run-a-node-with-digital-ocean.md deleted file mode 100644 index 5f125b0caa..0000000000 --- a/docs/operate/run-a-node/run-a-node-with-digital-ocean.md +++ /dev/null @@ -1,104 +0,0 @@ -# Run a Node with Digital Ocean - -### Introduction - -This is a step by step guide to deploy the [Stacks Blockchain](https://github.com/stacks-network/stacks-blockchain) on [DigitalOcean](https://digitalocean.com/). - -Build code is hosted on this [Github repository](https://github.com/stacksfoundation/stacks-machine-images) using the [methods from here](https://github.com/stacks-network/stacks-blockchain-docker). - -### Steps - -{% stepper %} -{% step %} -### Create the Droplet from the Marketplace - -Go to the [Stacks Blockchain page](https://marketplace.digitalocean.com/apps/stacks-blockchain) in DigitalOcean's marketplace. Click on `Create Stacks Blockchain Droplet`. -{% endstep %} - -{% step %} -### Choose plan and region - -Choose a plan (it will only allow you to select a droplet that meets the minimum requirements) and your preferred datacenter region. -{% endstep %} - -{% step %} -### Authentication - -Enter a root password or [enable SSH keys](https://docs.digitalocean.com/products/droplets/how-to/add-ssh-keys/) if you prefer. -{% endstep %} - -{% step %} -### Create the Droplet - -You can leave the rest of the options as they are and click on `Create Droplet`. -{% endstep %} - -{% step %} -### Wait for creation - -You will need to wait a few seconds for the droplet to get created. Once created click on it to see more information. -{% endstep %} - -{% step %} -### Access the Droplet - -Congratulations! You are now running the Stacks Blockchain. You can click on `Console` for a terminal window to open or login using SSH to the public IP you've been assigned to with user `root`. -{% endstep %} -{% endstepper %} - -### Getting started after deploying Stacks Blockchain - -Once the droplet is launched, the initial startup can take several minutes while BNS data is imported (this is a one time operation) and the Bitcoin headers are synced. - -To keep track of the progress, you can SSH to the host and view logs: - -```bash -ssh root@your_droplet_public_ipv4 -/opt/stacks-blockchain-docker/manage.sh -n mainnet -a logs -``` - -After the stacks blockchain finishes the initial header sync and starts to sync with its peers, the application ports will open (`20443` and `3999`) and HTTP port `80` will now start proxying requests. - -Use `http://your_droplet_public_ipv4` to access the data directly, with output being similar to: - -```json -{ - "server_version": "stacks-blockchain-api v6.2.3 (master:77ab3ae2)", - "status": "ready", - "chain_tip": { - "block_height": 91820, - "block_hash": "0x06b276e85f238151414616618ae0adaf5eeda4eac6cad5bbefceeb37948ab275", - "index_block_hash": "0x4d7c075d7ab0f90b1dbc175f5c42b7344265d00cfef202dd9681d95388eeed8c", - "microblock_hash": "0xcf4f9037cc10696b2812b617ca105885be625c6acf8ad67e71bb4c09fa6ebb21", - "microblock_sequence": 4 - } -} -``` - -{% hint style="info" %} -For the full list of API endpoints for the Stacks Blockchain, consult the [Hiro API Docs](https://docs.hiro.so/api) -{% endhint %} - -All services are managed by a [systemd unit file](https://github.com/stacksfoundation/stacks-machine-images/blob/master/files/etc/systemd/system/stacks.service) that is set to start on boot. - -Manual control is also possible via the [manage.sh script](https://github.com/stacks-network/stacks-blockchain-docker/blob/master/manage.sh) at `/opt/stacks-blockchain-docker/manage.sh` on the host. - -Full details on how to use the manage.sh script is [available here](https://github.com/stacks-network/stacks-blockchain-docker/blob/master/docs/usage.md). - -### Launching a Droplet using the DigitalOcean API - -In addition to creating a Droplet from the Stacks Blockchain 1-Click App via the control panel, you can also use the [DigitalOcean API](https://digitalocean.com/docs/api). - -As an example, to create a 4GB Stacks Blockchain Droplet in the SFO2 region, you can use the following curl command. You’ll need to either save your [API access token](https://docs.digitalocean.com/reference/api/create-personal-access-token/) to an environment variable or substitute it into the command below. - -{% hint style="info" %} -The `name`, `region` and `size` values below are hardcoded, so adjust as desired. -{% endhint %} - -```bash -$ export TOKEN= -$ curl -X POST -H 'Content-Type: application/json' \ - -H 'Authorization: Bearer '$TOKEN'' -d \ - '{"name":"stacks-blockchain","region":"sfo2","size":"s-2vcpu-4gb","image":"stacksfoundation-stacksblockchain"}' \ - "https://api.digitalocean.com/v2/droplets" -``` diff --git a/docs/operate/run-a-node/run-a-node-with-docker.md b/docs/operate/run-a-node/run-a-node-with-docker.md deleted file mode 100644 index defe4be9b4..0000000000 --- a/docs/operate/run-a-node/run-a-node-with-docker.md +++ /dev/null @@ -1,119 +0,0 @@ -# Run a Node with Docker - -### Stacks Blockchain with Docker - -Run your own Stacks Blockchain node using [docker-compose](https://docs.docker.com/compose/) with just a few commands using [stacks-blockchain-docker](https://github.com/stacks-network/stacks-blockchain-docker) - -### Requirements - -The minimum viable requirements are listed below. - -While you _can_ run a node using these specs, it's _recommended_ to assign more than the minimum for better performance. - -* ⚠️ [docker-compose](https://docs.docker.com/compose/install/) version `2.2.2` or greater is **required** -* **8GB memory if running only a Stacks node** -* **16 GB memory if running Stacks + Bitcoin node** -* **1 Vcpu** ( _minimum of 2 Vcpu is recommended_ ) -* **500GB disk for Stacks node** -* **1TB disk space for Bitcoin node** - -{% hint style="warning" %} -MacOS with an ARM (M-series chip) processor is NOT recommended - -The way Docker for Mac on an Arm CPU is designed makes the I/O incredibly slow, and blockchains are _**very**_ heavy on I/O. This only seems to affect MacOS with the M-series chip, other Arm based systems like Raspberry Pi work as expected. -{% endhint %} - -### Quickstart - -The `` placeholder used below can be replaced with one of: - -* mainnet -* testnet -* mocknet - -{% stepper %} -{% step %} -### Clone the repository - -Clone the stacks-blockchain-docker repository locally and change into the directory: - -{% code title="Clone repository" %} -```bash -git clone https://github.com/stacks-network/stacks-blockchain-docker && cd stacks-blockchain-docker -``` -{% endcode %} -{% endstep %} - -{% step %} -### Start the services - -Start the docker-compose services for the chosen network: - -{% code title="Start services" %} -```bash -./manage.sh -n -a start -``` -{% endcode %} - -{% hint style="info" %} -With an optional HTTP proxy on port 80: - -{% code title="Start with proxy" %} -```bash -./manage.sh -n -a start -f proxy -``` -{% endcode %} -{% endhint %} -{% endstep %} -{% endstepper %} - -### Accessing the services - -{% hint style="info" %} -For networks other than `mocknet`, downloading the initial headers can take several minutes. Until the headers are downloaded, the `/v2/info` endpoints won't return any data. - -Follow the logs to track the sync progress: - -{% code title="Follow logs" %} -```bash -./manage.sh -n -a logs -``` -{% endcode %} -{% endhint %} - -stacks-blockchain: - -* Ports `20443-20444` are exposed on `localhost` - -{% code title="Check stacks-blockchain /v2/info" %} -```bash -curl -sL localhost:20443/v2/info | jq -r -``` -{% endcode %} - -stacks-blockchain-api: - -* Port `3999` is exposed on `localhost` - -{% code title="Check stacks-blockchain-api" %} -```bash -curl -sL localhost:3999 | jq -r -``` -{% endcode %} - -proxy: - -* Port `80` is exposed on `localhost` - -{% code title="Check proxy" %} -```bash -curl -sL localhost/v2/info | jq -r -curl -sL localhost | jq -r -``` -{% endcode %} - -### Upgrades - -{% hint style="warning" %} -For schema-breaking upgrades to running instances of this repo, you'll need to [run an event-replay](https://github.com/stacks-network/stacks-blockchain-docker/blob/master/docs/upgrade.md). -{% endhint %} diff --git a/docs/operate/run-a-node/run-a-node-with-quicknode.md b/docs/operate/run-a-node/run-a-node-with-quicknode.md deleted file mode 100644 index aa06a7868b..0000000000 --- a/docs/operate/run-a-node/run-a-node-with-quicknode.md +++ /dev/null @@ -1,63 +0,0 @@ -# Run a Node with Quicknode - -[QuickNode](https://www.quicknode.com/) is a service for rapidly getting set up with a Stacks node. As an easy and fast alternative to running your own node, you can utilize QuickNode to serve as an API. - -{% stepper %} -{% step %} -### Create a QuickNode account - -Sign up on QuickNode: https://www.quicknode.com/signup -{% endstep %} - -{% step %} -### Create an endpoint - -Once signed in, click "Create an endpoint". Select: - -* Stacks -* your desired network (e.g., mainnet or testnet) -* your desired QuickNode plan level - -After that you'll have an API endpoint URL you can use to connect to Stacks. -{% endstep %} - -{% step %} -### Install the Stacks network package - -Install the `@stacks/network` package in your frontend project. -{% endstep %} - -{% step %} -### Import the network class - -In your frontend code, import the network class: - -{% code title="example.js" %} -```javascript -import { StacksTestnet } from "@stacks/network"; -``` -{% endcode %} -{% endstep %} - -{% step %} -### Configure the network with your QuickNode endpoint - -Create the network instance using your QuickNode endpoint URL: - -{% code title="example.js" %} -```javascript -const network = new StacksTestnet({ url: "" }); -``` -{% endcode %} - -Replace \ with the full endpoint URL provided by QuickNode. -{% endstep %} - -{% step %} -### Use with @stacks/transactions - -You can now call transactions and other Stacks RPC methods as you normally would using the `@stacks/transactions` library, passing the `network` instance where required. - -For an example integration and walkthrough, refer to the Hello Stacks tutorial. -{% endstep %} -{% endstepper %} diff --git a/docs/operate/run-a-node/run-a-pruned-bitcoin-node.md b/docs/operate/run-a-node/run-a-pruned-bitcoin-node.md deleted file mode 100644 index e5b5c22356..0000000000 --- a/docs/operate/run-a-node/run-a-pruned-bitcoin-node.md +++ /dev/null @@ -1,255 +0,0 @@ -# Run a Pruned Bitcoin Node - -This guide is written for a Unix based system. It's reasonable to expect some modifications will be required for other operating systems. - -When started, the pruned Bitcoin node will take roughly \~24 hours to reach chain tip. - -{% hint style="warning" %} -While bitcoin is syncing, it's recommended to keep a stacks-blockchain node at chain tip, or [use a stacks chainstate archive](https://docs.hiro.so/stacks/archive/guides/stacks-blockchain). -{% endhint %} - -Requirements: - -* Bitcoin Core >= v25.0 - * https://github.com/bitcoin/bitcoin - * https://bitcoincore.org/en/download/ -* Host with a minimum of: - * 2 vCPU (a single dedicated cpu for the bitcoind process) - * 4GB Memory (during sync, more available memory will improve sync time) - * 50GB free disk space (actual usage is closer to 20GB) -* User account: `bitcoin:bitcoin` -* Chainstate directory located at: `/bitcoin/mainnet` - * `bitcoin` user must have read/write access. -* Config directory located at: `/etc/bitcoin` - * `bitcoin` user must have at least read access - -Caveats - -[BIP-0159](https://github.com/bitcoin/bips/blob/master/bip-0159.mediawiki) - -In short, this BIP specifies that pruned nodes will advertise the service bit `NODE_NETWORK_LIMITED`, which restricts syncing blocks older than 288 blocks (\~2 days). - -What this means is that in practice, a stacks-blockchain node: - -* Cannot sync from genesis using a pruned node. -* Must not be offline or otherwise down for longer than \~2 days (or 288 Bitcoin blocks). - -{% stepper %} -{% step %} -### Add bitcoin user and set file ownership - -```shell -$ sudo mkdir -p /bitcoin/mainnet -$ sudo mkdir /etc/bitcoin -$ sudo useradd bitcoin -d /bitcoin -$ sudo chown -R bitcoin:bitcoin /bitcoin /etc/bitcoin/ -``` -{% endstep %} - -{% step %} -### Bitcoin Config - -Below is a sample config used to sync a pruned bitcoin node - feel free to adjust as needed. - -{% hint style="info" %} -If using the [systemd unit below](run-a-pruned-bitcoin-node.md#systemd-unit-file), save this file as `/etc/bitcoin/bitcoin.conf` -{% endhint %} - -Notes: - -* `btuser:btcpass` is hardcoded as an rpcauth user/password ([generated using this script](https://github.com/bitcoin/bitcoin/tree/master/share/rpcauth)). -* Only localhost access is allowed (`127.0.0.1`) on the standard mainnet ports. -* Pruning is set to be small, storing only the last 1GB of blocks (for p2p traffic, this is more than enough). -* `dbcache` is set to the maximum of 16GB. -* Wallet (and wallet rpc calls) are disabled. - -``` -## [rpc] - -# Accept command line and JSON-RPC commands. -server=1 - -# Allow JSON-RPC connections from specified source. -rpcallowip=127.0.0.1/0 - -# Bind to given address to listen for JSON-RPC connections. -rpcbind=127.0.0.1:8332 - -# Username and HMAC-SHA-256 hashed password for JSON-RPC connections. - -# Use the script at https://github.com/bitcoin/bitcoin/tree/master/share/rpcauth to generate - -# Note: may be specified multiple times for different users. -rpcauth=btcuser:18857b4df4b1f0f5e6b1d7884617ab39$de6e02e1da8ee138ee702e13e0637e24679d844756216b066c3aeac4bcac5e10 # btuser:btcpass - -# Optional: rpcwhitelist can restrict listed RPC calls to specific rpcauth users. - -# Uncomment the below the restrict the `limited` user to a small subset of `get` commands - -# rpcauth=limited:350c91a60895b567c4662c27e63e9a41$25188b0f51f2f974dcdc75c1e0d41174e8f7ae19fb96927abf68ac5bc1e8897b # limited:limited - -# rpcwhitelist=limited:getblockchaininfo,getblock,getblockcount,getblockhash,getblockheader,getnetworkinfo - -# rpcwhitelistdefault=0 - -## [core] - -# Specify data directory -datadir=/bitcoin/mainnet - -# Do not keep transactions in the mempool longer than hours (default: 336) -mempoolexpiry=24 - -# Bind to given address and always listen on it (default: 0.0.0.0) -bind=127.0.0.1:8333 - -# Maximum database cache size MiB (4 to 16384, default: 450). In addition, unused mempool memory is shared for this cache -dbcache=16384 - -# Maintain a full transaction index, used by the getrawtransaction rpc call (**Running a pruned node requires that this option is disabled**) -txindex=0 - -# Reduce storage requirements by enabling pruning (deleting) of old - -# blocks. This allows the pruneblockchain RPC to be called to - -# delete specific blocks and enables automatic pruning of old - -# blocks if a target size in MiB is provided. This mode is - -# incompatible with -txindex. Warning: Reverting this setting - -# requires re-downloading the entire blockchain. (default: 0 = - -# disable pruning blocks, 1 = allow manual pruning via RPC, >=550 = - -# automatically prune block files to stay under the specified - -# target size in MiB) -prune=1024 # 1GB of chainstate is enough for p2p block data (if using the RPC,this can be adjusted higher to store more blocks) - -## [wallet] - -# Do not load the wallet and disable wallet RPC calls -disablewallet=1 -``` -{% endstep %} - -{% step %} -### Systemd unit file - -ref: https://github.com/bitcoin/bitcoin/blob/master/contrib/init/bitcoind.service - -``` -[Unit] -Description=Bitcoin daemon -Documentation=https://github.com/bitcoin/bitcoin/blob/master/doc/init.md - -# https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/ -After=network-online.target -Wants=network-online.target - -[Service] -ExecStart=/usr/bin/bitcoind -pid=/run/bitcoind/bitcoind.pid \ - -conf=/etc/bitcoin/bitcoin.conf \ - -startupnotify='systemd-notify --ready' \ - -shutdownnotify='systemd-notify --stopping' - -# Make sure the config directory is readable by the service user -PermissionsStartOnly=true -ExecStartPre=/bin/chgrp bitcoin /etc/bitcoin - -# Process management -#################### - -Type=notify -NotifyAccess=all -PIDFile=/run/bitcoind/bitcoind.pid - -Restart=on-failure -TimeoutStartSec=infinity -TimeoutStopSec=600 - -# Directory creation and permissions -#################################### - -# Run as bitcoin:bitcoin -User=bitcoin -Group=bitcoin - -# /run/bitcoind -RuntimeDirectory=bitcoind -RuntimeDirectoryMode=0710 - -# /etc/bitcoin -ConfigurationDirectory=bitcoin -ConfigurationDirectoryMode=0710 - -# /var/lib/bitcoind -StateDirectory=bitcoind -StateDirectoryMode=0710 - -# Hardening measures -#################### - -# Provide a private /tmp and /var/tmp. -PrivateTmp=true - -# Mount /usr, /boot/ and /etc read-only for the process. -ProtectSystem=full - -# Deny access to /home, /root and /run/user -ProtectHome=true - -# Disallow the process and all of its children to gain - -# new privileges through execve(). -NoNewPrivileges=true - -# Use a new /dev namespace only populated with API pseudo devices - -# such as /dev/null, /dev/zero and /dev/random. -PrivateDevices=true - -# Deny the creation of writable and executable memory mappings. -MemoryDenyWriteExecute=true - -# Restrict ABIs to help ensure MemoryDenyWriteExecute is enforced -SystemCallArchitectures=native - -[Install] -WantedBy=multi-user.target -``` -{% endstep %} - -{% step %} -### Enable and start the Bitcoin service - -```shell -$ sudo systemctl daemon-reload -$ sudo systemctl enable bitcoin.service -$ sudo systemctl start bitcoin.service -``` -{% endstep %} - -{% step %} -### Track sync progress - -{% hint style="info" %} -Once started, you may track the sync progress: - -``` -$ sudo tail -f /bitcoin/mainnet/debug.log -2024-12-05T19:35:31Z UpdateTip: new best=00000000000000000058990a84cc8f8eab25dbbd572f123f9190cea7256d7349 height=509258 version=0x20000000 log2_work=88.128280 tx=299522737 date='2018-02-15T03:42:14Z' progress=0.295203 cache=43.5MiB(172740txo) -... -$ bitcoin-cli \ - -rpcconnect=127.0.0.1 \ - -rpcport=8332 \ - -rpcuser=btcuser \ - -rpcpassword=btcpass \ - getblockcount -509016 -``` -{% endhint %} -{% endstep %} -{% endstepper %}