How to Bootstrap a Profitable Lightning Node

Learnings from a top 100 node to help illuminate your path

Red
11 min readMar 4, 2022

The most profitable Lightning nodes have a unique edge. Natural demand as a merchant, mobile wallet, exchange, liquidity provider. Large stack and girthy channels, liquidity relationships, savvy scripts, history, knowledge.

What is a pleb to do in this world?

Lightning is a moving target and I can’t show you your path. I’ll share my approach over the last few months of running my node Cold Sats to help illuminate it, but you must find your own way.

Cold Sats will yield 1.44% this year if I keep up with my current pace. If you’re disappointed then turn back now. Lightning is a low risk, low reward place to make your sats more liquid.

I don’t know how you found your way here but you’ve joined us at the beginning of a revolution. Take a front row seat with me.

Build Your Node

The most common way to run a node is on a Raspberry Pi 4 8GB. If you’re new to Lightning I suggest running myNode, Umbrel or Raspiblitz on a pi.

I chose myNode which came loaded with Bitcoin, LND, Tor, RTL, Thunderhub, Mempool and more apps that I never tried. I use RTL as my core GUI.

Flash a file onto a micro SD, plug that into a pi that’s plugged into a 1 TB+ SSD, turn on the machine and you’re syncing. Access the node by going to the machine’s IP address in a browser. From there you can do most management things in a web GUI, but some advanced tools require command line.

Guides from @parman_the and @BTCsessions describe this process well.

I had issues with my 4GB pi running 85 channels over tor. Machine would freeze or all channels go offline. Reboots sometimes helped. Usually it resolved itself after some time. I estimate 90% uptime.

I migrated to a more powerful machine running a RaspiBolt setup and switched to hybrid mode recently and I’ve had 100% uptime since.

I still recommend a pi to start. It’s the easiest plug and play solution and with 8GB ram you likely won’t have the same issues as me.

Secure Your Seed + channel.backup

After syncing the Bitcoin blockchain you’re ready to create a Lightning wallet. I use LND which is the most popular implementation of Lightning, but consider looking into c-lightning or Eclair.

Note that LND uses an aezeed seed which is different than BIP39. You must use a wallet that supports aezeed like BlueWallet to access your funds.

If your node blows up then you will need to recover your funds from your channel.backup + seed with either another synced machine or something like Blixt. This process will force close all channels.

The most popular way to remotely backup your channel.backup file is with the Balance of Satoshis (BOS) Telegram bot.

Consider the Responsibility

You must stay online after you open your first channel. If you go offline for an extended period, ensure that you have a watchtower set up to protect you. Notify channel partners of any ongoing issues.

Ensure that you understand cooperative vs. force closures. Sometimes your sats will be stuck in limbo for 2 weeks at a time.

You’re running a hot wallet, so it’s best to follow good security practices.

Security is your paranoia vs their will. If their will is greater than your paranoia, they’ll eventually win. — @BitcoinRevolution4 on Plebnet

If you use onion URLs then that string of text and your password could get keylogged. I use hardware SSH keys and disabled password access. Each new third party app installed is a new attack vector. It’s best to keep it simple and run the bare minimum when possible.

Consider the privacy implications of doxxing any UTXOs you own, exposing your IP, or connecting your Twitter / Telegram to your Lightning node. You don’t need to run a public routing node to use Lightning for your own payments.

Survey the Landscape

We’re almost ready to melt down your digital gold and shape it into some new pipes, but there are 35K+ Lightning nodes. Where to begin?

I spent most of my early days on Amboss and Terminal Web. Browse the top 100 nodes and their connections. Then small ones. Consider:

  • Outbound fees
  • Inbound fees
  • Channel partners
  • Number of channels
  • Size of channels

You can assume that a node is an outbound sink (never routes inbound) if all inbound fees to it are high. If a node has a static very high outbound fee that suggests they might be a good rebalancer (or a bad partner). Nodes with low or zero outbound fees are often great partners, but sometimes inbound sinks.

The vast majority of my earnings come from these popular outbound sinks: LOOP, bfx-lnd0, bfx-lnd1, Nicehash and SeasickDiver. This shouldn’t be too much of a secret if you look at my channels and outbound fees.

My node is built around serving these channels. Fee structure, girth, rebalancing and swapping out. I want these channels to always have outbound liquidity and I want channels that route inbound to them well.

Make a List of Nodes and Channel Sizes

Make a list of nodes you like. It won’t be obvious and it doesn’t need to be perfect. Consider connecting popular nodes that aren’t connected. Find a few low fee nodes, high fee, outbound sinks, or choose one specific niche.

Take a look at channel recommenders and other helpful tools offered by LNDg, LNnodeinsite, LnRouter and Gridflare.

Consider roughly how many sats you can allocate to Lightning. You aren’t going to get very far with less than 20 - 30M sats. Take that number and figure out how many channels you can support.

Don’t make channels smaller than 2M sats. I like girthy channels between 5M - 25M. Large outbound drains 50M - 100M. That means I made less channels, but I believe it has positioned me uniquely. There is no rule.

I base my channel size on the activity + channel sizes of the node I’m partnering with. If the node has all 5M channels then there’s no point in 20M. If a node routes a lot of large payments I want a bigger channel to support that. I’ve updated many channel sizes over time.

If I had to choose one channel size it would be 5M sats.

Open a Lot of Channels

My basic bootstrap approach was to open a lot of channels at once, then purchase and rebalance LNBig inbound into them. It slowly grew organically from there.

Open a batch of channels with BOS:
bos open <pubkey> — amount <amount> <pubkey> — amount <amount>, etc.

Once you have a few channels opened, use LNnodeinsight to run channel opening simulations to see channel overlaps and score improvements for potential new partners.

Set Fees

You can use fees to earn sats and steer routing. Increase your fee to decrease the outbound flow of sats and vice versa. The goal is not always a balanced channel but rather to get sats into the spots they are most demanded.

I run my node with part dynamic fees and part static fees. I categorize my channels into 3 buckets:

  • Good Outbound — manually updated based on flow
    704 - 1904ppm
  • Ok Outbound — updated hourly based on balance
    0 - 10% outbound (444ppm)
    11 - 100% outbound (284ppm)
  • Routers — updated hourly based on balance
    0 - 10% outbound (444ppm)
    11 - 25% outbound (284ppm)
    26 - 75% outbound (84ppm)
    76 - 100% outbound (4ppm)

Consider a 4th bucket for permanently low fees if a channel never routes outbound with higher fees but routes inbound very well. I did this with nodes like Breeze, Coingate, PrestonPysh, and Boltz at first but moved away from it as outbound demand grew.

Some nodes run all high static fees. This model requires more rebalancing.

I generally only want Good Outbound and Routers because I can’t rebalance Ok Outbound profitably. If they don’t route inbound at some point they get cut.

In retrospect I should have set fees higher at first. I suggest you do that. If you think a channel might drain then look at the inbound fees for that node and match the highest. Then slowly lower every couple days you don’t route.

I use charge-lnd on an hourly cron to set fees automatically. This tool allows me to set up rules for certain channels or liquidity thresholds.

Update your config with:
nano /home/bitcoin/charge-lnd/charge.config

Do a dry run for fee changes:
/home/bitcoin/.local/bin/charge-lnd -c /home/bitcoin/charge-lnd/charge.config — dry-run

Run fee changes:
/home/bitcoin/.local/bin/charge-lnd -c /home/bitcoin/charge-lnd/charge.config

There is quite a bit of controlled chaos happening at Cold Sats. With low fees some channels will route outbound that wouldn’t otherwise, creating inbound that is difficult or less likely to get. Then that turns into 10M route to LOOP.

Low fees also allow my channel partners to rebalance easier if they wish.

I like to aggressively hold at least a little liquidity on both sides of most channels to avoid route failures due to lack of liquidity. 4ppm and 444ppm help do that.

Don’t open to LOOP at 4ppm and drain 700K sats in a minute, but do tell me about whatever funny mistake you make.

Get Inbound Liquidity

Next comes the tricky part. How do you get others to open channels to you?

Consider using Lightning Network Plus to do swaps for free inbound liquidity. I personally didn’t do any of these because I wanted to be more targeted and less committed. I would have done a few in retrospect.

Once you’re more established, other operators will be willing to do dual-funded channels with you using BOS. I’ve opened 24 dual-funded channels to date.

Many liquidity providers like zero fee routing or LNBig also sell inbound. I purchased 264M sats from LNbig at a cost of 545K sats in my first 2 months. You can also swap out with a protocol like LOOP or mobile wallet like Wallet of Satoshi (WOS), which will push your sats remote and get you inbound.

WOS likely would have been cheaper than my LNBig approach at my scale.

Make node friends. Run a good node and others will start opening channels to you. Once you get your flow going, inbound liquidity won’t be a concern.

Collect Data and Reevaluate

There’s a chicken and egg problem when you first start. In order to get good data you need to have a system with inbound liquidity in most channels. That’s why I opted to open a lot of channels at once and rebalance LNBig inbound into them.

I burned sats in the beginning to collect data. I spent 177K on rebalance (+ on chain fees) and earned 79K in routing fees in my first full month. By the second month I was profitable with 157K earned and 117K spent. Things got a lot more interesting in the third month.

You will need 2 – 4 weeks of data. Watch the flow of all of your channels. Ensure that each channel gets some inbound to see how it routes. Sometimes a channel will awaken after a long slumber. If not, close it. I’ve closed 145 channels to date.

Historically I have only cut channels that I opened. That way it’s no loss to the other operator. I like to maintain good relationships, but if there is truly no movement then neither operator should be upset about a cordial separation.

You will continue to reevaluate through the whole life of the node, but once you have a solid node it’s not a lot of work. At some point you will see consistent patterns emerge and are ready to start rebalancing where profitable.

Rebalance

Rebalancing means sending sats to yourself. Increase inbound in one channel and outbound in another. Depending on your fee structure and what you’ve observed, you might rebalance anywhere from none to all of your channels.

I rebalance only my Good Outbound channels at a rate of 50 - 325ppm depending on current flow. You need high fees to offset that cost. You also need to consider the opportunity cost in moving the sats.

I use rebalance-lnd which is a command line tool. BOS (command line) and LNDg (web GUI) are also popular rebalance tools.

I only set the to channel and rebalance-lnd will automatically attempt to send sats from channels that have a minimum balance of 3M sats. I used to run a large exclude list because I didn’t want to pull sats from bad inbound channels. Over time inbound improved and it shrank. Then I stopped entirely.

I loop a script in a screen for each channel.

Create a screen with:
screen -S wallet

Rebalance with:
for ((i=0;i<5000;i++)); do timeout 600 rebalance-lnd/rebalance.py -a 400000 — to 797247085257949185 — fee-ppm-limit 200 — min-local 3000000; sleep 60; done

Then exit the screen with:
ctrl+a
d

Re-enter screen with:
screen -r wallet

Kill a screen with:
screen -X -S kill wallet

I kill the script every 10 minutes because it will sometimes hang up on a path for a long time. The downside of running scripts like this is that it can cause more stuck HTLCs which can be an issue in force closures. Rebalance attempts also add to the size of your channel.db.

Typically I have 2 - 5 scripts running lately, one for each channel. I’ll adjust params or turn them off sometimes if my pace is too fast. It’s quite a manual targeted approach.

I don’t spend a lot of time on it now but it’s a semi-weekly dance.

Swap Out

I swap sats out of Lightning so that I can open new channels to Good Outbound nodes after they have drained. This is only economical at certain scales and for channels that command very high fees.

I have a large channel with WOS that I can rebalance at 50 - 200ppm. It’s relatively easy and reliable to rebalance. I turn this dial up and down given my current pace of outbound vs rebalance vs swap out flow.

When I’m ready to swap out I send sats from WOS channel to WOS wallet, then pay 7 - 8K (varies with mempool depth) to send back to myself on chain.

The round trip costs me up to 360ppm for 50M sats or 280ppm for 100M.

Maintain Your Node

The more activity in your node (rebalances + routes) the larger your channel.db will grow. You will need to regularly compact the channel.db to decrease the size. Currently LND can only do this during a restart. Mine is 11GB right now.

Check the size of your channel.db with (path depending on machine):
sudo du -ha /data/lnd/data/graph/mainnet/channel.db

Once a channel reaches over 100–200K updates consider closing and re-opening it. This will clear the data stored for that channel. Wait until more sats are on your side because on chain sats and inbound liquidity are valuable.

Check your largest channels with:
lncli listchannels | jq -r ‘.[][]| [.num_updates, .remote_pubkey] | @tsv’ | sort -rn

There are dozens of other helpful commands for LND and BOS.

Join the Community

There’s a special social movement happening in Lightning. It pulled me into Twitter after years of lurking. I joined Bitcoin at the end of 2013 and when I look around at Lightning now I get the same vibes. It’s mostly technical, ideal driven, optimistic people.

I joined Plebnet Telegram about a month into my journey and it opened up a new dimension. I’ve made dozens of node friends and learned so much about Bitcoin, Lightning and Linux. Read the past conversations there and ask questions.

Take a Step Back

Recognize again that the target will move and Lightning will hopefully be a different, much larger place in the future.

Lightning is a long term game of patience. Changes to your fees can take days to weeks to make an effect. I didn’t route to my golden goose LOOP for the last 3 days, then 10M this morning.

When you route a random payment consider where that payment came from. Sure it’s often a rebalance but I’m sure I’ve routed remittances to El Salvador.

I run a Lightning node not just to earn sats but to help scale Bitcoin. Permisionless sound money is a fundamental human right and never before has there been an opportunity like this to enforce that.

I got struck by Lightning and I hope you get struck too.

--

--