|
| 1 | +## Sample AWS Blockchain Node Runner app for Bitcoin Nodes |
| 2 | + |
| 3 | +### Overview |
| 4 | + |
| 5 | +This guide walks you through deploying a Bitcoin Core mainnet node in a **Virtual Private Cloud (VPC)** using **Docker**, leveraging **AWS Secrets Manager** for secure credential handling. This configuration ensures robust security and performance while optimizing data transfer costs. |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +### Getting Started |
| 10 | + |
| 11 | +#### Cloning the Repository |
| 12 | + |
| 13 | +First, clone the repository from GitHub to get the necessary files and configurations: |
| 14 | + |
| 15 | +``` |
| 16 | +git clone https://github.com/aws-samples/aws-blockchain-node-runners.git |
| 17 | +cd aws-blockchain-node-runners/lib/bitcoin |
| 18 | +``` |
| 19 | + |
| 20 | +#### Installing Dependencies |
| 21 | + |
| 22 | +Make sure you have AWS CLI installed and configured. Run the following to install any additional dependencies: |
| 23 | + |
| 24 | +``` |
| 25 | +npm install |
| 26 | +``` |
| 27 | + |
| 28 | +### Configuration Management - Generating RPC Authentication |
| 29 | + |
| 30 | +To interact with the Bitcoin Core RPC endpoint within your isolated VPC environment, run the following command before deploying the Bitcoin Node via CDK: |
| 31 | + |
| 32 | +``` |
| 33 | +node generateRPCAuth.js |
| 34 | +``` |
| 35 | + |
| 36 | +For a deeper dive and an overview of credential rotation, see [RPC Authentication -- Deep Dive](#rpc-authentication----deep-dive). |
| 37 | + |
| 38 | + |
| 39 | +### Deploying the Node |
| 40 | + |
| 41 | +To deploy a single node setup, use the following command: |
| 42 | + |
| 43 | +``` |
| 44 | +npx cdk deploy SingleNodeBitcoinCoreStack |
| 45 | +``` |
| 46 | + |
| 47 | +For High Availability (HA) node deployment, use: |
| 48 | + |
| 49 | +``` |
| 50 | +npx cdk deploy HABitcoinCoreNodeStack |
| 51 | +``` |
| 52 | + |
| 53 | +### Deployment Architectures for Bitcoin Nodes |
| 54 | + |
| 55 | +#### Single Node Setup |
| 56 | + |
| 57 | +- A **Bitcoin node** deployed in a **public subnet** continuously synchronizes with the Bitcoin network using outbound connections through a **NAT Gateway**. |
| 58 | +- Outbound communication flows through an **Internet Gateway (IGW)**, but the node itself does not have a **public IP address** or **Elastic IP (EIP)**. |
| 59 | +- The **NAT Gateway** translates the node's private IP into a public IP for outbound connections, but inbound connections are blocked. This ensures that the node functions as an **outbound-only node**, increasing security and reducing data transfer costs. |
| 60 | + |
| 61 | +#### High Availability (HA) Setup |
| 62 | + |
| 63 | +- Deploying **multiple Bitcoin nodes** in an **Auto Scaling Group** enhances fault tolerance and availability. |
| 64 | +- The nodes communicate internally through **private IP addresses** and synchronize through a shared **Application Load Balancer (ALB)**. |
| 65 | +- HA nodes maintain synchronization through the **NAT Gateway** without exposing the RPC endpoint to the public internet. |
| 66 | + |
| 67 | +--- |
| 68 | + |
| 69 | +### Optimizing Data Transfer Costs |
| 70 | + |
| 71 | +By deploying as an **outbound-only node**, data transfer costs are significantly reduced since the node does not serve blockchain data to external peers. With its outbound connections, the node(s) are able to maintain full blockchain synchronization. |
| 72 | + |
| 73 | +--- |
| 74 | +### Accessing and Using RPC with a Single Node Bitcoin Core Instance |
| 75 | + |
| 76 | +To interact with your Bitcoin Core instance, you'll need to use AWS Systems Manager, as direct SSH access is not available. |
| 77 | + |
| 78 | +Follow these steps to make an RPC call: |
| 79 | + |
| 80 | +1. **Access the Instance:** |
| 81 | + - Open the AWS Console and navigate to EC2 Instances. |
| 82 | + - Locate and select the instance named `SingleNodeBitcoinCoreStack/BitcoinSingleNode`. |
| 83 | + - Click the "Connect" button. |
| 84 | + - Choose "Session Manager" from the connection options. |
| 85 | + - Select "Connect" to establish a session. |
| 86 | + |
| 87 | +2. **Execute an RPC Call:** |
| 88 | +Once connected, you can interact with the Bitcoin Core node using Docker commands. |
| 89 | + |
| 90 | +To test the RPC interface, use the following command: |
| 91 | + |
| 92 | +``` |
| 93 | +sudo docker exec -it bitcoind bitcoin-cli getblockchaininfo |
| 94 | +``` |
| 95 | + |
| 96 | + This command executes the `getblockchaininfo` RPC method, which returns current state information about the blockchain. |
| 97 | + |
| 98 | +3. **Interpreting Results:** |
| 99 | + - The output will provide detailed information about the current state of the blockchain, including the current block height, difficulty, and other relevant data. |
| 100 | + - You can use similar commands to execute other RPC methods supported by Bitcoin Core. |
| 101 | + |
| 102 | +--- |
| 103 | +### Secure RPC with AWS Secrets Manager |
| 104 | + |
| 105 | +To securely interact with the Bitcoin Core RPC endpoint from a private subnet within your isolated VPC environment, AWS Secrets Manager is leveraged for credential storage and retrieval. |
| 106 | + |
| 107 | +**Important**: Ensure that you execute the following commands from within a private subnet in the Bitcoin Core Node VPC. A VPC CloudShell environment is suitable for testing purposes. |
| 108 | + |
| 109 | +#### Retrieving Credentials |
| 110 | +First, retrieve the RPC credentials from AWS Secrets Manager: |
| 111 | + |
| 112 | +``` |
| 113 | +export BTC_RPC_AUTH=$(aws secretsmanager get-secret-value --secret-id bitcoin_rpc_credentials --query SecretString --output text) |
| 114 | +``` |
| 115 | + |
| 116 | +#### Single node RPC Call using credentials |
| 117 | +To make an RPC call to a single Bitcoin node, use the following command. Replace <Bitcoin-Node-Private-IP> with the actual private IP address of your Bitcoin node: `<Bitcoin-Node-Private-IP>`. |
| 118 | + |
| 119 | +``` |
| 120 | +curl --user "$BTC_RPC_AUTH" \ |
| 121 | + --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getblockchaininfo", "params": []}' \ |
| 122 | + -H 'content-type: text/plain;' http://<Bitcoin-Node-Private-IP>:8332/ |
| 123 | +``` |
| 124 | + |
| 125 | +#### High Availability (HA) RPC Call using credentials |
| 126 | + |
| 127 | +For high availability setups utilizing an Application Load Balancer (ALB), use the following command. Replace <Load-Balancer-DNS-Name> with your ALB's DNS name: |
| 128 | + |
| 129 | +``` |
| 130 | +curl --user "$BTC_RPC_AUTH" \ |
| 131 | + --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getblockchaininfo", "params": []}' \ |
| 132 | + -H 'content-type: text/plain;' \ |
| 133 | + <Load Balancer DNS Name> |
| 134 | +``` |
| 135 | + |
| 136 | +--- |
| 137 | + |
| 138 | + |
| 139 | +### **Bitcoin Core: Creating an Encrypted Wallet for Payments** |
| 140 | + |
| 141 | +This guide covers how to create an encrypted Bitcoin Core wallet specifically designed for receiving and managing payments in a secure and efficient way. |
| 142 | + |
| 143 | +--- |
| 144 | + |
| 145 | +#### **1. Create an Encrypted Payment Wallet** |
| 146 | + |
| 147 | +To create a wallet specifically for handling payments, use the following command: |
| 148 | + |
| 149 | +``` |
| 150 | +sudo docker exec -it bitcoind bitcoin-cli createwallet "payments" false false "my_secure_passphrase" |
| 151 | +``` |
| 152 | + |
| 153 | +- **payments:** The wallet name, indicating its purpose. |
| 154 | +- **passphrase:** A secure, memorable phrase to protect your funds. |
| 155 | + |
| 156 | +##### **Why Encrypt?** |
| 157 | +- Protects against unauthorized access. |
| 158 | +- Ensures funds are safe even if the server is compromised. |
| 159 | + |
| 160 | +--- |
| 161 | + |
| 162 | +#### **2. Generate a Receiving Address** |
| 163 | + |
| 164 | +To receive payments, generate a new address. You do not need to unlock the wallet for this step: |
| 165 | + |
| 166 | +``` |
| 167 | +sudo docker exec -it bitcoind bitcoin-cli -rpcwallet="payments" getnewaddress "customer1" "bech32" |
| 168 | +``` |
| 169 | + |
| 170 | +- **customer1:** Label to identify payments from this customer. |
| 171 | +- **bech32:** Generates a SegWit address for lower transaction fees. |
| 172 | + |
| 173 | +**Example Output:** |
| 174 | +``` |
| 175 | +bc1qxyzabc123... (Bech32 address) |
| 176 | +``` |
| 177 | + |
| 178 | +--- |
| 179 | + |
| 180 | +#### **3. Monitor Incoming Payments** |
| 181 | + |
| 182 | +To check the balance and verify received payments: |
| 183 | + |
| 184 | +``` |
| 185 | +sudo docker exec -it bitcoind bitcoin-cli -rpcwallet="payments" getbalance |
| 186 | +``` |
| 187 | + |
| 188 | +- Displays the total balance held in the wallet. |
| 189 | + |
| 190 | +To view detailed transactions: |
| 191 | + |
| 192 | +``` |
| 193 | +sudo docker exec -it bitcoind bitcoin-cli -rpcwallet="payments" listtransactions |
| 194 | +``` |
| 195 | + |
| 196 | +--- |
| 197 | + |
| 198 | +#### **4. Sending Payments (Requires Unlocking)** |
| 199 | + |
| 200 | +When making a payout or transferring funds, you need to unlock the wallet: |
| 201 | + |
| 202 | +``` |
| 203 | +sudo docker exec -it bitcoind bitcoin-cli -rpcwallet="payments" walletpassphrase "my_secure_passphrase" 600 |
| 204 | +``` |
| 205 | + |
| 206 | +- Unlocks the wallet for **600 seconds (10 minutes)**. |
| 207 | + |
| 208 | +#### **Send Bitcoin to a specified address:** |
| 209 | + |
| 210 | +``` |
| 211 | +sudo docker exec -it bitcoind bitcoin-cli -rpcwallet="payments" sendtoaddress "bc1qrecipientaddress" 0.01 "Payment for service" |
| 212 | +``` |
| 213 | + |
| 214 | +- Sends **0.01 BTC** with an optional label for record-keeping. |
| 215 | + |
| 216 | + |
| 217 | +#### **5. Lock the Wallet After Use** |
| 218 | + |
| 219 | +For enhanced security, immediately lock the wallet after transactions: |
| 220 | + |
| 221 | +``` |
| 222 | +sudo docker exec -it bitcoind bitcoin-cli -rpcwallet="payments" walletlock |
| 223 | +``` |
| 224 | + |
| 225 | + |
| 226 | + |
| 227 | +#### **6. Backup the Wallet** |
| 228 | + |
| 229 | +To protect your payment data, back up the encrypted wallet regularly: |
| 230 | + |
| 231 | +``` |
| 232 | +sudo docker exec -it bitcoind bitcoin-cli -rpcwallet="payments" backupwallet "/path/to/backup/payments.dat" |
| 233 | +``` |
| 234 | + |
| 235 | + |
| 236 | +#### **Security Tips for Payment Wallets** |
| 237 | +- Use strong passphrases and store them securely offline. |
| 238 | +- Regularly backup your wallet after creating new addresses or receiving payments. |
| 239 | +- Consider setting up automated wallet backups to ensure data integrity. |
| 240 | + |
| 241 | +--- |
| 242 | +### RPC Authentication -- Deep Dive |
| 243 | + |
| 244 | +The `generateRPCAuth.js` script is responsible for generating secure authentication credentials for your Bitcoin node. This script creates a randomly generated **username** and **password** along with a **salt**. The password and salt are then combined and hashed using the **SHA256** algorithm to produce a secure **hash**. This hash is combined with the username to generate the final **rpcauth** parameter that is appended to the `bitcoin.conf` file. |
| 245 | + |
| 246 | +The final `rpcauth` line in `bitcoin.conf` looks like this: |
| 247 | + |
| 248 | +``` |
| 249 | +rpcauth=user_258:c220c5f38690bf880f0dd177547e55f7$77c6ec2dd90e792d60450b01a84cc8c2563a7fb1d0fbd73de49be818fde4b407 |
| 250 | +``` |
| 251 | + |
| 252 | +- The **rpcauth** part consists of a **username**, **salt**, and a **hashed password**, providing robust protection in the case that your `bitcoin.conf` is accessed by an unauthorized entity. |
| 253 | +- The randomly generated **username** and **password** are securely stored in **AWS Secrets Manager**. |
| 254 | + |
| 255 | +By using this script, it ensures that your node has unique and secure credentials. |
| 256 | + |
| 257 | +### Rotating RPC Secrets |
| 258 | + |
| 259 | +To maintain security, rotate RPC credentials periodically using the `generateRPCAuth.js` script: |
| 260 | + |
| 261 | +``` |
| 262 | +node generateRPCAuth.js |
| 263 | +``` |
| 264 | + |
| 265 | +This will update the value of your credentials in Secrets Manager. |
| 266 | + |
| 267 | +**Replacing the Credentials and Restarting the Node to Apply Updates** |
| 268 | + |
| 269 | +- Replace the old `rpcauth` value from the `bitcoin.conf` file with the new one: |
| 270 | + ``` |
| 271 | + sudo docker exec -it bitcoind sh -c "sed -i 's/^rpcauth=.*/rpcauth=<new rpcauth string with escape char>/' /root/.bitcoin/bitcoin.conf" |
| 272 | + ``` |
| 273 | +- Restart the Bitcoin node to apply changes: |
| 274 | + ``` |
| 275 | + sudo docker restart bitcoind |
| 276 | + ``` |
| 277 | + |
| 278 | +#### Verifying the Credential Rotation |
| 279 | + |
| 280 | +Make an RPC call to ensure the new credentials are active: |
| 281 | + |
| 282 | +``` |
| 283 | +curl --user "$BTC_RPC_AUTH" \ |
| 284 | + --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getblockchaininfo", "params": []}' \ |
| 285 | + -H 'content-type: text/plain;' http://<Bitcoin-Node-Private-IP>:8332/ |
| 286 | +``` |
| 287 | + |
| 288 | +--- |
| 289 | + |
| 290 | +### Monitoring and Troubleshooting |
| 291 | + |
| 292 | +Keep your node healthy by monitoring logs and configurations: |
| 293 | + |
| 294 | +- Check recent logs: |
| 295 | + ``` |
| 296 | + sudo docker logs -f --tail 100 bitcoind |
| 297 | + ``` |
| 298 | +- View the configuration file: |
| 299 | + ``` |
| 300 | + cat /home/bitcoin/.bitcoin/bitcoin.conf |
| 301 | + ``` |
| 302 | +- View user data logs: |
| 303 | + ``` |
| 304 | + sudo cat /var/log/cloud-init-output.log |
| 305 | + ``` |
| 306 | + |
| 307 | +--- |
| 308 | + |
| 309 | +### Additional Tips and Best Practices |
| 310 | + |
| 311 | +- Regularly rotate secrets and always remove old `rpcauth` entries before restarting the node. |
| 312 | +- Use **CloudWatch** to monitor node performance and detect issues promptly. |
| 313 | + |
| 314 | +--- |
| 315 | + |
| 316 | +### Conclusion |
| 317 | + |
| 318 | +Deploying and managing a Bitcoin node on AWS requires careful configuration to ensure security, cost efficiency, and high availability. By following the best practices outlined in this guide, you can maintain a robust and secure node while minimizing costs. Stay proactive with monitoring and regularly update credentials to keep your node running smoothly. |
| 319 | + |
0 commit comments