Setup GuideSelf-Hosted (DIY)
Self-Hosted (DIY)
Want to run your own Lightning Address on your domain? This guide walks you through setting up a self-hosted LNURL-pay server.
Requirements
- A domain you control
- A web server (or serverless platform)
- A Lightning node or custodial account to receive payments
Basic Implementation
Your server needs to handle two endpoints:
1. The Well-Known Endpoint
example.sh
Shell
GET https://yourdomain.com/.well-known/lnurlp/{username}Return:
example.json
JSON
{ "callback": "https://yourdomain.com/lnurlp/{username}/callback", "minSendable": 1000, "maxSendable": 100000000000, "metadata": "[[\"text/plain\",\"Pay {username}@yourdomain.com\"]]", "tag": "payRequest"}2. The Callback Endpoint
example.sh
Shell
GET https://yourdomain.com/lnurlp/{username}/callback?amount={msats}When called, generate a Lightning invoice for the requested amount and return:
example.json
JSON
{ "pr": "lnbc...", "routes": []}Using LNbits
LNbits provides a ready-made LNURL-pay extension:
- Install LNbits on your server
- Enable the LNURLp extension
- Create a pay link for each user
- Point your
.well-known/lnurlpto LNbits
Using BTCPay Server
BTCPay Server supports Lightning Address natively:
- Set up BTCPay Server with Lightning
- Enable LNURL in store settings
- Configure your domain's
.well-knownto point to BTCPay
Proxy Setup
If you just need to redirect to another provider, create a simple proxy:
example.js
JavaScript
// Example: Cloudflare Workerexport default { async fetch(request) { const url = new URL(request.url); const username = url.pathname.split('/').pop(); // Proxy to your actual provider const upstream = `https://provider.com/.well-known/lnurlp/${username}`; return fetch(upstream); }}Security Considerations
- Always use HTTPS
- Validate usernames to prevent injection
- Rate limit requests
- Consider authentication for invoice generation
Testing
Use these tools to verify your setup:
- lnurl.fiatjaf.com — LNURL decoder and tester
- Any LNURL-compatible wallet — try sending yourself some sats