A complete Docker-based development environment for Bitcoin and Lightning Network development, featuring a LNURL server for Lightning payments and testing guides using the Bitkit app.
- Bitcoin Core (regtest): Bitcoin node for development
- LND: Lightning Network Daemon for Lightning payments
- Electrum Server: For Bitcoin blockchain queries
- LNURL Server: Lightning payment server with LNURL support
- LDK Backup Server: Lightning Development Kit backup service
- VSS Server: Versioned Storage Server for app and ldk-node state backups
-
Clone and start the services:
git clone --recurse-submodules [email protected]:ovitrif/bitkit-docker.git cd bitkit-docker docker compose up -d
-
Wait for services to initialize (about 30-60 seconds)
-
Check health:
curl http://localhost:3000/health
- Port: 43782 (RPC), 39388 (P2P)
- Network: Regtest
- Wallet: Auto-created
- Authentication:
polaruser/polarpass
- REST API:
http://localhost:8080 - P2P:
localhost:9735 - RPC:
localhost:10009 - Network: Regtest
- Features: Zero-conf, SCID alias, AMP support
- Port: 3000
- Features:
- LNURL-withdraw
- LNURL-pay
- LNURL-auth
- LNURL-channel
- Lightning Address support
- QR code generation
- Endpoints:
/health- Service health check/generate- Generate UI for LNURL/generate/withdraw- Generate LNURL-withdraw/generate/pay- Generate LNURL-pay/generate/channel- Generate LNURL-channel/generate/auth- Generate LNURL-auth/.well-known/lnurlp/:username- Lightning Address
- Port: 5050
- Features: RS256 JWT authentication
- Port: 5005
- Features: Issuing RS256 JWT via LNURL-Auth protocol expected by VSS
- Endpoints:
/health- Service health check/auth- LNURL-auth endpoint
- Port: 60001
- Network: Regtest
- Features: Full blockchain indexing
# Health Check
curl http://localhost:3000/health | jq
# Generate LNURL-withdraw
curl -s http://localhost:3000/generate/withdraw | jq
# Generate LNURL-pay
curl -s http://localhost:3000/generate/pay | jq
# Lightning Address
curl -s http://localhost:3000/.well-known/lnurlp/alice | jq
# VSS Health Check
curl -v http://localhost:5050/vss/getObject./bitcoin-cli mine 1docker compose exec lnd lncli --network=regtest --tlscertpath=/home/lnd/.lnd/tls.cert --macaroonpath=/home/lnd/.lnd/data/chain/bitcoin/regtest/admin.macaroon getinfo# All services
docker compose logs -f
# Specific service
docker compose logs -f lnurl-server
docker compose logs -f vss-server
docker compose logs -f lnd
docker compose logs -f bitcoind- in
Env.{kt,swift}, use for REGTEST electrum server:"tcp://localhost:60001" - in app, wipe current wallet data and create fresh one
- run
docker compose up --build -d - fund onchain wallet:
./bitcoin-cli fund - send funds to n-app wallet address:
./bitcoin-cli send 0.25 - mine block:
./bitcoin-cli mine 1 - get local LND nodeID and open channel
http://localhost:3000/healthcurl -s http://localhost:3000/health | jq -r '.lnd.uris[0]' | pbcopy- app: send > paste, then complete the flow
./bitcoin-cli mine 3
- generate LNURL pay:
http://localhost:3000/generate/pay - paste lnurl into app
- generate fixed amount LNURL pay (QuickPay):
http://localhost:3000/generate/pay?minSendable=10000&maxSendable=10000
ngrok http 3000- change
DOMAINindocker-compose.ymlto__NGROK_URL__ docker compose downif runningdocker compose up --build -dhttp://localhost:3000/.well-known/lnurlp/alice- copy the email-like lightning address and paste into app
- (optional) use physical phone so localhost is usable via
adb reverse - (optional) reset
bitkit-dockerstatedocker compose down -vrm -rf ./lnd ./lnurl-server/datadocker compose up --build -d
adb reverse tcp:60001 tcp:60001adb reverse tcp:9735 tcp:9735- fund onchain wallet:
./bitcoin-cli fund - fund LND wallet:
- get address:
curl -s http://localhost:3000/address | jq -r .address | pbcopy - fund LND wallet:
./bitcoin-cli send 0.2 - mine block
./bitcoin-cli mine 1 - check balance:
curl -s http://localhost:3000/balance | jq
- get address:
- generate LNURL channel:
http://localhost:3000/generate/channel - paste lnurl into app and complete the flow
- mine blocks:
./bitcoin-cli mine 6
- setup a channel (see above)
- generate LNURL:
curl -s http://localhost:3000/generate/withdraw | jq -r .lnurl | pbcopy - set an amount of at least ₿5000 & complete the flow
- generate LNURL with limits:
curl -s "http://localhost:3000/generate/withdraw?minWithdrawable=100000&maxWithdrawable=200000" | jq -r .lnurl | pbcopyminWithdrawable(optional): min msats (default: 1000 = 1 sat)maxWithdrawable(optional): max msats (default: 100000000 = 100k sats)
- set DOMAIN in
docker-compose.ymltohttp://__YOUR_NETWORK_IP__:3000 - run
docker compose down - run
docker compose up --build -d - generate LNURL auth:
http://localhost:3000/generate/auth - paste lnurl into app and complete the flow
adb reverse tcp:3000 tcp:3000adb reverse tcp:5050 tcp:5050- cd to root dir
git submodule update --init --recursivedocker compose up --build -d
- in
Env.ktuse commented REGTEST urls forlnurlAuthSeverUrlandvssServerUrl - uninstall & reinstall new app
- create new wallet
- send onchain from other wallet to have activity
- backup seed, then wipe and restore
- (optional) use physical phone so localhost is usable via
adb reverse - (optional) reset
bitkit-dockerstatedocker compose down -vrm -rf ./lnd ./lnurl-server/datadocker compose up --build -d
- in
Env.kt, changeElectrumServers.REGTESTto"tcp://127.0.0.1:60001" android:adb reverse tcp:60001 tcp:60001&adb reverse tcp:9735 tcp:9735- fund onchain wallet:
./bitcoin-cli fund - fund LND wallet:
- get address:
curl -s http://localhost:3000/address | jq -r .address - fund LND wallet:
./bitcoin-cli send 0.2 - mine block
./bitcoin-cli mine 1 - check balance:
curl -s http://localhost:3000/health | jq '.lnd.balance'
- get address:
- fund app wallet:
./bitcoin-cli send 0.002 - mine block
./bitcoin-cli mine 1 curl -s http://localhost:3000/health | jq -r '.lnd.uris[0]'and copy to clipboard- send > paste invoice > complete flow for 100_000 sats > return to home screen
- mine blocks:
./bitcoin-cli mine 6 - await channel ready notice
Key environment variables in docker-compose.yml:
BITCOIN_RPC_HOST: Bitcoin RPC host (default:bitcoind)BITCOIN_RPC_PORT: Bitcoin RPC port (default:43782)LND_REST_HOST: LND REST API host (default:lnd)LND_REST_PORT: LND REST API port (default:8080)
./lnd:/lnd-certs:ro- LND certificates and macaroons./lnurl-server/data:/data- LNURL server database./lnurl-server/keys:/app/keys:ro- RSA keys for JWT signingbitcoin_home- Bitcoin blockchain datapostgres_data- VSS PostgreSQL database
RSA Key Generation:
# Generate RSA keys for JWT
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -pubout -out public.pem
# Copy keys for services
mv private.pem public.pem lnurl-server/keys/
# Update VSS_JWT_PUBLIC_KEY env variable in docker-compose.ymlDatabase Setup:
- PostgreSQL container with
postgresdatabase - Table schemas:
https://github.com/lightningdevkit/vss-server/tree/main/rust/impls/src/postgres/sql - Auto-mounted from
sql/v0_create_vss_db.sql
Docker Setup:
# Clean slate
docker compose down -v
rm -rf ./lnd ./lnurl-server/data
# run in lnurl-auth-server root dir:
rm -rf ./data ./test-data
# Optional: Rotate keys
# rm -rf lnurl-server/keys/ private.pem public.pem
# Then Generate new RSA keys (see above)
# Initialize vss-server submodule:
git submodule update --init --recursive
# Start services
docker compose up --build -d- Check if ports are available
- Ensure Docker has enough resources
- Check logs:
docker compose logs
- Wait for LND to fully sync
- Check macaroon files exist
- Verify network connectivity between containers
- Ensure Bitcoin Core is fully synced
- Check RPC authentication credentials
- Verify port mappings
- Run
docker compose down -v - Delete databases:
rm -rf ./lnd ./lnurl-server/data - Delete RSA keys:
rm -rf ./lnurl-server/keys ./public.pem - Delete lnurl-auth-server db: cd to its root dir then run
rm -rf ./data ./test-data
- Check latest logs snapshot:
docker logs lnurl-server --tail 10 - Check live logs:
docker compose logs -f lnurl-server - Check LND wallet balance:
curl -s http://localhost:3000/balance | jq- This setup uses regtest network for development
- Self-signed certificates are used for LND REST API
- Default credentials are used
- All services are exposed on localhost only
Do not use for production. Bitkit Dev server is vibe-coded and not optimised.
This project is licensed under the MIT License. See the LICENSE file for more details.