Files
archy/apps/lightning-stack/manifest.yml
T
archipelagoandClaude Fable 5 abf0f56afc fix(security): close the five host-networked app UIs the audit could not see
Scanning archi-dev-box from OUTSIDE found five ports serving their screens
with no login — lnd-ui 18083, bitcoin-ui 8334, fips-ui 8336, electrs-ui
50002 and the Fedimint Guardian 8175 — none of which appeared in the gate's
unprotected list. They are host-networked, so Podman publishes nothing to
pin and their manifests declared 'ports: []'; the gate builds its map from
declared ports, so it neither protected them nor reported them. An audit
that reports success while five screens are open is worse than no audit.

Their nginx now listens on 127.0.0.1 instead of 0.0.0.0, and each port is
declared 'auth: gated' so the daemon owns the outside. 'bind:' on a
host-networked app is a statement of where the container listens, not a
publish instruction — quadlet already skips PublishPort in host mode.
Guardian 8175 is declared on the fedimint app because its companion has no
manifest, and the gate keys on port, not container.

Credential paths were NOT exposed and are verified so: /lnd-connect-info,
the /proxy/lnd/ passthrough, container logs and every RPC method through
these screens all return 401 unauthenticated. What leaked was the page
shell.

Also fixes the delivery gap that would have made this unshippable: only
bitcoin-ui, lnd-ui and electrs-ui were ever rsynced to
/opt/archipelago/docker, so edits to fips-ui and fedimint-ui reached nodes
through no path at all. All five now sync; the two whose rebuilds the
daemon owns are synced without being handed to container-specs.

Every remaining undeclared port is now declared with a stated reason —
gated: botfights 9100, router 8084, pine 10380; exempt with rationale:
fedimint consensus 8173/8174, gateway 8176/9737, netbird 8086/8087 (TLS +
own auth, and enrolled devices cannot hold a session), pine TLS 10381,
lightning-stack REST 8091 (macaroon, mirrors lnd). Zero undeclared ports
remain across all 56 manifests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 08:46:09 -04:00

80 lines
2.0 KiB
YAML

app:
id: lightning-stack
name: Lightning Stack
version: 0.12.0
description: Complete Lightning Network implementation. Includes LND, CLN, and management tools.
container:
image: lightninglabs/lightning-stack:v0.12.0
image_signature: cosign://...
pull_policy: if-not-present
dependencies:
- app_id: bitcoin-core
version: ">=24.0"
- storage: 50Gi
resources:
cpu_limit: 4
memory_limit: 4Gi
disk_limit: 50Gi
security:
capabilities: [NET_BIND_SERVICE]
readonly_root: true
no_new_privileges: true
user: 1000
seccomp_profile: default
network_policy: isolated
apparmor_profile: lightning-stack
ports:
- host: 9738
container: 9735
protocol: tcp # P2P
auth: none
auth_rationale: >-
Lightning p2p. The BOLT-8 noise handshake authenticates and encrypts the channel itself.
- host: 10010
container: 10009
protocol: tcp # gRPC
auth: none
auth_rationale: >-
LND gRPC, authenticated by macaroon over TLS. Remote wallets depend on reaching this directly.
# Mirrors lnd's 18080 exemption — same LND REST API, same macaroon auth.
- host: 8091
container: 8080
protocol: tcp # REST/Web UI
auth: none
auth_rationale: >-
LND REST, authenticated by macaroon over TLS. A browser login page would break
Zeus and every non-browser wallet client, exactly as for lnd's 18080.
volumes:
- type: bind
source: /var/lib/archipelago/lightning-stack
target: /root/.lightning
options: [rw]
environment:
- BITCOIND_HOST=bitcoin-core
- BITCOIND_RPCUSER=${BITCOIN_RPC_USER}
- BITCOIND_RPCPASS=${BITCOIN_RPC_PASSWORD}
- NETWORK=mainnet
health_check:
type: http
endpoint: http://127.0.0.1:8080
path: /v1/getinfo
interval: 30s
timeout: 5s
retries: 3
bitcoin_integration:
rpc_access: admin
sync_required: true
lightning_integration:
channel_management: true
payment_routing: true