pull down to refresh

This quick guide shows how to run your Lightning Network node (LND) with both Tor and clearnet connections using Docker containers and Wireguard VPN.

Why It Matters

  • Faster payments with fewer failures (clearnet + Tor dual connectivity)
  • Privacy preserved through the Tor network and in clearnet
  • Improved reachability
  • Better routing capabilities

Quick Setup

1. On Your VPS

[Interface]
PrivateKey = your-private-key
Address = 10.0.0.1/24
ListenPort = 51820

# The magic sauce - forward LN port to your node
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; iptables -t nat -A PREROUTING -p tcp --dport 9735 -j DNAT --to-destination 10.0.0.2:9735
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = your-peer-public-key
AllowedIPs = 10.0.0.2/32

2. On Your Host Machine

[Interface]
PrivateKey = your-private-key
Address = 10.0.0.2/24
DNS = 127.0.0.11, 1.1.1.1

# Route local Docker traffic properly
PostUp = ip route add 172.16.0.0/12 dev eth0; ip route add 127.0.0.11/32 dev eth0
PostDown = ip route del 172.16.0.0/12 dev eth0; ip route del 127.0.0.11/32 dev eth0

[Peer]
PublicKey = your-vps-public-key
AllowedIPs = 0.0.0.0/0
Endpoint = your-vps-ip:51820
PersistentKeepalive = 25

3. Docker Compose Config

...

wireguard-lnd:
  image: linuxserver/wireguard
  container_name: wireguard-lnd
  restart: always
  cap_add:
    - NET_ADMIN
  sysctls:
    - net.ipv4.conf.all.src_valid_mark=1
  volumes:
    - /data/lnd/wireguard:/config
    - /lib/modules:/lib/modules:ro
  networks:
    - bitcoind
    - lnd
    - tor-lnd

lnd:
  image: lightninglabs/lnd:v0.18.5-beta
  container_name: lnd
  user: "1000:1000"
  volumes:
    - /data/lnd/data:/.lnd/
    - /data/tor/lnd/run:/var/run/tor:ro
  command: lnd --configfile=/.lnd/lnd.conf
  network_mode: "container:wireguard-lnd"
  depends_on:
    - wireguard-lnd
    - bitcoind
    - tor-lnd

tor-lnd:
  image: ghcr.io/m0wer/docker-tor:latest
  container_name: tor-lnd
  user: "1000:1000"
  volumes:
    - /data/tor/lnd/conf:/etc/tor:ro
    - /data/tor/lnd/data:/var/lib/tor
    - /data/tor/lnd/run:/var/run/tor
  networks:
    - tor-lnd

...

4. LND Config

# Key settings for dual connectivity
[Application Options]
externalip=your-vps-ip:9735
nat=false
tlsextradomain=wireguard-lnd

listen=0.0.0.0:9735
rpclisten=0.0.0.0:10009
restlisten=0.0.0.0:8080

[tor]
tor.active=true
tor.v3=true
tor.streamisolation=false
tor.skip-proxy-for-clearnet-targets=true
tor.socks=tor-lnd:9050
tor.control=tor-lnd:9051
tor.targetipaddress=wireguard-lnd
That's it! You're now running a dual-stack LND node that can process payments faster and more reliably while maintaining privacy.

References

10 sats \ 3 replies \ @ek 9h
Was about to post my guide but then I saw it in the references lol
reply
100 sats \ 2 replies \ @klk OP 3h
:-) Was very useful, thanks.
reply
0 sats \ 1 reply \ @ek 3h
How did you come across it?
reply
100 sats \ 0 replies \ @klk OP 3h
Before I even knew how to implement it, I searched for site:stacker.news wireguard tunnel or something like that. Which led to #265524
I feel that adding site:stacker.news for some kind of searches really gives you curated results.
reply
10 sats \ 1 reply \ @anon 3h
Nice. I've set it up the same way, a while ago. Maybe a note: With this constellation lnd is not reachable from the internal network. All traffic from lnd goes throigh wireguard.
reply
0 sats \ 0 replies \ @klk OP 3h
Well from the Docker host you can still reach it. Now you just need to point to wireguard-lnd.
Since the lnd container is using the wireguard-lnd network stack, if it binds a port it's really binding it on the wireguard-lnd “container”.
So I had to adjust services (like Alby, lndg, ...) to point to wireguard-lnd instead. And to add it as an alternative domain name for the TLS in lnd.conf (that part you can see above).
reply
Where’s the Bitcoind part?
reply
0 sats \ 0 replies \ @klk OP 3h
I have a huge compose with all the stack: bitcoind, electrs, mempool, lnd, ... Maybe I can create another guide about that. For now here you go:
services:
  bitcoind:
    image: lncm/bitcoind:v28.0@sha256:1d335a5adbfac6d66cee20b62b339385819dc75f8cb60c6c5773922cec4c25ef
    container_name: bitcoind
    user: "1000:1000"
    volumes:
      - /flash/bitcoin/data/:/data/.bitcoin
      - /data/bitcoin/conf/bitcoin.conf:/data/.bitcoin/bitcoin.conf:ro
      - /data/tor/bitcoind/run:/var/run/tor

    ports:
      - "8333:8333"  # P2P network port
      - "28333:28333"  # ZMQ tx
      - "28332:28332"  # ZMQ block
    deploy:
      resources:
        limits:
          cpus: 8
          memory: 20G
    restart: always
    networks:
      - bitcoind

  tor-bitcoind:
    image: ghcr.io/m0wer/docker-tor:latest
    user: "1000:1000"
    volumes:
      - /data/tor/bitcoin/conf:/etc/tor:ro
      - /data/tor/bitcoin/data:/var/lib/tor
      - /data/tor/bitcoin/run:/var/run/tor
    deploy:
      resources:
        limits:
          cpus: 2
          memory: 300M
    restart: always
    networks:
      - bitcoind
    depends_on:
      - bitcoind
reply
Isn't this meant for devs?
reply
0 sats \ 0 replies \ @klk OP 3h
Not really devs but public node runners.
reply