Lightning Security Module (Remote Signer)
Set up an lnd remote signer container that holds private keys on a separate,
secured machine. The signer never routes payments or opens channels — it only
holds keys and signs when asked by a watch-only litd node.
Architecture
CODEBLOCK0
The watch-only node handles all networking and channel management. The signer
node holds the seed and performs cryptographic signing. Even if the agent machine
is fully compromised, the attacker cannot extract private keys.
See references/architecture.md for the full
architecture explainer.
Quick Start (Container — Recommended)
On the Signer Machine
CODEBLOCK1
On the Agent Machine
CODEBLOCK2
Two-Container Local Setup
For testing both on the same machine:
CODEBLOCK3
Installation
Default: pulls the lnd Docker image for the signer.
CODEBLOCK4
This pulls lightninglabs/lnd:v0.20.0-beta from Docker Hub. The signer only
needs plain lnd (not litd) since it only holds keys and signs.
Build from Source (Fallback)
CODEBLOCK5
Native Mode
For running the signer without Docker:
CODEBLOCK6
Remote Nodes
Export credentials from a remote signer:
CODEBLOCK7
Credential Bundle Format
The exported bundle (~/.lnget/signer/credentials-bundle/) contains:
| File | Purpose |
|---|
| INLINECODE2 | Account xpubs for watch-only wallet import |
| INLINECODE3 |
Signer's TLS certificate for authenticated gRPC |
|
admin.macaroon | Signer's admin macaroon for RPC authentication |
The bundle is also available as a single base64-encoded tar.gz file
(credentials-bundle.tar.gz.b64) for easy copy-paste transfer between machines.
Scripts
| Script | Purpose |
|---|
| INLINECODE6 | Pull lnd signer image (or build from source) |
| INLINECODE7 |
Start signer container |
|
docker-stop.sh | Stop signer container |
|
setup-signer.sh | Create signer wallet and export credentials |
|
start-signer.sh | Start signer (delegates to Docker by default) |
|
stop-signer.sh | Stop signer (delegates to Docker by default) |
|
export-credentials.sh | Re-export credentials from running signer |
Managing the Signer
Start
CODEBLOCK8
Stop
CODEBLOCK9
Re-export Credentials
If TLS certificates or macaroons have been regenerated:
CODEBLOCK10
Configuration
Container Config
The signer compose template is at
skills/lightning-security-module/templates/docker-compose-signer.yml. Config
is passed via command-line arguments.
Native Config
The native signer config template is at
skills/lightning-security-module/templates/signer-lnd.conf.template. Key
differences from a standard lnd node:
- - No P2P listening (
--listen=) — signer doesn't route - RPC on 0.0.0.0:10012 — accepts connections from watch-only node
- REST on localhost:10013 — local only, for wallet creation
- TLS extra IP 0.0.0.0 — watch-only on a different machine can connect
- No autopilot, no routing fees — signer is signing-only
Security Model
What stays on the signer:
- - 24-word seed mnemonic
- All private keys (funding, revocation, HTLC)
- Wallet database with key material
What gets exported:
- - Account xpubs (public keys only — cannot spend)
- TLS certificate (for authenticated connection)
- Admin macaroon (for RPC auth — scope down for production)
Threat model:
- - Compromised agent machine cannot sign transactions or extract keys
- Attacker with agent access can see balances and channel state but not spend
- Signer machine should have minimal attack surface
Production hardening:
- - Replace admin macaroon with a signer-only macaroon (see
macaroon-bakery) - Restrict signer RPC to specific IP addresses via firewall
- Run signer on dedicated hardware or a hardened VM
- Use Lightning Node Connect (LNC) via
lightning-mcp-server for read-only agent access
Macaroon Bakery for Signer
For production, bake a signing-only macaroon:
CODEBLOCK11
Then re-export the credentials bundle with the scoped macaroon.
Container & Ports
| Container | Purpose | Ports |
|---|
| INLINECODE18 | Remote signer (lnd) | 10012, 10013 |
| Port | Service | Interface | Description |
|---|
| 10012 | gRPC | 0.0.0.0 | Signer RPC (watch-only connects here) |
| 10013 |
REST | 0.0.0.0 | REST for wallet creation |
File Locations
| Path | Purpose |
|---|
| INLINECODE19 | Signer wallet passphrase (0600) |
| INLINECODE20 |
Signer seed mnemonic (0600) |
|
~/.lnget/signer/credentials-bundle/ | Exported credentials |
|
~/.lnget/signer/signer-lnd.conf | Signer config (native mode) |
|
versions.env | Pinned container image versions |
闪电安全模块(远程签名器)
在独立的安全机器上设置一个持有私钥的lnd远程签名器容器。签名器从不路由支付或开启通道——它仅持有密钥,并在被只读litd节点请求时进行签名。
架构
代理机器 签名器机器(安全)
┌─────────────────┐ ┌─────────────────────┐
│ litd(只读) │◄──gRPC───►│ lnd(签名器) │
│ - neutrino │ │ - 持有种子 │
│ - 管理通道 │ │ - 签名承诺交易 │
│ - 路由支付 │ │ - 签名链上交易 │
│ - 无密钥材料 │ │ - 无P2P网络连接 │
└─────────────────┘ └─────────────────────┘
只读节点处理所有网络和通道管理。签名器节点持有种子并执行加密签名。即使代理机器被完全攻破,攻击者也无法提取私钥。
完整架构说明请参见 references/architecture.md。
快速开始(容器——推荐)
在签名器机器上
bash
1. 安装lnd签名器镜像
skills/lightning-security-module/scripts/install.sh
2. 启动签名器容器
skills/lightning-security-module/scripts/start-signer.sh
3. 设置签名器钱包并导出凭证
skills/lightning-security-module/scripts/setup-signer.sh
4. 将凭证包复制到代理机器
设置脚本会打印凭证包路径和base64字符串。
在代理机器上
bash
5. 导入凭证包
skills/lnd/scripts/import-credentials.sh --bundle
6. 以只读模式启动litd
skills/lnd/scripts/start-lnd.sh --watchonly
7. 创建只读钱包
skills/lnd/scripts/create-wallet.sh
8. 检查状态
skills/lnd/scripts/lncli.sh getinfo
双容器本地设置
在同一台机器上进行测试:
bash
同时启动litd + 签名器
skills/lnd/scripts/start-lnd.sh --watchonly
设置签名器钱包
skills/lightning-security-module/scripts/setup-signer.sh --container litd-signer
导入凭证并创建只读钱包
skills/lnd/scripts/import-credentials.sh --bundle ~/.lnget/signer/credentials-bundle
skills/lnd/scripts/create-wallet.sh --container litd
安装
默认:拉取签名器的lnd Docker镜像。
bash
skills/lightning-security-module/scripts/install.sh
这将从Docker Hub拉取 lightninglabs/lnd:v0.20.0-beta。签名器只需要普通的lnd(而非litd),因为它仅持有密钥并进行签名。
从源码构建(备用方案)
bash
skills/lightning-security-module/scripts/install.sh --source
原生模式
无需Docker运行签名器:
bash
原生设置签名器
skills/lightning-security-module/scripts/setup-signer.sh --native
原生启动签名器
skills/lightning-security-module/scripts/start-signer.sh --native
原生停止签名器
skills/lightning-security-module/scripts/stop-signer.sh --native
远程节点
从远程签名器导出凭证:
bash
skills/lightning-security-module/scripts/export-credentials.sh \
--rpcserver signer-host:10012 \
--tlscertpath ~/signer-tls.cert \
--macaroonpath ~/signer-admin.macaroon
凭证包格式
导出的包(~/.lnget/signer/credentials-bundle/)包含:
| 文件 | 用途 |
|---|
| accounts.json | 用于只读钱包导入的账户扩展公钥 |
| tls.cert |
签名器的TLS证书,用于认证gRPC连接 |
| admin.macaroon | 签名器的管理员macaroon,用于RPC认证 |
该包也可以作为单个base64编码的tar.gz文件(credentials-bundle.tar.gz.b64)提供,方便在机器间复制粘贴传输。
脚本
| 脚本 | 用途 |
|---|
| install.sh | 拉取lnd签名器镜像(或从源码构建) |
| docker-start.sh |
启动签名器容器 |
| docker-stop.sh | 停止签名器容器 |
| setup-signer.sh | 创建签名器钱包并导出凭证 |
| start-signer.sh | 启动签名器(默认委托给Docker) |
| stop-signer.sh | 停止签名器(默认委托给Docker) |
| export-credentials.sh | 从运行中的签名器重新导出凭证 |
管理签名器
启动
bash
Docker(默认)
skills/lightning-security-module/scripts/start-signer.sh
指定网络
skills/lightning-security-module/scripts/start-signer.sh --network mainnet
停止
bash
Docker停止(保留数据)
skills/lightning-security-module/scripts/stop-signer.sh
Docker停止并删除卷
skills/lightning-security-module/scripts/stop-signer.sh --clean
重新导出凭证
如果TLS证书或macaroon已重新生成:
bash
skills/lightning-security-module/scripts/export-credentials.sh
配置
容器配置
签名器的compose模板位于
skills/lightning-security-module/templates/docker-compose-signer.yml。配置通过命令行参数传递。
原生配置
原生签名器配置模板位于
skills/lightning-security-module/templates/signer-lnd.conf.template。与标准lnd节点的关键区别:
- - 无P2P监听(--listen=)——签名器不路由
- RPC监听0.0.0.0:10012——接受来自只读节点的连接
- REST监听localhost:10013——仅本地,用于钱包创建
- TLS额外IP 0.0.0.0——允许不同机器上的只读节点连接
- 无自动导航,无路由费用——签名器仅用于签名
安全模型
保留在签名器上的内容:
- - 24词种子助记词
- 所有私钥(资金、撤销、HTLC)
- 包含密钥材料的钱包数据库
导出的内容:
- - 账户扩展公钥(仅公钥——无法花费)
- TLS证书(用于认证连接)
- 管理员macaroon(用于RPC认证——生产环境中应缩小范围)
威胁模型:
- - 被攻破的代理机器无法签名交易或提取密钥
- 拥有代理访问权限的攻击者可以查看余额和通道状态,但无法花费
- 签名器机器应具有最小的攻击面
生产环境加固:
- - 将管理员macaroon替换为仅签名macaroon(参见 macaroon-bakery)
- 通过防火墙将签名器RPC限制为特定IP地址
- 在专用硬件或加固的虚拟机上运行签名器
- 通过 lightning-mcp-server 使用闪电节点连接(LNC)实现只读代理访问
签名器的Macaroon烘焙
对于生产环境,烘焙一个仅签名的macaroon:
bash
skills/macaroon-bakery/scripts/bake.sh --role signer-only \
--container litd-signer --rpc-port 10012
然后使用限定范围的macaroon重新导出凭证包。
容器与端口
| 容器 | 用途 | 端口 |
|---|
| litd-signer | 远程签名器(lnd) | 10012, 10013 |
| 端口 | 服务 | 接口 | 描述 |
|---|
| 10012 | gRPC | 0.0.0.0 | 签名器RPC(只读节点连接至此) |
| 10013 |
REST | 0.0.0.0 | 用于钱包创建的REST接口 |
文件位置
| 路径 | 用途 |
|---|
| ~/.lnget/signer/wallet-password.txt | 签名器钱包密码(0600权限) |
| ~/.lnget/signer/seed.txt |
签名器种子助记词(0600权限) |
| ~/.lnget/signer/credentials-bundle/ | 导出的凭证 |
| ~/.lnget/signer/s