Complete Docker infrastructure for running a Bitcoin node with Core Lightning, private DNS, VPN, and monitoring.
Lightning nodes handle real funds. Software is provided as-is. Use only at your own risk. See CLN security docs.
- Docker >= 24.0 & Docker Compose >= 2.0
- Linux (Debian/Ubuntu)
- 16GB+ RAM, 4+ CPU cores, 50GB+ storage
chmod +x bastion
./bastion upWhat happens:
- Generates
bastion.conf(auto-prompted for Wireguard URL, port, CLN alias) - Creates
.envsymlinks βbastion.conf(one source of truth) - Deploys: network β bitcoin β monitor
| Stack | Services | IPs |
|---|---|---|
| network | unbound DNS, wireguard VPN, pi-hole | 10.0.0.2-3 |
| bitcoin | bitcoind, lightningd, tor, rtl, teosd | 10.0.0.10-14 |
| monitor | prometheus, grafana, portainer, node-exporter | 10.0.0.20-23 |
./bastion up # Start all stacks
./bastion stop # Stop services
./bastion down # Remove containers
./bastion status # Show containers
./bastion audit # Check node profitability
./bastion logs # Tail logs| Service | Port | Location | Version |
|---|---|---|---|
| RTL (Lightning UI) | 3000 | http://localhost:3000 | v0.15.8 |
| Grafana | 4001 | http://localhost:4001 | latest |
| Portainer | 4000 | https://localhost:4000 | latest |
| Prometheus | 9090 | http://localhost:9090 | latest |
| Pi-hole | 80 | http://localhost/admin | latest |
| CLN REST API | 3001 | http://localhost:3001 | (CLN native) |
| Wireguard VPN | 51820/udp | External | latest |
Defaults (change immediately):
- Grafana:
admin:admin - Pi-hole:
admin:${PIHOLE_PASSWORD} - Bitcoin RPC:
bitcoind.user:bitcoind.pass - CLN REST API: Access via
http://localhost:3001
./bastion auto-generates bastion.conf on first run:
- Interactive prompts: Wireguard URL/port, CLN node alias
- Auto-generated: TIMEZONE, PIHOLE_PASSWORD, USER_ID, GROUP_ID
- Symlinks: Each stack references
../bastion.confvia.env
stack-bitcoin/docker-compose.yml # Edit RPC user/pass, pruning settings
stack-bitcoin/config/cln_config # CLN configuration (alias, plugins, proxy)
stack-network/docker-compose.yml # Wireguard server config
bastion.conf # GENERATED - in .gitignore
stack-*/.env # SYMLINKS - in .gitignore
stack-*/data/ # Volumes - in .gitignore
-rpcuser=bitcoind.user # RPC user (change if desired)
-rpcpassword=bitcoind.pass # RPC password (change if desired)
-prune=20000 # ~20GB block storage (adjust as needed)
-txindex=0 # Disabled (not needed for CLN)
-rpcallowip=10.0.0.0/24 # Allow RPC from container network
-rpcbind=0.0.0.0 # Listen on all interfaces (container network)Note: RPC credentials must match those in stack-bitcoin/config/cln_config and RTL config.
All plugins included and enabled by default:
| Plugin | Commit | Purpose |
|---|---|---|
| clboss | 95d195f8 | Channel autopilot & rebalancing |
| watchtower-client | be344ecc | TEOS breach watching |
| peerswap | 23b32d3a | Submarine swap rebalancing |
| backup | cb3adab | Replication to USB/external |
| trustedcoin | v0.8.6 | Fee and block validity estimator; verifies block data and channel existence |
| darknet | Local | Prefer .onion addresses for peers |
CLN Configuration:
# Autopilot settings (clboss)
--clboss-min-channel=1000000 # Minimum channel: 1M sats
--clboss-max-rebalance-fee-ppm=250 # Max rebalancing fee
--clboss-auto-close=false # Don't auto-close channels
# Autoclean settings (remove failed payments & invoices)
autoclean-failedpays-age=604800 # Remove failed pays after 7 days
autoclean-failedforwards-age=604800 # Remove failed forwards after 7 days
autoclean-expiredinvoices-age=2592000 # Remove expired invoices after 30 days
# Wallet & backup
wallet=sqlite3:///root/.lightning/bitcoin/lightningd.sqlite3:/backup_usb/lightningd.sqlite3
# Network settings
proxy=10.0.0.11:9050 # Tor SOCKS proxy
addr=statictor:10.0.0.11:9051 # Tor control port
always-use-proxy=true # Route all traffic through Tor
bind-addr=0.0.0.0:9735 # Listen on all interfacesImportant Plugins:
trustedcoin- Critical for fee estimation and block validation (marked asimportant-plugin)watchtower-client- Critical for channel security (marked asimportant-plugin)bcli- Disabled in favor of trustedcoin
TEOS (teosd) is included but not configured by default. Running a watchtower on the same machine as your node is riskyβif your node is compromised, so is the watchtower.
Configuration files are templates in stack-bitcoin/config/teos.toml but must be manually copied to the persistent data directory after first run:
# After first run of the stack, copy config to data directory
cp stack-bitcoin/config/teos.toml stack-bitcoin/data/teos/teos.toml
docker restart teosdWhy manual copy? The container mounts stack-bitcoin/data/teos:/home/teos/.teos for persistence. We can't simultaneously mount config/ templates into the same directory, so templates must be copied after first initialization.
RTL connects to CLN via Docker network (10.0.0.10:3001). Configuration template is in stack-bitcoin/config/RTL-Config.json but must be manually copied to the persistent data directory after first run:
# After first run of the stack, copy config to data directory
cp stack-bitcoin/config/RTL-Config.json stack-bitcoin/data/rtl/RTL-Config.json
docker restart rtlWhy manual copy? The container mounts stack-bitcoin/data/rtl:/data for persistence. We can't simultaneously mount config/ templates into the same directory, so templates must be copied after first initialization. Any changes to CLN RPC credentials or ports require updating this file.
General troubleshooting steps for common issues. Always check container logs first (docker logs <container>).
The commands below assume you are in the project root and have the necessary permissions to run Docker commands. Adjust paths and container names as needed based on your specific setup.
# CLN backup plugin backup not initialized - ensure USB mount is correct and accessible
# Example command to initialize backup plugin with mounted USB path:
docker run --rm -it -v $(pwd)/stack-bitcoin/data/cln:~/.lightning/bitcoin -v /mnt/backup_cln:/backup_usb --entrypoint /usr/local/bin/backup/backup-cli lightningd-custom:latest init --lightning-dir ~/.lightning/bitcoin file:///backup_usb/backup.sqlite.bkp
# CLN backup plugin - restore from backup file
docker run --rm -it -v $(pwd)/stack-bitcoin/data/cln:~/.lightning/bitcoin -v /mnt/backup_cln:/backup_usb --entrypoint /usr/local/bin/backup/backup-cli lightningd-custom:latest restore file:///backup_usb/backup.sqlite.bkp --lightning-dir ~/.lightning/bitcoin
# CLN backup plugin - compact backup file
docker exec lightningd lightning-cli backup-compact
# CLN not connecting to Bitcoin
docker logs lightningd
docker exec lightningd ping -c 3 10.0.0.12
# RTL cannot reach CLN
docker logs rtl
docker exec lightningd lightning-cli getinfo
# DNS issues
docker exec unbound dig @127.0.0.1 google.com
# TOR connectivity (config restart to refresh circuits)
docker kill --signal=HUP tor
docker logs tor
# TOR connectivity (delete tor state and cache for fresh start)
docker stop tor
rm -f stack-bitcoin/data/tor/state stack-bitcoin/data/tor/cached-* stack-bitcoin/data/tor/microdesc-*
docker start tor
# Container resource usage
docker stats
df -hAll containers are isolated on Docker network 10.0.0.0/24. External access only via:
- Wireguard VPN (51820/udp)
- SSH (port 22)
- HTTP/HTTPS web services (RTL, Grafana, etc)
Internal isolation:
- Bitcoin RPC:
10.0.0.12:8332(Docker network only) - CLN REST:
10.0.0.10:3001(Docker network only)
Recommended:
- Change default passwords (Grafana: admin:admin, Pi-hole, Bitcoin RPC)
- Keep
.gitignoreprotected - Use Wireguard for remote access
| Component | Version |
|---|---|
| Bitcoin Core | v26.0 |
| Core Lightning | v25.12.1 |
| RTL | v0.15.8 |
| CLN Plugins: | |
| clboss | 95d195f8 |
| watchtower-client | be344ecc |
| backup | cb3adab |
| trustedcoin | v0.8.6 (disabled) |
- Bitcoin: https://bitcoin.org
- Core Lightning: https://github.com/ElementsProject/lightning
- Docker: https://docs.docker.com
- Block explorer: https://mempool.space
Software provided as-is. Use at your own risk. Change defaults immediately. Never commit secrets.