Run a Bitcoin Knots full node on the Akash Network with authenticated RPC access, automatic credential setup, and configurable runtime options.
andrey01/bitcoin-knots:v28.1.0@sha256:f272b90297f89d9fe819548b5928367396359e3eea172d622758b90151ce12a3
- Verified install via Luke Dashjr's PPA
tinias PID 1 for clean signal handling- Automatic
rpcauth.confgeneration whenRPCUSERandRPCPASSWORDare set - Optional
BITCOIN_ARGSfor runtime flags (defaults to-txindex=1) - Adds the following flags when RPC credentials are provided:
-rpcauthfile=/root/.bitcoin/rpcauth.conf
-server=1
-rpcbind=0.0.0.0
-rpcallowip=0.0.0.0/0
- Persistent volume support via
/root
env:
- RPCUSER=user
- RPCPASSWORD=changeme123
- BITCOIN_ARGS=-txindex=1 -dbcache=2048You can omit BITCOIN_ARGS entirely — it defaults to -txindex=1.
If RPCUSER and RPCPASSWORD are set, the image automatically enables authenticated RPC access using rpcauthfile.
Note: This setup does not encrypt traffic. For secure communication, use a reverse proxy to terminate TLS.
Expose port 8332 in your SDL and access RPC via:
NOTE: You can query HTTP or HTTPS. Not all providers offer signed HTTPS
*.ingress.<provider>endpoints, so add-kto skip TLS certificate verification (not recommended for production). When you expose a serviceas: 80, Akash’s ingress controller also makes the app available over HTTPS using a self-signed TLS certificate. The ingress controller always terminates TLS and forwards plain HTTP to the application.
curl -s -u user:changeme123 -X POST \
-H 'Content-Type: application/json' \
--data '{"jsonrpc":"1.0","id":"curl","method":"getblockchaininfo","params":[]}' \
http://vk2hrmj9mh92732apu9glbkte4.ingress.europlots.com | jq -r .bitcoin-cli \
-rpcconnect=vk2hrmj9mh92732apu9glbkte4.ingress.europlots.com \
-rpcport=80 \
-rpcuser=user \
-rpcpassword=changeme123 \
getblockchaininfo
bitcoin-clidoes not support HTTPS, only plain HTTP.
| Action | Safe over HTTP? | Notes |
|---|---|---|
getblockchaininfo, getpeerinfo, getmempoolinfo |
✅ Yes | Read-only RPCs are low-risk over plain HTTP. |
sendrawtransaction, sendtoaddress, walletpassphrase |
❌ No | These expose sensitive data — only use over HTTPS or a secure channel. |
RPC over HTTPS (bitcoin-cli) |
❌ Not supported | Use curl or a TLS proxy. |
- Use a reverse proxy with TLS (e.g., NGINX or Caddy) for encrypted access
- Use curl over HTTPS for secure transaction broadcasting
- Use Tor or VPN to obscure your IP when making RPC calls
- Never expose RPC with full access (
-rpcallowip=0.0.0.0/0) without authentication
By default, Akash assigns random NodePorts (in the 30000–32767 range) when you expose services like the Bitcoin P2P port 8333. This means your node:
- Can make outbound connections (sync, broadcast, etc.)
- Cannot accept inbound P2P connections over port 8333 (default) unless the correct port mapping is manually advertised (which is not currently possible to detect from inside the container)
To support full peer-to-peer functionality and help the Bitcoin network, you can request a leased static public IP using Akash’s IP leasing feature.
NOTE: Not all Akash providers currently enabled the IP leasing, so this option is kept commented out by default.
-
Define an
endpoints:block in your SDL:endpoints: bitcoind: kind: ip
-
Use the endpoint under
exposefor the P2P tcp port8333:expose: - port: 8333 proto: tcp to: - global: true ip: bitcoind
-
Update
BITCOIN_ARGSto advertise the correct IP:- BITCOIN_ARGS=-txindex=1 -dbcache=2048 -externalip=${IP_ADDR}ℹ️ As of now, leased IPs are not injected into the container as environment variables. See GitHub issue #284. As a workaround, you can retrieve the public IP at runtime with:
export IP_ADDR=$(curl -s ifconfig.me)
- Fallback behavior: Without a leased IP, Akash maps exposed ports to random NodePorts, making your node unreachable for inbound P2P connections over port 8333 (default).
JSON-RPC (port
8332) remains reachable via Akash ingress and is unaffected. - Provider support: Not all Akash providers currently support IP leasing. For this reason, the IP-related expose rule (
ip: bitcoind) is often commented out by default in the SDL. - Always confirm that your chosen provider supports IP leases and that one has been allocated to your deployment before enabling this feature.
You can optionally deploy this Bitcoin Knots node alongside the full mempool.space stack — including frontend, backend, and MariaDB — using the deploy-mempool.yaml file provided in this repository.
This setup enables a fully integrated block explorer UI, REST API, and WebSocket interface over Akash ingress.
Note: Persistent backend cache (
/backend/cache) is currently not backed by a persistent volume due to permission issues withUSER 1000and root-owned persistent storage (Ceph) mounts. The cache functionality itself still works, but it is ephemeral and will be lost on Pod restart. You can rebuild the Docker image withUSER rootto enable persistent volume mounting, though this reduces container isolation and is not recommended for production (ref).
mempool/electrs is Blockstream's electrs fork used for address lookups.
When using bitcoind alone as the backend, the Mempool UI does not support address lookups and will show errors like:
❌
405 Method Not Allowed: Address lookups cannot be used with bitcoind as backend.❌ "Error loading address data. There are too many transactions on this address, more than your backend can handle."
To enable full address lookup support, we integrate mempool/electrs — the same high-performance backend used by mempool.space.
This Electrum server enables:
- Rich transaction history per address
- Fast lookup performance (even for addresses with thousands of UTXOs)
- Better UI support for wallets and explorers
| Backend | Address Lookup | MEMPOOL_BACKEND | Notes |
|---|---|---|---|
bitcoind |
❌ No | none |
Basic explorer-only mode — no address history |
romanz/electrs |
electrum |
Lightweight, but struggles with high-UTXO addresses | |
cculianu/Fulcrum |
✅ Yes | electrum |
More scalable, but not officially supported by Mempool developers |
mempool/electrs |
✅ Best choice | electrum |
Official high-performance fork for full mempool.space compatibility (fork of Blockstream/electrs) |
Blockstream/esplora |
✅ Yes | esplora |
Exposes REST API; required with MEMPOOL_BACKEND=esplora |
We recommend mempool/electrs for production deployments or if you need address-level transaction history.
mempool/electrs uses --jsonrpc-import, which connects to bitcoind via RPC instead of reading blk*.dat files directly. This means:
- You do not need to mount raw
.datfiles or share storage between Pods. - You must wait for
bitcoindto fully sync before Electrum becomes responsive. Fully sync can take a day and ~728GiB disk space (as of May 8, 2025).
Until the sync is complete:
- Address lookups will return errors
- The Mempool UI may appear unresponsive
- The mempoolelectrs service backend will log messages like:
WARN - waiting for bitcoind sync and mempool load to finish: 816535/895785 blocks, verification progress: 76.456%, mempool loaded: true
⚠️ Slow first-time address queries: When usingmempool/electrs, querying addresses with large transaction histories (50k+ txs) can take several minutes on the first request. Subsequent requests are much faster (seconds), suggesting RocksDB cache warming. This performance issue is under investigation — cache size appears limited to 8 MB and may not be configurable in the current release.
When you deploy the full deploy-mempool.yaml SDL (Bitcoin Knots + Mempool stack), here’s what happens behind the scenes:
-
app(bitcoind) Theappservice begins downloading the full Bitcoin blockchain into/root/.bitcoin.⚠️ This can take 1–2 days depending on provider disk and bandwidth. 💾 As of May 8, 2025, full sync requires ~766 GiB of disk space. -
mempoolelectrs(efficient Electrum indexer) This service waits forbitcoindto fully sync before it starts. It uses--jsonrpc-importto communicate withbitcoindvia RPC — no raw.datfile access is needed. -
Indexing Phase Once sync is complete,
mempoolelectrsstarts indexing the entire blockchain, writing to its own RocksDB store under/electrs.⚠️ This indexing process may take several hours and will consume up to 1.5 TiB of storage after compaction. However, during the compaction phase, twice more - up to 3.0 TiB of temporary space may be required — so we recommend provisioning a volume of at least 3-4 TiB to avoid out-of-disk errors. -
apiandwebservices- The
webUI talks to theapibackend and MariaDB (db). - The
apiservice queries themempoolelectrsElectrum API (50001) for transaction/address/block data. If Electrum is unavailable or still syncing, theapiservice falls back tobitcoind(using theCORE_RPC_*config).
- The
-
db(MariaDB) Used by the Mempool backend for caching and statistics. If the API loses connection todb, the UI will freeze or lag behind. If possible, ensureapianddbare scheduled on the same node to avoid cross-node latency or packet loss.
- ✅ Wait for
bitcoindto finish syncing before expecting Electrum or Mempool UI to respond - ✅ See the logs on
api,mempoolelectrsservices to diagnose startup delays / sync progress / issues - ✅ You can use
curl http://api:8999/api/v1/blocks/tip/heightinside itself or inside thewebPod to verify sync progress ⚠️ If Mempool UI gets stuck on an old block height, the cause is usually DB connection loss or Electrum still syncing / starting up (verify size of /electrs directory is growing)
If you prefer to avoid running mempool/electrs (Blockstream's electrs fork), you can simplify your deployment with the following changes:
-
Set
MEMPOOL_BACKEND=nonein theapiservice. -
Remove or comment out the entire
mempoolelectrsservice section. -
Ensure the
CORE_RPC_*environment variables are enabled in theapiservice (not commented out):- CORE_RPC_HOST=app - CORE_RPC_PORT=8332 - CORE_RPC_USERNAME=user - CORE_RPC_PASSWORD=changeme123
⚠️ Note: This disables address lookup functionality and any Mempool UI features that depend on Electrum. You’ll still get block/mempool data frombitcoind, but without per-address transaction history or UTXO queries.
To transfer data between deployments (e.g., the /electrs index from one provider to another), this setup exposes auxiliary port 8080 for the app (bitcoind) and mempoolelectrs services, enabling rclone serve sftp over the internet.
💤 Important: Ensure both source and target containers are running
sleep infinity. This avoids interference and allows safe, manual control over the backup process.
📝 Note: For the
app(bitcoind) service, use/root/.bitcoinas the source or destination directory instead of/electrs.
nohup rclone serve sftp /electrs \
--addr :8080 \
--user myuser \
--pass mypass123 &This starts an SFTP server on port 8080, exposing /electrs for incoming transfers.
📝 Note: The
30353port is the external nodePort mapped to8080for themempoolelectrsservice in the target deployment.
rclone --config /dev/null \
--sftp-host provider.europlots.com \
--sftp-port 30353 \
--sftp-user myuser \
--sftp-pass "$(rclone obscure mypass123)" \
copy /electrs/ :sftp: \
--progress --transfers=16 --checkers=16 --multi-thread-streams=4| Option | Purpose |
|---|---|
--transfers |
Number of simultaneous file uploads |
--multi-thread-streams |
Parallel chunks per file (better throughput) |
--checksum |
Optional: End-to-end data integrity check |
--bwlimit 50M |
Optional: Bandwidth throttle |
--retries 10 |
Optional: Retry logic on transient failures |
✅ Re-running the
rclone copycommand is safe and resumable — it will skip already copied files.
Maintainer: Andrey Arapov


