Lightning client
Install and configure LND (Lightning Network Daemon). Write lnd.conf for bitcoind RPC and ZMQ, generate the 24-word seed, set up auto-unlock, enable watchtower and wumbo channels.
Which Lightning implementation should a first-time node run? You'll install LND (the Lightning Network Daemon) from Lightning Labs, the most widely used, best-documented, and best-tooled implementation for a node operator who wants a web UI and a mobile app to work out of the box. Core Lightning and Eclair are excellent too, but LND has the ecosystem advantage, and that matters when you're starting out.
This page takes you from zero to a running lnd service with a
24-word seed, an auto-unlocking wallet, and a healthy getinfo
response.
Real money from satoshi one
Lightning isn't a testbed. The wallet you create here holds real
bitcoin, and every channel open or close is an on-chain transaction
that costs real fees. Until you have your 24-word seed written
down on paper and your channel.backup file syncing off-Pi
(next page after this one), don't fund the wallet. A lost seed or
missing SCB on a dead SSD means the funds are gone, no support desk.
Budget about 30 minutes of hands-on time for this page.
Create the system user and data directory
LND is a long-running daemon that manages real money. It gets its
own unprivileged system user and a dedicated data directory on the
SSD, with the home-directory ~/.lnd path symlinked to the real
location. Same pattern you used for bitcoind.
-
As user
admin, create thelnduser. Give it group membership inbitcoin(so it can readbitcoin.conffor auto-RPC) and indebian-tor(so it can read Tor's cookie file for the control port):sudo adduser --disabled-password --gecos "" lnd sudo usermod -a -G bitcoin,debian-tor lnd sudo adduser admin lndThe third command puts
admininto thelndgroup so you can runlnclilater withoutsudo. -
Create the data directory on the SSD and hand it to
lnd:sudo mkdir /data/lnd sudo chown -R lnd:lnd /data/lnd -
Open a shell as the
lnduser and set up the symlinks. LND looks for its data in~/.lndby default; pointing that at/data/lndmeans every tool and tutorial that assumes the default path still works:sudo su - lnd ln -s /data/lnd /home/lnd/.lnd ln -s /data/bitcoin /home/lnd/.bitcoin ls -laThe two symlinks should show in cyan, not red. Red means a broken link, usually because the target directory doesn't exist yet.
Download LND
LND ships as a statically linked binary tarball. You'll download it, verify the SHA256 checksum, verify the GPG signature on the manifest, and only then copy the binaries into place.
-
Still as the
lnduser, grab the release archive, the manifest, and the maintainer's signature:cd /tmp wget https://github.com/lightningnetwork/lnd/releases/download/v0.20.1-beta/lnd-linux-arm64-v0.20.1-beta.tar.gz wget https://github.com/lightningnetwork/lnd/releases/download/v0.20.1-beta/manifest-v0.20.1-beta.txt wget https://github.com/lightningnetwork/lnd/releases/download/v0.20.1-beta/manifest-roasbeef-v0.20.1-beta.sig -
Verify the checksum of the binary against the manifest. The
--ignore-missingflag lets you check only the file you downloaded, not every platform listed in the manifest:sha256sum --check manifest-v0.20.1-beta.txt --ignore-missingExpected output:
lnd-linux-arm64-v0.20.1-beta.tar.gz: OK
Verify the signature
The checksum proves the download wasn't corrupted in transit. It does not prove the manifest itself is authentic, for that you need to verify the PGP signature against the maintainer's public key. LND releases are signed by Olaoluwa "Roasbeef" Osuntokun.
-
Import the signing key from the LND repo (the
scripts/keys/roasbeef.ascpath is the canonical source):curl https://raw.githubusercontent.com/lightningnetwork/lnd/master/scripts/keys/roasbeef.asc | gpg --import -
Verify the manifest against the signature:
gpg --verify manifest-roasbeef-v0.20.1-beta.sig manifest-v0.20.1-beta.txtLook for a
Good signature from "Olaoluwa Osuntokun"line. The full fingerprint should readA5B6 1896 952D 9FDA 83BC 054C DC42 612E 8923 7182. GPG will also warn that the key isn't certified with a trusted signature. That's expected; you haven't built a web of trust around this key, you've just pinned its fingerprint.
Why GPG when we already have a checksum?
A corrupt download trips the checksum. A compromised download server serves a real binary with a matching checksum and a forged manifest. The signature check is what catches that, the attacker would also need Roasbeef's private key, which they do not have.
Install the binaries
-
Step back out of the
lndshell first, installing binaries into/usr/local/binneedsadmin'ssudo:exit -
Extract the archive and install both binaries:
cd /tmp tar -xvf lnd-linux-arm64-v0.20.1-beta.tar.gz sudo install -m 0755 -o root -g root -t /usr/local/bin lnd-linux-arm64-v0.20.1-beta/* lnd --versionExpected output:
lnd version 0.20.1-beta commit=v0.20.1-beta
Set the wallet unlock password
LND's wallet is password-protected and asks for the password on every startup. You have two options:
- Manual unlock every time the Pi reboots. Most secure at rest: the password lives only in your head, but a power blip at 3 a.m. leaves LND offline until you're awake to type a password.
- Auto-unlock from a file on disk. Trades at-rest encryption
for uptime. On a single-user home node behind a firewall this is
the right default; an attacker who can read files as
lndhas already lost you the game.
This guide picks auto-unlock. You can switch later.
-
Become
lndagain and create the password file, then enter password[C](one you haven't used anywhere else):sudo su - lnd nano /data/lnd/password.txt -
Lock the file down so only
lndcan read it:chmod 600 /data/lnd/password.txt
Write lnd.conf
LND reads its configuration from /data/lnd/lnd.conf (resolved
via the ~/.lnd symlink). This file does the heavy lifting,
chain backend, Tor, channel policy, watchtower client, all of it.
-
Create the config file:
nano /data/lnd/lnd.conf -
Paste the following. Replace
YourAliaswith whatever name you want to show up in channel graphs, and pick a hex colour you like:# RaspiBolt: lnd configuration # /data/lnd/lnd.conf [Application Options] alias=YourAlias color=#ff9900 debuglevel=info maxpendingchannels=5 listen=localhost # Auto-unlock the wallet from a file on disk. # Comment out to unlock manually with `lncli unlock`. wallet-unlock-password-file=/data/lnd/password.txt wallet-unlock-allow-create=true # TLS certificate: auto-renew and don't advertise LAN IPs tlsautorefresh=true tlsdisableautofill=true # Channel defaults bitcoin.basefee=1000 bitcoin.feerate=1 minchansize=100000 accept-keysend=true accept-amp=true coop-close-target-confs=24 # Drop stale invoices to keep the DB tidy gc-canceled-invoices-on-startup=true gc-canceled-invoices-on-the-fly=true [bolt] db.bolt.auto-compact=true db.bolt.auto-compact-min-age=168h [Bitcoin] bitcoin.active=true bitcoin.mainnet=true bitcoin.node=bitcoind [Bitcoind] bitcoind.rpchost=127.0.0.1:8332 bitcoind.rpcuser=raspibolt bitcoind.rpcpass=PASSWORD_B_REPLACE_ME bitcoind.zmqpubrawblock=tcp://127.0.0.1:28332 bitcoind.zmqpubrawtx=tcp://127.0.0.1:28333 [tor] tor.active=true tor.v3=true tor.streamisolation=true tor.skip-proxy-for-clearnet-targets=true [protocol] protocol.wumbo-channels=true protocol.option-scid-alias=true protocol.simple-taproot-chans=true protocol.rbf-coop-close=true [wtclient] wtclient.active=trueReplace
PASSWORD_B_REPLACE_MEwith therpcpassfrom yourbitcoin.conf(password[B]from the Bitcoin section).
Stream isolation, and why we skip it for bitcoind
tor.streamisolation=true gives every outbound Lightning
connection its own Tor circuit, so two peers can't correlate you
from the same exit. Good privacy default.
But skip-proxy-for-clearnet-targets=true is also on, which keeps
local clearnet connections, like the one to bitcoind on
127.0.0.1:8332, off of Tor entirely. Without that, LND tries to
send RPC calls through Tor to a localhost IP, and Tor (rightly)
refuses. The combination gives you Tor for everything public and
direct sockets for everything local.
systemd unit
Running lnd by hand once is fine for the initial wallet setup.
For actual operation you want it under systemd so it starts at
boot, restarts after crashes, and only comes up after bitcoind
is ready.
-
Back as user
admin, create the unit file:exit sudo nano /etc/systemd/system/lnd.service -
Paste:
# RaspiBolt: systemd unit for LND # /etc/systemd/system/lnd.service [Unit] Description=LND Lightning Network Daemon Wants=bitcoind.service After=bitcoind.service [Service] ExecStart=/usr/local/bin/lnd ExecStop=/usr/local/bin/lncli stop User=lnd Type=simple Restart=always RestartSec=30 TimeoutSec=240 LimitNOFILE=128000 # Hardening PrivateTmp=true ProtectSystem=full NoNewPrivileges=true PrivateDevices=true MemoryDenyWriteExecute=true [Install] WantedBy=multi-user.target -
Reload systemd and enable the unit (don't start it yet, you need to create the wallet first):
sudo systemctl daemon-reload sudo systemctl enable lnd
Create the wallet and the seed
First start is a two-window affair: LND runs in the foreground in one SSH session and waits for you to create the wallet from a second session.
-
Still as
admin, start LND in the foreground:sudo su - lnd lndYou'll see it print startup logs and then sit on a line like
Waiting for wallet encryption password. Use 'lncli create' .... Leave this window open. -
Open a second SSH session to the Pi. Become the
lnduser and runlncli create:sudo su - lnd lncli create -
At the prompts:
- Enter password
[C]as the wallet password. Use exactly the same password you wrote intopassword.txt. - When asked about an existing cipher seed, answer
n, you want a fresh seed. - When asked about a seed passphrase, press Enter to skip it unless you know what you're doing. A passphrase adds a 25th word that you also have to back up; lose it and the 24 words alone will not restore the wallet.
- Enter password
-
LND prints a 24-word cipher seed. Stop scrolling. Read this part.
The 24-word seed is your on-chain wallet
These 24 words are the only rope back to the on-chain funds on this node. If the Pi dies, the SSD dies, or the house burns down, the seed, and only the seed, can restore your wallet on a fresh LND.
- Write the words down on paper. Twice. Keep the two copies in two different physical locations.
- Do not photograph the screen, do not type the words into any text file, do not email them to yourself, do not put them in a password manager unless it's one you trust with your life.
- The RaspiBolt backup card is a nice printable template if you want one.
- Anyone with these words can empty every on-chain sat on this node. The seed does not restore Lightning channel balances, for that, see Channel backup.
Seriously. Write it down before you go any further.
Once the seed is recorded, exit the second session:
exit
exitBack in the first window where lnd is still running, stop it with
Ctrl-C. Then start it again in the foreground to confirm the
auto-unlock works:
lndLook for Attempting automatic wallet unlock with password and
Opened wallet. Stop it again with Ctrl-C and exit the lnd
user session:
exitStart LND under systemd
-
As
admin, start the service and follow the log:sudo systemctl start lnd sudo journalctl -f -u lndWait until you see
LNWL: Opened walletand then graph-sync progress. Exit the log tail withCtrl-C. -
Let
adminuselncliwithoutsudo. Theadminuser is already in thelndgroup; the remaining permissions tweak is a symlink and a group-read bit on the macaroon:ln -s /data/lnd /home/admin/.lnd sudo chmod -R g+X /data/lnd/data/ sudo chmod g+r /data/lnd/data/chain/bitcoin/mainnet/admin.macaroon -
Log out of the SSH session and log back in, group membership only takes effect on a fresh shell. Then smoke-test:
lncli getinfo lncli getnetworkinfogetinfoshould return anidentity_pubkey, the currentblock_height, andsynced_to_chain: trueonce LND has caught up with the graph.getnetworkinfoshould show a non-zero number of nodes and channels, proof that LND is talking to the wider Lightning network over Tor.
Main takeaway: LND is up, the wallet is unlocked, the 24-word
seed is on paper, and lncli works from admin. You have a
working Lightning node.
Fund the node and open a channel
-
Generate a native-SegWit address and send a small amount of on-chain sats to it from another wallet:
lncli newaddress p2wkhWait for one confirmation, then:
lncli walletbalance -
Pick a well-connected peer from Amboss or LightningNetwork+. A peer URI looks like
pubkey@host:port. Connect, then open a channel (capacity in sats, explicit fee in sats/vByte from mempool.space):lncli connect 03864ef025fde8fb587d989186ce6a4a186895ee44a926bfc370e2c366597a3f8f@34.239.230.56:9735 lncli openchannel --sat_per_vbyte 8 03864ef025fde8fb587d989186ce6a4a186895ee44a926bfc370e2c366597a3f8f 200000 0Three confirmations later the channel is active:
lncli listchannels
Before you open channels in anger
Set up Channel backup before you open your first real channel. The backup is only useful if it exists when you need it, and you need it as soon as the first channel lands.
Add watchtowers
Lightning channels assume both sides are honest. If a peer tries to settle an old channel state while your node is offline, they walk away with funds that should have been yours. Watchtowers are third-party nodes that watch your channels for you and punish cheaters, and because the worst a watchtower can do is fail silently, you don't have to trust them.
You already enabled wtclient.active=true in lnd.conf. Add a
tower or two:
sudo su - lnd
lncli wtclient add 023bad37e5795654cecc69b43599da8bd5789ac633c098253f60494bde602b60bf@iiu4epqzm6cydqhezueenccjlyzrqeruntlzbx47mlmdgfwgtrll66qd.onion:9911
lncli wtclient towersOpenoms maintains a list of public altruistic watchtowers; add two or three more for redundancy.
Useful lncli commands
A small reference you'll come back to:
# node info and peers
lncli getinfo
lncli listpeers
# channels
lncli pendingchannels
lncli listchannels
lncli closechannel --sat_per_vbyte <fee> <funding_txid> <output_index>
lncli closechannel --force <funding_txid> <output_index>
# payments
lncli decodepayreq <invoice>
lncli payinvoice <invoice>
lncli sendpayment --amp --dest=<pubkey> --amt=<sats>
lncli addinvoice <sats>
lncli listinvoices
lncli listpayments
# help
lncli
lncli help <command>Full API reference at api.lightning.community.
Upgrading LND
LND release notes are non-negotiable reading, some releases ship database migrations that are one-way. Before every upgrade:
- Read the release notes end to end.
- Stop the service:
sudo systemctl stop lnd. - Repeat the download, verify, and install steps above with the new version.
- Update
0.20.1-betainlib/versions.tsso the rest of the guide agrees. - Start the service:
sudo systemctl start lndand tail the log until you seesynced_to_chain: true.

