Repository navigation
Releases: IkarusMK/satoshicortex
Release list
SatoshiCortex 1.5.0
Image: ghcr.io/ikarusmk/satcortex:1.5.0 · released 2026-10-01
Update: docker compose pull && docker compose up -d (with SATCORTEX_VERSION=latest in your .env). Only the application image is new — LND, Bitcoin Core and Tor keep running, only the app container restarts. Nothing to change in docker-compose.yml or .env.
If the fee automation was switched on, it now steers each channel by its fill level and sets a maximum per payment that follows it — starting once about half a day of fill levels has been measured. Channels you want to keep as they are: open their row and choose fixed.
Verify what you pull:
gh attestation verify oci://ghcr.io/ikarusmk/satcortex:1.5.0 --owner IkarusMKFull history in CHANGELOG.md.
Added: fees per channel by fill level
- The fee automation now prices each channel by how full it is on your
side: from 80 % half the anchor, 50–80 % the anchor, 20–50 % one and a
half times, below 20 % three times. The anchor is the network median within
the four-week band, as before. - It decides on the average fill level, never on the moment. Every channel
is measured hourly; the automation looks at the last 24 hours — or 72, if
you choose every three days — and touches a channel at most once in that
period. A channel without enough measurements (right after the update, or a
new one) waits until at least half the period is measured, and its row says
so. Five percentage points of slack at each step boundary. - One switch for all channels, and a choice per channel: automatic or
fixed. A fixed channel is never touched, the base fee never. - It never moves money. Rebalancing stays a button you press, with your
PIN.
Added: a maximum per payment for each channel
The largest single payment a channel forwards (max_htlc), set in the
channel's row: fixed by hand, or following the fill level — half of what is
spendable on your side, rounded down to 10,000 sat, never below 1 % of the
capacity. Checked against what LND accepts for that channel before anything
is sent.
Added: earnings per channel
Fees earned against what the channel cost to open, rebalance and close — per
7, 30 or 90 days or since the start, with a monthly chart, a table per channel,
the earnings per million sat of capacity, and the final balance of closed
channels. The fee counts at the outgoing channel, rebalancing at the channel
that was refilled, opening only if you opened it. Fees of outside swap
services never reach LND and are not included; the page says so.
Changed: the Channels page
- An overview on top — capacity, your side, the far side, the net of the last
30 days — with buttons to open, rebalance, fees and earnings. - One row per channel with bar, capacity, fee and automation step, maximum per
payment, reachability and the net of 30 days. A row unfolds into the
channel's balance, age, who opened it, the steering of fee and maximum, its
earnings since opening, and the buttons for exactly this channel. - The panels below sit in sections: Earnings, Steer, Open & close,
Watch, Protection. - The Forwarded summary is part of the earnings now. Your node in the
network moved to the Node tab.
Changed: every table fits a phone
On a narrow screen each table — what went through your node, earnings, route
knowledge, blocks, the countries on the map — turns into stacked rows with the
column names beside the values. No view scrolls sideways at phone width.
Changed: housekeeping
Comments and test descriptions describe reports from operation in their own
words instead of quoting them, and every example address in the code and the
tests comes from the documentation ranges.
SatoshiCortex 1.4.2
Image: ghcr.io/ikarusmk/satcortex:1.4.2 · released 2026-09-29
Update: docker compose pull && docker compose up -d (with SATCORTEX_VERSION=latest in your .env). Only the application image is new — LND, Bitcoin Core and Tor keep running, only the app container restarts. Nothing to change in docker-compose.yml or .env.
Verify what you pull:
gh attestation verify oci://ghcr.io/ikarusmk/satcortex:1.4.2 --owner IkarusMKFull history in CHANGELOG.md.
Changed: the wallet keeps on-chain and Lightning apart
- The balance comes in two blocks, On-chain and Lightning · in your
channels, each with the two buttons that belong to it — Deposit and
Send, Create invoice and Pay invoice. They jump to the matching panel
further down. - Your transactions stay right under the balance. Below them the panels sit
in two sections, On-chain (bc1…) and Lightning (lnbc…), each with a
sentence on what belongs there. - Receive is now called Create a Lightning invoice. Next to Pay a
Lightning invoice it did not say which of the two ways it meant. - The note on the channel reserve sits under both blocks instead of as a
narrow column beside the numbers.
Changed: "What went through your node", second pass
Found on a running node after 1.4.1.
- Your own rebalancing is shown as Rebalancing — out via one channel, back
via the other — instead of as a payment from you and one to you. It is
recognised from LND's own payment list: a payment that comes back over one
of your own channels. A failed attempt no longer reads like someone else's
payment gone wrong, and it gets no warning colour — nothing was lost. - The list of events has its own heading. After a single refusal it ran
straight on below the table of reasons and read like a second header row. - A payment stands once, not as started and again as went through. The
amount moves into the line with the outcome — also for lines recorded
before this version.
Upgrading
Only the application image is new; Bitcoin Core, LND and Tor keep running.
Nothing to change in docker-compose.yml or .env.
SatoshiCortex 1.4.1
Image: ghcr.io/ikarusmk/satcortex:1.4.1 · released 2026-09-29
Update: docker compose pull && docker compose up -d (with SATCORTEX_VERSION=latest in your .env). Only the application image is new — LND, Bitcoin Core and Tor keep running, only the app container restarts. Nothing to change in docker-compose.yml or .env.
Verify what you pull:
gh attestation verify oci://ghcr.io/ikarusmk/satcortex:1.4.1 --owner IkarusMKFull history in CHANGELOG.md.
Fixed: the Electrum card gives each app the line it accepts
Found at the first test with a real device.
- The card offered
host:port, and Trezor Suite answers that with Invalid
URL — it wantshost:port:t. Each route now shows one line per app, ready
to copy: Trezor Suite with:t, the BitBoxApp without; an IPv6 address in
brackets. - The home network address came from the browser's address bar. Opened
through a domain behind a reverse proxy, that was the domain — useless for
Electrum. The card now takes an IP address or a home-network name from the
address bar, and otherwise asks for the server's address once and keeps it. - The steps in the interface name the apps' real menus — checked against
Trezor Suite 26.9.2 and the BitBoxApp's source — in German and English, and
say that a BitBoxApp account can hold a Native SegWit and a Taproot key.
Fixed: an earlier "in use since" date searches again
Registering an account again with an earlier date now makes the node search
from that date. Before, a second registration only loaded the wallet, and
history older than the first date stayed missing. Checked against a real
Bitcoin Core with the chain's clock moved ten days forward.
Changed: "What went through your node" says what it means
- Forwarded, to you and from you are shown apart. LND says it in the channel
numbers: no incoming channel for a payment you send, no outgoing one for a
payment to you. So "channel 0" is gone — also for entries recorded before
this version. - Every reason LND knows, all 53, in plain language. A warning colour and a
concrete step only where there is something to do: a channel out of
balance on your side, an amount above your channel maximum, a peer that is
not connected. - Probes — payments without an invoice that others send to test a route to
you — are counted on their own. They are not a fault; nothing to do. - Both lists are tables now, like the routes your node has learned: what was
turned down (direction, reason, route, count) and the latest events (time,
direction, result, amount, fee, route). Channels by name; a forward that
went through shows the fee you earned. - Where LND's detailed reason says "no detail", the reason on the wire is
shown instead of nothing.
Added: look up and copy every connection
Each line under Your connections now has Look at the node and Copy key.
Nodes without a name showed only a shortened key before — neither to look up
nor to copy.
Fixed: copy buttons never stay silent
Where the clipboard asks for permission and never answers, every copy button
on the page stayed silent. After a second and a half the text is now marked
and the button says so. Lists that refresh on their own — the Electrum routes
while an account is searching, Your connections — are only rebuilt when
something changed, so the Copied note stays.
Upgrading
Only the application image is new; Bitcoin Core, LND and Tor keep running.
Nothing to change in docker-compose.yml or .env.
SatoshiCortex 1.4.0
Image: ghcr.io/ikarusmk/satcortex:1.4.0 · released 2026-09-28
Update: docker compose pull && docker compose up -d (with SATCORTEX_VERSION=latest in your .env). Correction: besides the application, the satcortex-bitcoind (31.1) and satcortex-lnd (v0.21.3-beta) images were rebuilt in the same versions — a comment change in example.env triggers their rebuild. A full pull therefore restarts Bitcoin Core and LND once; Tor keeps running. Over Tor nothing else changes; for the home network route see Upgrading below. Version 1.4.1 rebuilds only the application again.
Verify what you pull:
gh attestation verify oci://ghcr.io/ikarusmk/satcortex:1.4.0 --owner IkarusMKFull history in CHANGELOG.md.
Added: BitBoxApp and Trezor Suite over Electrum — without electrs
Both apps connect only to an Electrum server. SatoshiCortex now answers the
Electrum protocol itself, under External wallets — no extra container, no
address index over the whole chain, no hours of extra syncing.
You register an account with its public key (xpub, ypub or zpub; for a
plain xpub you pick the address type). Bitcoin Core follows it as a watch-only
wallet and searches the chain with the block filters the node builds anyway.
Everything else the apps ask — headers, transactions, merkle proofs, fee
estimates, broadcasting — comes from Bitcoin Core directly. Signing stays on
the device; the service only passes on what the device has already signed.
- Two routes: your home network (opt-in, see Upgrading) and Tor, with an
onion address of its own while the service is switched on. - TLS and plain TCP on the same port, told apart by the first byte. The
tab shows the self-signed certificate and its fingerprint for the BitBoxApp. - One search at a time. Registering several accounts queues them; each
waits for the one before, so the node is never searching twice at once. An
account whose search had not yet started when the application restarted
says so and asks to be registered again — and does not hold up the others. - Private keys are refused before they go anywhere. The public key is kept
only in the node, never in the application's settings. - Protocol 1.4, the version both apps pin and electrs speaks. A daily
check reads both apps' sources and fails the moment either asks for a
command or version this service does not answer. - Tested end to end against a real Bitcoin Core on regtest: the command
sequences of both apps, balances, unspent outputs and history against what a
wallet holding the keys reports itself, every header linking to the tip and
every merkle proof leading to the header's root, and a payment signed by the
"device" and broadcast through this service. These tests now run in CI with
the same verified Bitcoin Core release as the image.
Upgrading
Tor works without any change. For the home network route, take the new
docker-compose.yml (it adds one port line to app, closed by default) and
set both lines in your .env:
ELECTRUM_BIND=0.0.0.0
ELECTRUM_LAN_PORT=50001
Never forward that port in your router.
SatoshiCortex 1.3.3
Image: ghcr.io/ikarusmk/satcortex:1.3.3 · released 2026-09-27
Update: docker compose pull && docker compose up -d (with SATCORTEX_VERSION=latest in your .env). Only the application image is new — LND, Bitcoin Core and Tor keep running, only the app container restarts. Nothing to change in docker-compose.yml or .env.
Verify what you pull:
gh attestation verify oci://ghcr.io/ikarusmk/satcortex:1.3.3 --owner IkarusMKFull history in CHANGELOG.md.
Fixed: Look at the node called a node reachable without checking
When a node showed no warnings, Look at the node said it "announces
regularly, is reachable and well connected". The reachable part was never
checked. Every finding in that box comes from your own graph — what the node
announces about itself — and announcing an address does not mean anything
answers there. The channel list could show a partner as rarely online while
the lookup called it reachable in the same moment.
The verdict now says only what the graph can tell: announces regularly, lists
an address, is well connected — and that this says nothing about whether the
node answers right now. Below it, a second line reports what your node
actually knows at this moment, from LND and without any new measurement:
- Connected right now — your node has a live connection to it.
- Not connected, even though you share a channel — LND re-establishes
connections to channel partners on its own; if none is up, the node cannot
be reached at the moment, and nothing flows through that channel. - No connection, no channel — normal; Connect shows whether it answers.
If LND cannot tell, the line is left out rather than guessed. A node that is
not in your graph can still show as connected, for example one with only
private channels.
SatoshiCortex 1.3.2
Image: ghcr.io/ikarusmk/satcortex:1.3.2 · released 2026-09-26
Update: docker compose pull && docker compose up -d (with SATCORTEX_VERSION=latest in your .env). Only the application image is new — LND, Bitcoin Core and Tor keep running, only the app container restarts. Nothing to change in docker-compose.yml or .env.
Verify what you pull:
gh attestation verify oci://ghcr.io/ikarusmk/satcortex:1.3.2 --owner IkarusMKFull history in CHANGELOG.md.
Fixed: "your node appears NOWHERE in the Lightning graph" — on every node
Under Wallet, every running node read: "as long as you have no public
channel, your node appears NOWHERE in the Lightning graph". It said so on nodes
with public channels too — the sentence depended on the wallet state only,
never on the channels. Found while renewing the screenshots.
The interface now works it out from your own channels. A public channel is
announced from its sixth confirmation on (BOLT 7), and the node with it; the
block it was funded in sits in the channel's short channel id, so no extra
call is needed. The line now says one of three things: your node is in the
graph, your public channel will be announced from its sixth confirmation on,
or — only when there really is no public channel — that nobody finds it yet.
Until the channels have loaded, it claims nothing about the graph at all.
Changed: the README shows the current version
All screenshots are new. The earlier ones dated from before the first public
release — an old version number, the navigation without Connect, and a
display fault fixed in 1.2.5. New screens show the network contribution, the
mempool tiles, the blocks, the fee panel and receiving over Lightning. The
highlights now name what had been missing: paying and receiving, moving
liquidity, fees against the network, the channel backup to your own WebDAV,
restoring, and how the wallet opens after a restart.
SatoshiCortex 1.3.1
Image: ghcr.io/ikarusmk/satcortex:1.3.1 · released 2026-09-26
Update: docker compose pull && docker compose up -d (with SATCORTEX_VERSION=latest in your .env). Only the application image is new — LND, Bitcoin Core and Tor keep running, only the app container restarts. Nothing to change in docker-compose.yml or .env.
Verify what you pull:
gh attestation verify oci://ghcr.io/ikarusmk/satcortex:1.3.1 --owner IkarusMKFull history in CHANGELOG.md.
Fixed: "database is locked" and lost messages in the evaluation
Seen on a running node: sqlite3.OperationalError: database is locked, and
shortly after a gap in bitcoind's event stream.
Both had the same root in the part that records what bitcoind reports.
- It asked the node about its sync state for every single message —
through the full status query, five RPC calls, two of which wait for
Bitcoin Core's main lock. With a busy mempool that is dozens of messages a
second, and during a new block each of those calls can hang for up to
fifteen seconds. It now asks once every thirty seconds, with one call. - It held the database's write lock while it waited. Rows of the last
seconds were written but not yet committed when those calls started, so
every other writer — the HTLC stream, the news, the interface — waited
twenty seconds and gave up. Events are now collected in memory and written
in one short transaction that contains database work and nothing else. - No answer was taken for "back in sync". When that status call timed
out, the recorder put its connection down and reconnected — and everything
published in between was lost. Only a clear "yes" from bitcoind pauses it
now. - A locked database no longer kills the recorder. Before, the error
ended its thread, and the evaluation stood still until the application was
restarted. Now the collected events wait and are written on the next
attempt, with the time they arrived. Should the database stay unwritable
for a long time, what has to be dropped is recorded as a gap instead of
missing silently. - Two more ways to the same error are closed. SQLite starts a
transaction as a reader; one that read and then wrote — every block does —
failed at once if anyone else had saved something in between, however long
it was willing to wait. Transactions now take the write lock at their
start. And a failed write no longer leaves its transaction open. - The daily clean-up deletes in portions, so it no longer holds the lock
for as long as removing a whole day of transactions takes.
Fixed: the fee fields showed a default instead of your fees
After every restart or reload the fee fields read 100 ppm and 0, whatever
the channels actually charged. The fees themselves were never lost — LND
keeps them — the interface just never asked.
- The fields are now filled with what the selected channel charges, taken
from LND's fee report (FeeReport, checked in v0.21.3-beta), and a line
below the channel choice says it in words. For All channels with
different fees per channel, the line names the range and the most common
value is filled in. - The channel view refreshes itself regularly. What you type is not
overwritten by that refresh; choosing another channel or setting the fees
shows the current state again. - If LND cannot say what the channels charge, the line says so instead of
letting the default pass for your setting.
Changed: the README's diagram shows the phone
How it works now draws both routes for Zeus — over Tor, through an onion
address of its own, and over your router's VPN — and says which ports open
only when you switch them on.
SatoshiCortex 1.3.0
Image: ghcr.io/ikarusmk/satcortex:1.3.0 · released 2026-09-26
Update: docker compose pull && docker compose up -d (with SATCORTEX_VERSION=latest in your .env). This release rebuilds all four images; LND and Bitcoin Core keep their versions, their containers restart once. For the VPN route to external wallets, take over the new docker-compose.yml.
Verify what you pull:
gh attestation verify oci://ghcr.io/ikarusmk/satcortex:1.3.0 --owner IkarusMKFull history in CHANGELOG.md.
New: external wallets — Zeus on your phone, over Tor or VPN
A new tab, External wallets, connects Zeus on a phone to this node. Zeus
then talks to LND directly — balances, channels, invoices, payments —
depending on what you allow the device.
- Two routes, and only these two.
- Tor: for the first Tor device the node creates an onion address of its
own, for Zeus only. It is announced nowhere and exists only while at least
one device uses it. - VPN: LND's REST interface on your home network, reached through your
router's VPN. Off by default: setLND_REST_BINDandLND_REST_LAN_PORT
in the.envand redeploy with the newdocker-compose.yml. Nothing is
opened to the internet.
- Tor: for the first Tor device the node creates an onion address of its
- Permission levels, checked against LND's permission table
(v0.21.3-beta): view, receive, pay over Lightning (no on-chain
sending, no opening or closing channels — both needonchain:write) and
full. Not even full may issue keys, so a stolen phone cannot mint itself
a replacement that survives its revocation. - One root key per device. Revoking a device deletes its root key: that
device's key is worthless at once, every other key keeps working. The
default root key, which the application's own macaroon hangs on, can never
be touched. - Behind the PIN, like every other way money can leave: issuing and
revoking keys. The key is shown once, as a QR code and as text, and stored
nowhere. - Said plainly in the interface: LND has no spending limit for keys, this
page's PIN does not apply inside Zeus, and a key cannot be tied to one of
the two routes — LND hands every REST request to gRPC over127.0.0.1, so
an IP lock would always see the same address. - QR codes up to version 20 (666 bytes). A key for Zeus is about 450
characters long and did not fit into the previous limit of 213.
Changed: the wallet-software release moved
The release for Sparrow and hardware wallets now sits in the same tab. Saving
it changes only the home-network release; before, it sent all network
settings along, taken from the fields of the settings page.
Changed: build metadata
Images are built without BuildKit provenance, and no build record or build
summary is uploaded any more. Provenance stays verifiable through the signed
attestation:
gh attestation verify oci://ghcr.io/ikarusmk/satcortex:1.3.0 --owner IkarusMK
Upgrading
- For the Tor route, pulling the new image is enough.
- For the VPN route, take over the new
docker-compose.ymland add the two
lines to your.env(seeexample.env). Without them nothing changes.
SatoshiCortex 1.2.6
Image: ghcr.io/ikarusmk/satcortex:1.2.6 · released 2026-09-24
Update: docker compose pull app && docker compose up -d app (with SATCORTEX_VERSION=latest in your .env).
Verify what you pull:
gh attestation verify oci://ghcr.io/ikarusmk/satcortex:1.2.6 --owner IkarusMKFull history in CHANGELOG.md.
Improved: rebalancing knows the peer's limit and follows up by itself
A rebalance through a channel to an LDK node, for more than a quarter of that
channel's capacity, could never succeed: LDK accepts at most 25 % of a channel
in flight at a time. LND split the payment, the second part never left, and
after 80 seconds the interface said "no answer" and locked the button until the
page was reloaded. How it ended was only in LND's log.
- The limit is shown before you press. LND reports per channel how much
the peer accepts at once (local_constraints.max_pending_amt_msat—
checked in v0.21.3-beta: that is where the peer'smax_htlc_value_in_flight
ends up, and LND checks our own HTLCs against it). The rebalance box names
it and the largest amount that fits into one round including fees, and
nothing is sent that is bound to fail. The server checks the same, after
the PIN. - No answer no longer means "reload and guess". The server passes on the
payment's identifier; the interface then follows the payment itself
(TrackPaymentV2) and reports "moved" or "not moved" with the reason. The
button stays locked while the payment is still in flight and unlocks as soon
as the outcome is known.
Fixed: test data and comments taken from a real node
Some test fixtures and comments used values from a real installation — an
address, amounts, identifiers — instead of made-up ones. They are replaced with
synthetic values (addresses from the documentation range 203.0.113.0/24).
SatoshiCortex 1.2.5
Image: ghcr.io/ikarusmk/satcortex:1.2.5 · released 2026-09-24
Update: docker compose pull app && docker compose up -d app (with SATCORTEX_VERSION=latest in your .env).
Verify what you pull:
gh attestation verify oci://ghcr.io/ikarusmk/satcortex:1.2.5 --owner IkarusMKFull history in CHANGELOG.md.
Fixed: "Lightning can be set up" on a node that is set up
The Lightning box on the overview, and the header under Wallet, said
"Blockchain: complete — Lightning can be set up" as long as the chain was
complete, even with the wallet created, unlocked and channels open. The line
knew only the chain, never the wallet — the same kind of mistake that was
fixed in the hint below it on 2026-09-09.
It now says "can be set up" only while there is demonstrably nothing set up:
LND reports no wallet, or Lightning has not been configured at all. If LND does
not answer, nobody here knows whether a wallet exists, and the line just says
"complete". Both boxes share one function now, and a test runs it in Node
against every wallet state.