| name | aperture |
| description | Install and run Aperture, the L402 Lightning reverse proxy from Lightning Labs. Use when creating L402 paywalls, configuring paid API endpoints, hosting paid content for other agents, or testing L402 authentication flows. |
Aperture - L402 Lightning Reverse Proxy
Aperture is a reverse proxy that implements the L402 protocol, enabling
payment-gated API access via the Lightning Network. It sits in front of your
backend services and requires Lightning micropayments before granting access.
Source: github.com/lightninglabs/aperture
Quick Start
skills/aperture/scripts/install.sh
skills/aperture/scripts/setup.sh
skills/macaroon-bakery/scripts/bake.sh --role invoice-only \
--save-to ~/.lnd/data/chain/bitcoin/mainnet/invoice.macaroon
skills/aperture/scripts/start.sh
lnget -k --no-pay https://localhost:8081/api/test
How Aperture Works
- Client requests a protected resource through Aperture
- Aperture responds with HTTP 402 +
WWW-Authenticate: L402 header containing
a macaroon and a Lightning invoice
- Client pays the invoice and obtains the preimage
- Client retries with
Authorization: L402 <macaroon>:<preimage>
- Aperture validates the token and proxies to the backend service
Installation
skills/aperture/scripts/install.sh
This will:
- Verify Go is installed
- Run
go install github.com/lightninglabs/aperture/cmd/aperture@latest
- Verify
aperture is on $PATH
To install manually:
go install github.com/lightninglabs/aperture/cmd/aperture@latest
Or build from source:
git clone https://github.com/lightninglabs/aperture.git
cd aperture
make install
Setup
skills/aperture/scripts/setup.sh
This generates ~/.aperture/aperture.yaml from the config template with
sensible defaults. The setup script auto-detects the local lnd node paths.
Options:
setup.sh --network testnet
setup.sh --lnd-host localhost:10009 \
--lnd-tls ~/.lnd/tls.cert \
--lnd-macdir ~/.lnd/data/chain/bitcoin/mainnet
setup.sh --port 8081
setup.sh --insecure
setup.sh --no-auth
Running Aperture
Start
skills/aperture/scripts/start.sh
Starts aperture as a background process reading ~/.aperture/aperture.yaml.
Options:
start.sh --foreground
start.sh --config /path/to
Stop
skills/aperture/scripts/stop.sh
Configuration
Config file: ~/.aperture/aperture.yaml
Invoice Macaroon Requirement
Aperture requires invoice.macaroon in the configured macdir to create
Lightning invoices for L402 challenges. This is not the same as
admin.macaroon. If the macaroon is missing, aperture will fail to start or
will return errors when clients request paid resources.
To bake an invoice macaroon with the macaroon-bakery skill:
skills/macaroon-bakery/scripts/bake.sh --role invoice-only \
--save-to ~/.lnd/data/chain/bitcoin/mainnet/invoice.macaroon
The setup.sh script will warn you if invoice.macaroon is not found at the
expected path.
Minimal Agent Configuration
This is the minimal config for an agent hosting paid endpoints with a local
lnd node:
listenaddr: "localhost:8081"
insecure: true
debuglevel: "info"
dbbackend: "sqlite"
sqlite:
dbfile: "~/.aperture/aperture.db"
authenticator:
network: "mainnet"
lndhost: "localhost:10009"
tlspath: "~/.lnd/tls.cert"
macdir: "~/.lnd/data/chain/bitcoin/mainnet"
services:
- name: "my-api"
hostregexp: ".*"
pathregexp: "^/api/.*$"
address: "127.0.0.1:8080"
protocol: http
price: 100
Service Configuration
Each service entry defines a backend to protect:
services:
- name: "service-name"
hostregexp: "^api.example.com$"
pathregexp: "^/paid/.*$"
address: "127.0.0.1:8080"
protocol: http
price: 100
capabilities: "read,write"
timeout: 31557600
authwhitelistpaths:
- "^/health$"
- "^/public/.*$"
ratelimits:
- pathregexp: "^/api/query.*$"
requests: 10
per: 1s
burst: 20
Authentication Backends
Direct LND Connection
authenticator:
network: "mainnet"
lndhost: "localhost:10009"
tlspath: "~/.lnd/tls.cert"
macdir: "~/.lnd/data/chain/bitcoin/mainnet"
Lightning Node Connect (LNC)
authenticator:
network: "mainnet"
passphrase: "your-pairing-phrase"
mailboxaddress: "mailbox.terminal.lightning.today:443"
Disable Authentication
authenticator:
disable: true
Database Backends
SQLite (recommended for agents):
dbbackend: "sqlite"
sqlite:
dbfile: "~/.aperture/aperture.db"
PostgreSQL:
dbbackend: "postgres"
postgres:
host: "localhost"
port: 5432
user: "aperture"
password: "secret"
dbname: "aperture"
TLS Configuration
autocert: true
servername: "api.example.com"
insecure: true
If neither is set, Aperture generates self-signed certs in ~/.aperture/.
Dynamic Pricing
Connect to a gRPC price server instead of static prices:
services:
- name: "my-api"
dynamicprice:
enabled: true
grpcaddress: "127.0.0.1:10010"
insecure: false
tlscertpath: "/path/to/pricer/tls.cert"
Hosting Paid Content for Agents
A common pattern is hosting information that other agents pay to access:
mkdir -p /tmp/paid-content
echo '{"data": "valuable information"}' > /tmp/paid-content/info.json
cd /tmp/paid-content && python3 -m http.server 8080 &
skills/aperture/scripts/setup.sh --insecure --port 8081
skills/aperture/scripts/start.sh
lnget --max-cost 100 https://localhost:8081/api/info.json
Integration with lnget and lnd
With all three components running:
skills/lnd/scripts/lncli.sh getinfo
skills/aperture/scripts/start.sh
lnget --max-cost 1000 https://localhost:8081/api/data
lnget tokens list
File Locations
| Path | Purpose |
|---|
~/.aperture/aperture.yaml | Configuration file |
~/.aperture/aperture.db | SQLite database |
~/.aperture/tls.cert | TLS certificate |
~/.aperture/tls.key | TLS private key |
~/.aperture/aperture.log | Log file |
Troubleshooting
Port already in use
Change listenaddr in config to a different port, or use setup.sh --port.
LND connection refused
Verify lnd is running and wallet is unlocked. Check lndhost, tlspath, and
macdir in the config point to the correct lnd instance.
No 402 challenge returned
Check that the request path matches a service's pathregexp and is not in
authwhitelistpaths. Verify authenticator.disable is not true.
Token validation fails
The client must present the exact macaroon from the challenge with the correct
preimage. Verify the preimage matches the payment hash.