Skip to content

Repository files navigation

Bitcoin Starter Stack

Private Bitcoin full node, routed over Tor

CI License: MIT Platform: Ubuntu 24.04 Tor

Docker Compose stack for a Bitcoin Core full node with all P2P traffic routed through a built-in Tor daemon, plus a lightweight web dashboard for sync progress, peers, mempool fees, and watch-only wallet balances.

Bitcoin node dashboard: live node status card, watch-only wallet balances in gold with sparklines above a 3D block tower

What it does

  • 🟠 Full Bitcoin node. The official Bitcoin Core image (digest-pinned, Dependabot-updated) validating the full chain, health-checked by Docker — or a pruned node in ~30 GB via one config key.
  • 🧅 Tor-only networking. All P2P traffic goes through the Tor container (onlynet=onion) — your home IP is never associated with your node. Accepts inbound over a Tor onion service by default to serve blocks back to the network (no IP exposure, no host port); set inbound_onion: false to run outbound-only.
  • 📊 Live dashboard. Sync progress, peers, uptime, pruned status, and disk usage (with a low-space warning) on your LAN at port 80 — optionally behind basic auth. RPC stays inside the Docker network; nothing but the dashboard port is exposed.
  • 🔑 Credentials handled properly. Config renders into gitignored files, so a stray git add can't publish your RPC password — and bitcoind itself gets only a salted rpcauth hash, never the plaintext.
  • ♻️ Reuse an existing chain. Point data_dir at an already-synced datadir and skip the multi-day initial download.
  • 📟 Opt-in alerts & remote access. Telegram alerts (node down, sync complete, disk low), a Healthchecks.io dead-man's switch for when the whole box goes dark, and dashboard access from anywhere via a Tor onion service — all routed over Tor. See Notifications.
  • 👀 Watch-only balances. Add your xpubs (or descriptors) right in the dashboard — each balance and a total, read straight off your own node, your addresses never touching a block explorer. Add and remove them from the UI; watch-only, so no keys and no spend risk. See Watch-only.
  • ⬆️ One-command upgrades. ./stack upgrade fetches the latest release, backs up, and applies it — or flip on dashboard.control (one question in ./stack init) and upgrade with a button from the dashboard; the stack runs the host-side agent for you.
  • 🔭 Knows when it's stale. A daily update check (over Tor) surfaces new Bitcoin Core and stack releases on the dashboard, and a Prometheus /metrics endpoint plugs into whatever monitoring you already run.

🚀 Quick Start

Prerequisites: Ubuntu Server 24.04 with Docker Engine, jq, an SSD with ~1 TB free (the chain is ~800 GB and grows — or ~30 GB pruned), and 8 GB+ RAM. Details in Hardware Requirements.

git clone https://github.com/VijitSingh97/bitcoin-starter-stack.git
cd bitcoin-starter-stack   # or unpack the tarball from the latest release
./stack up                 # generates config, creates the data dir, and starts — nothing to edit

That's it — no file to edit. ./stack up writes a .env with sensible defaults and an auto-generated RPC password (username defaults to bitcoin), for a full node over Tor, then starts the stack. It pulls prebuilt images (amd64 and arm64/Raspberry Pi) from GHCR, so there's nothing to compile — it only builds locally if you're on an unreleased commit.

Prefer to be asked? ./stack init walks you through the options — a dashboard password (Enter generates a strong one), a Tor onion, inbound Tor connections, a fast clearnet initial sync, pruning — each with a default you accept by pressing Enter. Everything is optional; you can also set it later by editing config.json and running ./stack apply. See Configuration.

Then watch it come up:

./stack status            # container + health summary
./stack logs tor          # wait for "Bootstrapped 100% (done)"
./stack logs bitcoin      # headers, then block sync

./stack wraps day-to-day operations (up, down, logs, status, doctor, apply, upgrade, backup/restore) — see Operations. Upgrading is one command: ./stack upgrade fetches the latest release, backs up, and applies it.

The initial block download is ~800 GB over Tor — expect days, with live progress on the dashboard the whole time. Full walkthrough: Getting Started.

📈 Monitoring

Open the dashboard at http://localhost, or from another machine on your LAN at http://<hostname>.local (needs avahi-daemon on the node box).

  • Node mode — a Full or Pruned badge in the header.
  • Sync progress — block height vs. headers, with a progress bar.
  • Peers — total connections, inbound vs. outbound.
  • Disk — chain size on disk vs. drive capacity.
  • Mempool & fees — transaction backlog and sat/vB estimates for the next / ~30-min / ~1-hour blocks (once synced), with a 24-hour fee sparkline.
  • Watch-only balances — add xpubs/descriptors from the UI; per-key balances and a total (shown once you have more than one), read off your own node (Watch-only).
  • Versions — Bitcoin Core version in the card, stack version in the footer.
  • Theme — follows your system light/dark setting; the top-right toggle cycles Auto → Light → Dark and remembers your choice.
  • Live block tower — a day-clock: a 12×12 layer is one UTC day. It fills to the current time of day at Bitcoin's ~10-minute spacing (one cube per 10 UTC minutes); the loading slot pulses, and a loading block N header shows the next block. At midnight the day is pushed down and a fresh one starts. Driven purely by the clock — no history or node lookups. Theme-aware and paused for prefers-reduced-motion.

The dashboard has no authentication — it's meant for your LAN only. Don't port-forward 80 to the internet.

🏗️ How it works

flowchart LR
    You(["👤 You · Browser"])
    Net(["🌐 Tor Network"])

    subgraph stack ["🐳 Bitcoin Starter Stack"]
        Dashboard["📊 Dashboard<br/>:80"]
        Bitcoin["🟠 Bitcoin Core"]
        Tor["🧅 Tor"]
    end

    You ==>|HTTP :80| Dashboard
    Dashboard -.->|RPC| Bitcoin
    Bitcoin ==>|SOCKS5| Tor
    Tor <==> Net
Loading

Three services on an isolated Docker network: tor (SOCKS5 proxy), bitcoin (Bitcoin Core, non-root, RPC reachable only from inside the network), and dashboard (Flask app polling the node over RPC). Full breakdown in Architecture.

📚 Documentation

Guide What's inside
Getting Started Prerequisites, install, first start, what to expect during sync.
Hardware Requirements CPU, RAM, disk sizing — with real numbers from a reference box.
Configuration Every config.json key, applying changes, reusing an existing node.
Watch-only Show xpub/descriptor balances on the dashboard, read off your own node.
Architecture The three services, network layout, and privacy model.
Operations Commands, health checks, upgrades, backup, troubleshooting.
Notifications & Remote Access Telegram alerts, a Healthchecks.io dead-man's switch, and reaching the dashboard over Tor.
Releasing How versions are cut: VERSION file, changelog discipline, the tag-triggered gate, and tarballs.

🧪 Testing

tests/run.sh

Runs shellcheck, configure.sh and CLI tests, a docker-compose contract test, a release-consistency check, an upgrade-path test, the dashboard's Python and frontend unit tests, and a real end-to-end boot whose egress audit asserts every established connection from the containers is Tor-only — the same suite CI runs on every push, plus a full image build, secret scanning (gitleaks), and Dockerfile lint (hadolint). See CONTRIBUTING.md.

⚠️ Disclaimer

USE AT YOUR OWN RISK. This software is provided "as is" without any warranties. Running a full node is resource-intensive (bandwidth, disk, memory). Understand your firewall setup before exposing anything beyond your LAN. Security posture and reporting: SECURITY.md. Licensed MIT.

About

Docker stack for Bitcoin node with a custom web dashboard, routed over Tor.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages