Merge pull request #861 from shocknet/mac-install
script enhancements with Mac install
This commit is contained in:
commit
dbda111255
17 changed files with 853 additions and 372 deletions
6
.github/workflows/test.yaml
vendored
6
.github/workflows/test.yaml
vendored
|
|
@ -1,5 +1,9 @@
|
||||||
name: Docker Compose Actions Workflow
|
name: Docker Compose Actions Workflow
|
||||||
on: push
|
on:
|
||||||
|
push:
|
||||||
|
paths-ignore:
|
||||||
|
- 'scripts/**'
|
||||||
|
- 'README.md'
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
|
||||||
499
README.md
499
README.md
|
|
@ -1,166 +1,333 @@
|
||||||
# Lightning.Pub
|
# Lightning.Pub
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
[](http://makeapullrequest.com)
|
[](http://makeapullrequest.com)
|
||||||
[](https://t.me/ShockBTC)
|
[](https://t.me/ShockBTC)
|
||||||

|

|
||||||
|
|
||||||
### Don't just run a Lightning Node, run a Lightning Pub.
|
### Don't just run a Lightning Node, run a Lightning Pub.
|
||||||
|
|
||||||
"Pub" is a [Nostr](https://nostr.info)-native account system designed to make running Lightning infrastructure for your friends/family/customers easier than previously thought possible.
|
"Pub" is a [Nostr](https://nostr.info)-native account system designed to make running Lightning infrastructure for your friends/family/customers easier than previously thought possible.
|
||||||
|
|
||||||
Lightning payments open the door to a new internet, but because of UX challenges with sovereignty we've seen a much slower uptake than we should for something so amazing.
|
Lightning payments open the door to a new internet, but because of UX challenges with sovereignty we've seen a much slower uptake than we should for something so amazing.
|
||||||
|
|
||||||
It may come as a surprise that the biggest hurdle to more adoption via Family and SMB Lightning nodes hasn't been with Bitcoin/Lightning node management itself, as we've seen that liquidity is easily automated, but rather the legacy baggage of traditional Client-Server web infrastructure. Things like IP4, Reverse Proxies, DNS, Firewalls and SSL certificates, all require a personal configuration that is a hurdle for most.
|
It may come as a surprise that the biggest hurdle to more adoption via Family and SMB Lightning nodes hasn't been with Bitcoin/Lightning node management itself, as we've seen that liquidity is easily automated, but rather the legacy baggage of traditional Client-Server web infrastructure. Things like IP4, Reverse Proxies, DNS, Firewalls and SSL certificates, all require a personal configuration that is a hurdle for most.
|
||||||
|
|
||||||
Tor as a workaround has proven too slow and unreliable, and a dead-end for clearnet-web usecases. Mobile node are easy but channels for every device is expensive and unscalable, and the UX that suffers from the limitations of the node not being an always-online server.
|
Tor as a workaround has proven too slow and unreliable, and a dead-end for clearnet-web usecases.
|
||||||
|
|
||||||
Pub solves these challenges with a P2P-like design that is also web-friendly, by implementing a full RPC that is Nostr-native. Being Nostr-native eliminates the complexity of configuring your node like a server by using commodity Nostr relays. These relays, unlike LNURL proxies, are trustless by nature of Nostr's own encryption spec (NIP44).
|
Mobile nodes are easy to use for spending, but channels for every device is expensive and unscalable. UX suffers from the limitations of the node not being an always-online server, which also makes them largely useless for merchants and routing services that earn revenue while you sleep.
|
||||||
|
|
||||||
Additionally, support for optional services are integrated into Pub for operators seeking backward compatibility with legacy LNURLs and Lightning Addresses.
|
Pub solves these challenges with a P2P-like design that is also web-friendly, by implementing a full RPC that is Nostr-native. Being Nostr-native eliminates the complexity of configuring your node like a server by using commodity Nostr relays. These relays, unlike LNURL proxies, are trustless by nature of Nostr's own encryption spec (NIP44).
|
||||||
|
|
||||||
By solving the networking and programability hurdles, Pub provides Lightning with a 3rd Layer that enables node-runners, Busineses, and Uncle Jims to more easily bring their personal network into Bitcoin's permissionless economy. In doing so, Pub runners can keep the Lightning Network decentralized, with custodial scaling that is free of fiat rails, large banks, and other forms of high-time-preference shitcoinery.
|
Additionally, support for optional services are integrated into Pub for operators seeking backward compatibility with legacy LNURLs and Lightning Addresses.
|
||||||
|
|
||||||
## Table of Contents
|
By solving the networking and programability hurdles, Pub provides Lightning with a 3rd Layer that enables node-runners, Busineses, and Uncle Jims to more easily bring their personal network into Bitcoin's permissionless economy. In doing so, Pub runners can keep the Lightning Network decentralized, with custodial scaling that is free of fiat rails, large banks, and other forms of high-time-preference shitcoinery.
|
||||||
- [Features](#features)
|
|
||||||
- [Planned Features](#planned-features)
|
## Table of Contents
|
||||||
- [Installation](#installation)
|
- [Features](#features)
|
||||||
- [One-Line Deployment](#one-line-deployment)
|
- [Planned Features](#planned-features)
|
||||||
- [Docker Installation](#docker-installation)
|
- [Installation](#installation)
|
||||||
- [Manual CLI Installation](#manual-cli-installation)
|
- [One-Line Deployment](#one-line-deployment)
|
||||||
- [Usage Notes](#usage-notes)
|
- [Docker Installation](#docker-installation)
|
||||||
- [Misc](#support-development)
|
- [Manual CLI Installation](#manual-cli-installation)
|
||||||
|
- [Usage Notes](#usage-notes)
|
||||||
## Features
|
- [Connecting to ShockWallet](#connecting-to-shockwallet)
|
||||||
|
- [Lightning Address](#lightning-address)
|
||||||
- Wrapper for [`LND`](https://github.com/lightningnetwork/lnd/releases) that can serve accounts over LNURL and NOSTR
|
- [Advanced Configuration](#advanced-configuration)
|
||||||
- A growing number of [methods](https://github.com/shocknet/Lightning.Pub/blob/master/proto/autogenerated/client.md)
|
- [Custom Nostr Relay](#custom-nostr-relay)
|
||||||
- Automated Channels
|
- [Bootstrap Liquidity Provider](#bootstrap-liquidity-provider)
|
||||||
- Receives quotes from multiple LSPs including Zeus, Voltage, and Flashsats
|
- [Custom Lightning Address Domain](#custom-lightning-address-domain)
|
||||||
- Bootstrap Peering
|
- [Support Development](#support-development)
|
||||||
- A pub node may trust another pub node until it can afford a channel
|
|
||||||
- Accounting SubLayers for Application Pools and Users
|
## Features
|
||||||
- A fee regime allows applications owners to monetize users, or node operators to host distinctly monetized applications.
|
|
||||||
|
- **Zero Network Configuration Required** - No port forwarding, Tor setup, firewall rules, or DNS configuration needed! Pub uses Nostr relays for all communication, making it perfect for users who want sovereignty without networking complexity.
|
||||||

|
- Wrapper for [`LND`](https://github.com/lightningnetwork/lnd/releases) that can serve accounts over LNURL and NOSTR
|
||||||
|
- A growing number of [methods](https://github.com/shocknet/Lightning.Pub/blob/master/proto/autogenerated/client.md)
|
||||||
- Connecting via ShockWallet is as easy as pasting an nprofile
|
- Automated Channels
|
||||||
- Or use a link to share your nprofile with friends and family
|
- Receives quotes from multiple LSPs including Zeus, Voltage, and Flashsats
|
||||||
|
- Bootstrap Peering
|
||||||
<img src="https://cdn.shockwallet.app/add_src_sm.png" height="20%" alt="Connect Wallet"> <img src="https://cdn.shockwallet.app/src_invite_sm.png" height="20%" alt="Invite Guests">
|
- A pub node may trust another pub node until it can afford a channel
|
||||||
|
- Can be disabled via environment variable for full sovereignty
|
||||||
## Planned Features
|
- Accounting SubLayers for Application Pools and Users
|
||||||
|
- A fee regime allows applications owners to monetize users, or node operators to host distinctly monetized applications.
|
||||||
- [x] A management dashboard is actively being integrated into [ShockWallet](https://github.com/shocknet/wallet2)
|
- **Complete Lightning Solution** - No additional LN node or Bitcoin full node required (uses Neutrino)
|
||||||
- [x] Nostr native [CLINK](https://clinkme.dev) "offers"
|
|
||||||
- [x] Encrypted Push Notifications
|

|
||||||
- [ ] P2P "LSP" coordination for channel batching over Nostr
|
|
||||||
- [ ] Swap integration
|
- Connecting via ShockWallet is as easy as pasting an nprofile
|
||||||
- [ ] High-Availabilty / Clustering
|
- Or use a link to share your nprofile with friends and family
|
||||||
|
|
||||||
Dashboard Wireframe:
|
<img src="https://cdn.shockwallet.app/add_source2.png" height="20%" alt="Connect Wallet"> <img src="https://cdn.shockwallet.app/invites2.png" height="20%" alt="Invite Guests">
|
||||||
|
|
||||||
<img src="https://shockwallet.b-cdn.net/pub_home_ss.png" alt="Pub Dashboard" width="240">
|
## Planned Features
|
||||||
|
|
||||||
## Installation
|
- [x] A management dashboard is actively being integrated into [ShockWallet](https://github.com/shocknet/wallet2)
|
||||||
|
- [x] Nostr native [CLINK](https://clinkme.dev) "offers"
|
||||||
### One-Line Deployment
|
- [x] Encrypted Push Notifications
|
||||||
|
- [_] Swap integration (in progress)
|
||||||
Paste one-line and have a Pub node in under 2 minutes. It uses neutrino so you can run it on a $5 VPS or old laptop.
|
- [ ] P2P "LSP" coordination for channel batching over Nostr
|
||||||
|
- [ ] High-Availabilty / Clustering
|
||||||
This method installs all dependencies and creates user-level systemd services.
|
|
||||||
|
Dashboard Wireframe:
|
||||||
**Platform Support:**
|
|
||||||
- ✅ **Debian/Ubuntu**: Fully tested and supported
|
<img src="https://shockwallet.b-cdn.net/pub_home_ss.png" alt="Pub Dashboard" width="240">
|
||||||
- ⚠️ **Arch/Fedora**: Should work but untested - please report issues
|
|
||||||
- 🚧 **macOS**: Basic support stubbed in but completely untested - help wanted
|
## Installation
|
||||||
|
|
||||||
To start, run the following command:
|
### One-Line Deployment
|
||||||
|
|
||||||
```bash
|
Paste one-line and have a Pub node in under 2 minutes. It uses neutrino so you can run it on a $5 VPS or old laptop.
|
||||||
wget -qO- https://deploy.lightning.pub | bash
|
|
||||||
```
|
This method installs all dependencies and creates user-level services (systemd on Linux, launchd on macOS).
|
||||||
|
|
||||||
It should look like this in a minute or so
|
**Platform Support:**
|
||||||
|
- ✅ **Debian/Ubuntu**: Fully tested and supported
|
||||||

|
- ✅ **Arch/Fedora**: Fully tested and supported
|
||||||
|
- ✅ **macOS**: Fully supported with launchd service management
|
||||||
**Note:** The installation is now confined to user-space, meaning:
|
|
||||||
- No sudo required for installation
|
> [!IMPORTANT]
|
||||||
- All data stored in `$HOME/lightning_pub/`
|
> **System Requirements:**
|
||||||
- Logs available at `$HOME/lightning_pub/install.log`
|
> - **RAM**: Minimum 2GB burstable in headless containers or VPS. 4+GB recommended for full Linux Desktop OS.
|
||||||
|
> - **Storage**: 20GB of space for compact blocks.
|
||||||
**⚠️ Migration from Previous Versions:**
|
> - **Network**: No port forwarding, Tor, or firewall configuration needed! Pub uses Nostr relays for communication to eliminate traditional server networking requirements.
|
||||||
Previous system-wide installations (as of 8.27.2025) need some manual intervention:
|
|
||||||
1. Stop existing services: `sudo systemctl stop lnd lightning_pub`
|
> [!TIP]
|
||||||
2. Disable services: `sudo systemctl disable lnd lightning_pub`
|
> **Bundled Node**: The Lightning.Pub install script provides a complete Lightning solution. You do NOT need to a full Bitcoin or other node, perfect small devices like Raspberry Pi.
|
||||||
3. Remove old systemd units: `sudo rm /etc/systemd/system/lnd.service /etc/systemd/system/lightning_pub.service`
|
|
||||||
4. Reload systemd: `sudo systemctl daemon-reload`
|
To start, run the following command:
|
||||||
5. Run the new installer: `wget -qO- https://deploy.lightning.pub | bash`
|
|
||||||
|
**Linux:**
|
||||||
Please report any issues to the [issue tracker](https://github.com/shocknet/Lightning.Pub/issues).
|
```bash
|
||||||
|
wget -qO- https://deploy.lightning.pub | bash
|
||||||
#### Automatic updates
|
```
|
||||||
|
|
||||||
These are controversial, so we don't include them. You can however add a line to your crontab to re-run the installer on your time preference and it will gracefully handle updating:
|
**macOS:**
|
||||||
|
```bash
|
||||||
```bash
|
curl -fsSL https://deploy.lightning.pub | bash
|
||||||
# Add to user's crontab (crontab -e) - runs weekly on Sunday at 2 AM
|
```
|
||||||
0 2 * * 0 wget -qO- https://deploy.lightning.pub | bash
|
|
||||||
```
|
It should look like this in a minute or so
|
||||||
|
|
||||||
**Note:** The installer will only restart services if version checks deem necessary.
|

|
||||||
|
|
||||||
### Docker Installation
|
**Note:** The installation is now confined to user-space, meaning:
|
||||||
|
- No sudo required for installation
|
||||||
See the [Docker Installation Guide](DOCKER.md).
|
- All data stored in `$HOME/lightning_pub/`
|
||||||
|
- **Linux**: Services managed via systemd (user-level)
|
||||||
### Manual CLI Installation
|
- **macOS**: Services managed via launchd with convenient aliases
|
||||||
|
|
||||||
1. Run [LND](https://github.com/lightningnetwork/lnd/releases) if you aren't already:
|
**After Installation:**
|
||||||
|
- The installer will display an admin connection string (nprofile and secret separated by a colon) and a **terminal QR code** for easy mobile setup
|
||||||
```ssh
|
- The QR code is displayed directly in your terminal - simply scan it with ShockWallet's node connetion flows
|
||||||
./lnd --bitcoin.active --bitcoin.mainnet --bitcoin.node=neutrino --neutrino.addpeer=neutrino.shock.network --feeurl=https://nodes.lightning.computer/fees/v1/btc-fee-estimates.json
|
- You can also copy/paste the connection string into ShockWallet if you prefer
|
||||||
```
|
- Connection info is also available via web browser on Start9 and Umbrel appliances (releases forthcoming)
|
||||||
|
|
||||||
2. Download and Install Lightning.Pub:
|
**⚠️ Migration from Previous Versions:**
|
||||||
|
Previous system-wide installations (as of 8.27.2025) need some manual intervention:
|
||||||
```ssh
|
1. Stop existing services: `sudo systemctl stop lnd lightning_pub`
|
||||||
git clone https://github.com/shocknet/Lightning.Pub && cd Lightning.Pub && npm i
|
2. Disable services: `sudo systemctl disable lnd lightning_pub`
|
||||||
```
|
3. Remove old systemd units: `sudo rm /etc/systemd/system/lnd.service /etc/systemd/system/lightning_pub.service`
|
||||||
|
4. Reload systemd: `sudo systemctl daemon-reload`
|
||||||
3. Configure values in the env file:
|
5. Run the new installer: `wget -qO- https://deploy.lightning.pub | bash`
|
||||||
|
|
||||||
```ssh
|
Please report any issues to the [issue tracker](https://github.com/shocknet/Lightning.Pub/issues).
|
||||||
cp env.example .env && nano .env
|
|
||||||
```
|
#### Automatic updates
|
||||||
|
|
||||||
4. Start the service:
|
These are controversial, so we don't include them. You can however add a line to your crontab to re-run the installer on your time preference and it will gracefully handle updating:
|
||||||
|
|
||||||
```ssh
|
**Linux:**
|
||||||
npm start
|
```bash
|
||||||
```
|
# Add to user's crontab (crontab -e) - runs weekly on Sunday at 2 AM
|
||||||
|
0 2 * * 0 wget -qO- https://deploy.lightning.pub | bash
|
||||||
## Usage Notes
|
```
|
||||||
|
|
||||||
Connect with ShockWallet ([wallet2](https://github.com/shocknet/wallet2)) using the wallet admin string that gets logged at startup. Simply copy/paste the string into the node connection screen.
|
**macOS:**
|
||||||
|
```bash
|
||||||
The nprofile of the node can also be used to send invitation links to guests via the web version of ShockWallet.
|
# Add to user's crontab (crontab -e) - runs weekly on Sunday at 2 AM
|
||||||
|
0 2 * * 0 curl -fsSL https://deploy.lightning.pub | bash
|
||||||
**Note that connecting with wallet will create an account on the node, it will not show or have access to the full LND balance. Allocating existing funds to the admin user will be added to the operator dashboard in a future release.**
|
```
|
||||||
|
|
||||||
Additional docs are WIP at [docs.shock.network](https://docs.shock.network)
|
**Note:** The installer will only restart services if version checks deem necessary.
|
||||||
|
|
||||||
## Support Development
|
#### Troubleshooting
|
||||||
|
|
||||||
> [!IMPORTANT]
|
If the installation fails or services don't start properly, use these commands to diagnose:
|
||||||
> ShockWallet and Lightning.Pub are free software. If you would like to see continued development, please show your [**support**](https://github.com/sponsors/shocknet) 😊
|
|
||||||
|
**Linux:**
|
||||||
<img src="https://www.gnu.org/graphics/agplv3-with-text-162x68.png" alt="License">
|
```bash
|
||||||
|
# Check service status
|
||||||
## Warning
|
systemctl --user status lnd
|
||||||
|
systemctl --user status lightning_pub
|
||||||
> [!WARNING]
|
|
||||||
> While this software has been used in a high-profile production environment for several years, it should still be considered bleeding edge. Special care has been taken to mitigate the risk of drainage attacks, which is a common risk to all Lightning APIs. An integrated Watchdog service will terminate spends if it detects a discrepancy between LND and the database, for this reason **IT IS NOT RECOMMENDED TO USE PUB ALONGSIDE OTHER ACCOUNT SYSTEMS** such as AlbyHub, LNBits, or BTCPay - this watchdog may however be disabled. While we give the utmost care and attention to security, **the internet is an adversarial environment and SECURITY/RELIABILITY ARE NOT GUARANTEED- USE AT YOUR OWN RISK**.
|
# View logs
|
||||||
|
journalctl --user-unit lnd -f
|
||||||
|
journalctl --user-unit lightning_pub -f
|
||||||
|
|
||||||
|
# Restart services if needed
|
||||||
|
systemctl --user restart lnd
|
||||||
|
systemctl --user restart lightning_pub
|
||||||
|
```
|
||||||
|
|
||||||
|
**macOS:**
|
||||||
|
After installation, run `source ~/.zshrc` (or `source ~/.bash_profile`) to enable the convenience aliases, or open a new terminal. Then use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check service status
|
||||||
|
lpub-status
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
lpub-log # Lightning.Pub logs
|
||||||
|
lnd-log # LND logs
|
||||||
|
|
||||||
|
# Control services
|
||||||
|
lpub-start # Start both services
|
||||||
|
lpub-stop # Stop both services
|
||||||
|
lpub-restart # Restart both services
|
||||||
|
```
|
||||||
|
|
||||||
|
**All Platforms:**
|
||||||
|
```bash
|
||||||
|
# Retrieve admin connection string (if installation completed but you need to find it again)
|
||||||
|
cat ~/lightning_pub/admin.connect
|
||||||
|
|
||||||
|
# Reset admin access (generates new admin.connect automatically)
|
||||||
|
rm ~/lightning_pub/admin.npub
|
||||||
|
sleep 1 # Wait briefly for new admin.connect to re-generate
|
||||||
|
cat ~/lightning_pub/admin.connect
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Installation
|
||||||
|
|
||||||
|
See the [Docker Installation Guide](DOCKER.md).
|
||||||
|
|
||||||
|
### Manual CLI Installation
|
||||||
|
|
||||||
|
1. Run [LND](https://github.com/lightningnetwork/lnd/releases) if you aren't already:
|
||||||
|
|
||||||
|
```ssh
|
||||||
|
./lnd --bitcoin.active --bitcoin.mainnet --bitcoin.node=neutrino --neutrino.addpeer=neutrino.shock.network --feeurl=https://nodes.lightning.computer/fees/v1/btc-fee-estimates.json
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Download and Install Lightning.Pub:
|
||||||
|
|
||||||
|
```ssh
|
||||||
|
git clone https://github.com/shocknet/Lightning.Pub && cd Lightning.Pub && npm i
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Configure values in the env file:
|
||||||
|
|
||||||
|
```ssh
|
||||||
|
cp env.example .env && nano .env
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Start the service:
|
||||||
|
|
||||||
|
```ssh
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage Notes
|
||||||
|
|
||||||
|
### Connecting to ShockWallet
|
||||||
|
|
||||||
|
**For Administrators:**
|
||||||
|
1. After installation, you'll see an admin connection string (format: `nprofile1...:token`) and a **terminal QR code** containing the same admin connection string
|
||||||
|
2. **Option 1**: Scan the terminal QR code directly with ShockWallet's "Add Source" feature (mobile or web) to pair as administrator
|
||||||
|
3. **Option 2**: Copy/paste the connection string into ShockWallet's node connection screen
|
||||||
|
|
||||||
|
**For Guest Users:**
|
||||||
|
- The guest nprofile (without admin token) is stored in `$HOME/lightning_pub/app.nprofile`
|
||||||
|
- Share the nprofile string with guests directly, or use invitation links from the "Invite" page in ShockWallet
|
||||||
|
- Guests paste the nprofile string into ShockWallet's "Add Source" feature to connect
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Connecting with wallet will create an account on the node, it will not show or have access to the full LND balance. Allocating existing funds to the admin user will be added to the operator dashboard in a future release.
|
||||||
|
|
||||||
|
### Lightning Address
|
||||||
|
|
||||||
|
When you run your own Lightning Pub, obtaining a Lightning Address is fully automated in ShockWallet. The wallet automatically:
|
||||||
|
1. Takes the CLINK offer from your Pub
|
||||||
|
2. Enrolls it at a LNURL bridge (creates a `@shockwallet.app` address)
|
||||||
|
3. This makes the Lightning Address trustless when payers support CLINK as it uses Nostr for communication instead of trusting the bridge to serve the correct invoice.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> **CLINK Integration**: Your Pub's CLINK offers enable ShockWallet to connect to CLINK-compatible services, like [Stacker News](https://stacker.news), allowing you to send and receive payments without additional setup.
|
||||||
|
|
||||||
|
For custom Lightning Address domains, see the [Advanced Configuration](#advanced-configuration) section.
|
||||||
|
|
||||||
|
## Advanced Configuration
|
||||||
|
|
||||||
|
Copy `env.example` to `.env` and customize settings:
|
||||||
|
```bash
|
||||||
|
cp env.example .env
|
||||||
|
nano .env # or use your preferred editor
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> Environment variables set in `.env` will override any settings configured via the wizard or stored in the settings database table.
|
||||||
|
|
||||||
|
### Custom Nostr Relay
|
||||||
|
|
||||||
|
By default, Lightning.Pub uses the ShockNet relay. To use your own:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Single relay
|
||||||
|
NOSTR_RELAYS=wss://your-relay-url.com
|
||||||
|
|
||||||
|
# Multiple relays (space-separated)
|
||||||
|
NOSTR_RELAYS="wss://relay1.com wss://relay2.com wss://relay3.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
The wizard interface (coming soon for Start9/Umbrel) will make this graphical.
|
||||||
|
|
||||||
|
### Bootstrap Liquidity Provider
|
||||||
|
|
||||||
|
By default, Lightning.Pub uses a bootstrap liquidity provider that provides initial channel funding as a service credit until you can afford your own channels. Pub compares rates from top LSPs and automatically requests a channel when needed.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Disable for full sovereignty
|
||||||
|
DISABLE_LIQUIDITY_PROVIDER=true
|
||||||
|
|
||||||
|
# Or point to a different Pub instance
|
||||||
|
LIQUIDITY_PROVIDER_PUB=nprofile1...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Lightning Address Domain
|
||||||
|
|
||||||
|
By default, ShockWallet automatically enrolls your CLINK offer at `@shockwallet.app`. For custom domains, you have two options:
|
||||||
|
|
||||||
|
**Option 1: Run your own [Bridgelet](https://github.com/shocknet/bridgelet)**
|
||||||
|
|
||||||
|
A minimalist LNURL-P and Lightning Address bridge service that uses CLINK Offers. This gives you full control over your Lightning Address domain without trusting third-party bridges.
|
||||||
|
|
||||||
|
**Option 2: Enable LNURL directly on Pub**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Configure which LNURL bridge to suggest to wallets (default: https://shockwallet.app)
|
||||||
|
BRIDGE_URL=https://your-bridge.com
|
||||||
|
|
||||||
|
# Enable LNURL callbacks directly on Pub (requires SSL reverse proxy pointing to Pub's port)
|
||||||
|
SERVICE_URL=https://yourdomain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complete Reference
|
||||||
|
|
||||||
|
See `env.example` for complete documentation of all available settings.
|
||||||
|
|
||||||
|
For additional documentation, guides, and FAQs, visit [docs.shock.network](https://docs.shock.network) or contribute to the [docs repository](https://github.com/shocknet/docs).
|
||||||
|
|
||||||
|
## Support Development
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> ShockWallet and Lightning.Pub are free software. If you would like to see continued development, please show your [**support**](https://github.com/sponsors/shocknet) 😊
|
||||||
|
|
||||||
|
<img src="https://www.gnu.org/graphics/agplv3-with-text-162x68.png" alt="License">
|
||||||
|
|
||||||
|
## Warning
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> While this software has been used in a high-profile production environment for several years, it should still be considered bleeding edge. Special care has been taken to mitigate the risk of drainage attacks, which is a common risk to all Lightning APIs. An integrated Watchdog service will terminate spends if it detects a discrepancy between LND and the database, for this reason **IT IS NOT RECOMMENDED TO USE PUB ALONGSIDE OTHER ACCOUNT SYSTEMS** such as AlbyHub, LNBits, or BTCPay - this watchdog may however be disabled. While we give the utmost care and attention to security, **the internet is an adversarial environment and SECURITY/RELIABILITY ARE NOT GUARANTEED- USE AT YOUR OWN RISK**.
|
||||||
|
|
|
||||||
9
package-lock.json
generated
9
package-lock.json
generated
|
|
@ -36,6 +36,7 @@
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"nostr-tools": "^2.13.0",
|
"nostr-tools": "^2.13.0",
|
||||||
"pg": "^8.4.0",
|
"pg": "^8.4.0",
|
||||||
|
"qrcode-terminal": "^0.12.0",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"rxjs": "^7.5.5",
|
"rxjs": "^7.5.5",
|
||||||
|
|
@ -5730,6 +5731,14 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/qrcode-terminal": {
|
||||||
|
"version": "0.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz",
|
||||||
|
"integrity": "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==",
|
||||||
|
"bin": {
|
||||||
|
"qrcode-terminal": "bin/qrcode-terminal.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/qs": {
|
"node_modules/qs": {
|
||||||
"version": "6.13.0",
|
"version": "6.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"nostr-tools": "^2.13.0",
|
"nostr-tools": "^2.13.0",
|
||||||
"pg": "^8.4.0",
|
"pg": "^8.4.0",
|
||||||
|
"qrcode-terminal": "^0.12.0",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"rxjs": "^7.5.5",
|
"rxjs": "^7.5.5",
|
||||||
|
|
|
||||||
BIN
pub_logo.png
BIN
pub_logo.png
Binary file not shown.
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 26 KiB |
|
|
@ -1,11 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
check_homebrew() {
|
|
||||||
if ! command -v brew &> /dev/null; then
|
|
||||||
log "${PRIMARY_COLOR}Homebrew not found. Installing Homebrew...${RESET_COLOR}"
|
|
||||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" || {
|
|
||||||
log "${PRIMARY_COLOR}Failed to install Homebrew.${RESET_COLOR}"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
create_launchd_plist() {
|
|
||||||
create_plist() {
|
|
||||||
local plist_path=$1
|
|
||||||
local label=$2
|
|
||||||
local program_args=$3
|
|
||||||
local working_dir=$4
|
|
||||||
|
|
||||||
if [ -f "$plist_path" ]; then
|
|
||||||
log "${PRIMARY_COLOR}${label} already exists. Skipping creation.${RESET_COLOR}"
|
|
||||||
else
|
|
||||||
cat <<EOF > "$plist_path"
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>Label</key>
|
|
||||||
<string>${label}</string>
|
|
||||||
<key>ProgramArguments</key>
|
|
||||||
<array>
|
|
||||||
${program_args}
|
|
||||||
</array>
|
|
||||||
<key>WorkingDirectory</key>
|
|
||||||
<string>${working_dir}</string>
|
|
||||||
<key>RunAtLoad</key>
|
|
||||||
<true/>
|
|
||||||
<key>KeepAlive</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
USER_HOME=$(eval echo ~$(whoami))
|
|
||||||
NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${USER_HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
|
|
||||||
LAUNCH_AGENTS_DIR="${USER_HOME}/Library/LaunchAgents"
|
|
||||||
|
|
||||||
create_plist "${LAUNCH_AGENTS_DIR}/local.lnd.plist" "local.lnd" "<string>${USER_HOME}/lnd/lnd</string>" ""
|
|
||||||
create_plist "${LAUNCH_AGENTS_DIR}/local.lightning_pub.plist" "local.lightning_pub" "<string>/bin/bash</string><string>-c</string><string>source ${NVM_DIR}/nvm.sh && npm start</string>" "${USER_HOME}/lightning_pub"
|
|
||||||
|
|
||||||
log "${PRIMARY_COLOR}Created launchd plists. Please load them using launchctl.${RESET_COLOR}"
|
|
||||||
}
|
|
||||||
|
|
@ -4,6 +4,11 @@ get_log_info() {
|
||||||
USER_HOME=$HOME
|
USER_HOME=$HOME
|
||||||
USER_NAME=$(whoami)
|
USER_NAME=$(whoami)
|
||||||
|
|
||||||
|
# Ensure node is in PATH for QR generation
|
||||||
|
if [ "$OS" = "Mac" ]; then
|
||||||
|
export PATH="$USER_HOME/node/bin:$PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
LOG_DIR="$INSTALL_DIR/logs"
|
LOG_DIR="$INSTALL_DIR/logs"
|
||||||
DATA_DIR="$INSTALL_DIR/"
|
DATA_DIR="$INSTALL_DIR/"
|
||||||
START_TIME=$(date +%s)
|
START_TIME=$(date +%s)
|
||||||
|
|
@ -16,7 +21,11 @@ get_log_info() {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Get the modification time of the timestamp file as a UNIX timestamp
|
# Get the modification time of the timestamp file as a UNIX timestamp
|
||||||
ref_timestamp=$(stat -c %Y "$TIMESTAMP_FILE")
|
if [ "$OS" = "Mac" ]; then
|
||||||
|
ref_timestamp=$(stat -f %m "$TIMESTAMP_FILE")
|
||||||
|
else
|
||||||
|
ref_timestamp=$(stat -c %Y "$TIMESTAMP_FILE")
|
||||||
|
fi
|
||||||
|
|
||||||
# Wait for a new unlocker log file to be created
|
# Wait for a new unlocker log file to be created
|
||||||
while [ $(($(date +%s) - START_TIME)) -lt $MAX_WAIT_TIME ]; do
|
while [ $(($(date +%s) - START_TIME)) -lt $MAX_WAIT_TIME ]; do
|
||||||
|
|
@ -24,7 +33,11 @@ get_log_info() {
|
||||||
# Loop through log files and check their modification time
|
# Loop through log files and check their modification time
|
||||||
for log_file in "${LOG_DIR}/components/"unlocker_*.log; do
|
for log_file in "${LOG_DIR}/components/"unlocker_*.log; do
|
||||||
if [ -f "$log_file" ]; then
|
if [ -f "$log_file" ]; then
|
||||||
file_timestamp=$(stat -c %Y "$log_file")
|
if [ "$OS" = "Mac" ]; then
|
||||||
|
file_timestamp=$(stat -f %m "$log_file")
|
||||||
|
else
|
||||||
|
file_timestamp=$(stat -c %Y "$log_file")
|
||||||
|
fi
|
||||||
if [ "$file_timestamp" -gt "$ref_timestamp" ]; then
|
if [ "$file_timestamp" -gt "$ref_timestamp" ]; then
|
||||||
latest_unlocker_log="$log_file"
|
latest_unlocker_log="$log_file"
|
||||||
break # Found the newest log file
|
break # Found the newest log file
|
||||||
|
|
@ -108,12 +121,18 @@ get_log_info() {
|
||||||
log "A node admin has not yet enrolled via Nostr."
|
log "A node admin has not yet enrolled via Nostr."
|
||||||
log "Paste this string into ShockWallet as a node source to connect as administrator:"
|
log "Paste this string into ShockWallet as a node source to connect as administrator:"
|
||||||
log "${SECONDARY_COLOR}$admin_connect${RESET_COLOR}"
|
log "${SECONDARY_COLOR}$admin_connect${RESET_COLOR}"
|
||||||
|
echo ""
|
||||||
|
log "Or scan this QR code with ShockWallet:"
|
||||||
|
node "$INSTALL_DIR/scripts/qr_generator.js" "$admin_connect" 2>/dev/null || log "QR code generation unavailable"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
elif [ -f "$DATA_DIR/app.nprofile" ]; then
|
elif [ -f "$DATA_DIR/app.nprofile" ]; then
|
||||||
app_nprofile=$(cat "$DATA_DIR/app.nprofile")
|
app_nprofile=$(cat "$DATA_DIR/app.nprofile")
|
||||||
log "Node is already set up. Use this nprofile to invite guest users:"
|
log "${SECONDARY_COLOR}Lightning.Pub${RESET_COLOR} is already set up. Use this nprofile to invite guest users:"
|
||||||
log "${SECONDARY_COLOR}$app_nprofile${RESET_COLOR}"
|
log "${SECONDARY_COLOR}$app_nprofile${RESET_COLOR}"
|
||||||
|
echo ""
|
||||||
|
log "Or scan this QR code with ShockWallet:"
|
||||||
|
node "$INSTALL_DIR/scripts/qr_generator.js" "$app_nprofile" 2>/dev/null || log "QR code generation unavailable"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
sleep $WAIT_INTERVAL
|
sleep $WAIT_INTERVAL
|
||||||
|
|
|
||||||
182
scripts/handle_macos.sh
Normal file
182
scripts/handle_macos.sh
Normal file
|
|
@ -0,0 +1,182 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# macOS-specific installation handler
|
||||||
|
# Called from install.sh when OS=Mac
|
||||||
|
|
||||||
|
handle_macos() {
|
||||||
|
local REPO_URL="$1"
|
||||||
|
|
||||||
|
export INSTALL_DIR="$HOME/lightning_pub"
|
||||||
|
export LAUNCH_AGENTS_DIR="$HOME/Library/LaunchAgents"
|
||||||
|
mkdir -p "$LAUNCH_AGENTS_DIR"
|
||||||
|
|
||||||
|
# Install LND
|
||||||
|
log "${PRIMARY_COLOR}Installing${RESET_COLOR} ${SECONDARY_COLOR}LND${RESET_COLOR}..."
|
||||||
|
LND_STATUS_FILE=$(mktemp)
|
||||||
|
install_lnd "$LND_STATUS_FILE"
|
||||||
|
install_result=$?
|
||||||
|
|
||||||
|
if [ $install_result -ne 0 ]; then
|
||||||
|
rm -f "$LND_STATUS_FILE"
|
||||||
|
log_error "LND installation failed" $install_result
|
||||||
|
fi
|
||||||
|
|
||||||
|
lnd_status=$(cat "$LND_STATUS_FILE")
|
||||||
|
rm -f "$LND_STATUS_FILE"
|
||||||
|
|
||||||
|
# Install Node.js
|
||||||
|
install_nodejs || log_error "Failed to install Node.js" 1
|
||||||
|
|
||||||
|
# Install Lightning.Pub
|
||||||
|
install_lightning_pub "$REPO_URL" || pub_install_status=$?
|
||||||
|
|
||||||
|
case ${pub_install_status:-0} in
|
||||||
|
0)
|
||||||
|
log "Lightning.Pub fresh installation completed successfully."
|
||||||
|
pub_upgrade_status=0
|
||||||
|
;;
|
||||||
|
100)
|
||||||
|
log "Lightning.Pub upgrade completed successfully."
|
||||||
|
pub_upgrade_status=100
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
pub_upgrade_status=2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log_error "Lightning.Pub installation failed with exit code $pub_install_status" "$pub_install_status"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Start services using launchd
|
||||||
|
if [ "$pub_upgrade_status" -eq 0 ] || [ "$pub_upgrade_status" -eq 100 ]; then
|
||||||
|
log "Starting services..."
|
||||||
|
if [ "$lnd_status" = "0" ] || [ "$lnd_status" = "1" ]; then
|
||||||
|
log "Note: LND may take several minutes to sync block headers depending on network conditions."
|
||||||
|
fi
|
||||||
|
|
||||||
|
create_launchd_plists
|
||||||
|
|
||||||
|
# Start/restart services
|
||||||
|
for svc in local.lnd local.lightning_pub; do
|
||||||
|
local plist="$LAUNCH_AGENTS_DIR/${svc}.plist"
|
||||||
|
if launchctl list 2>/dev/null | grep -q "$svc"; then
|
||||||
|
launchctl unload "$plist" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
launchctl load "$plist"
|
||||||
|
done
|
||||||
|
log "${SECONDARY_COLOR}LND${RESET_COLOR} and ${SECONDARY_COLOR}Lightning.Pub${RESET_COLOR} services started."
|
||||||
|
|
||||||
|
TIMESTAMP_FILE=$(mktemp)
|
||||||
|
export TIMESTAMP_FILE
|
||||||
|
get_log_info || log_error "Failed to get log info" 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Installation process completed successfully"
|
||||||
|
log "Run 'source ~/.zshrc' or open a new terminal to use lpub-status, lpub-log, etc."
|
||||||
|
|
||||||
|
if [ -d "$HOME/lightning_pub" ]; then
|
||||||
|
mv "$TMP_LOG_FILE" "$HOME/lightning_pub/install.log"
|
||||||
|
chmod 600 "$HOME/lightning_pub/install.log"
|
||||||
|
else
|
||||||
|
rm -f "$TMP_LOG_FILE"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
create_launchd_plists() {
|
||||||
|
local NVM_DIR="$HOME/.nvm"
|
||||||
|
local NODE_BIN="$HOME/node/bin"
|
||||||
|
|
||||||
|
# Create wrapper scripts so macOS shows proper names in Background Items
|
||||||
|
mkdir -p "$HOME/.local/bin"
|
||||||
|
|
||||||
|
# LND wrapper
|
||||||
|
cat > "$HOME/.local/bin/LND" <<EOF
|
||||||
|
#!/bin/bash
|
||||||
|
exec "$HOME/lnd/lnd" "\$@"
|
||||||
|
EOF
|
||||||
|
chmod +x "$HOME/.local/bin/LND"
|
||||||
|
|
||||||
|
# Lightning.Pub wrapper
|
||||||
|
cat > "$HOME/.local/bin/Lightning.Pub" <<EOF
|
||||||
|
#!/bin/bash
|
||||||
|
export PATH="$NODE_BIN:\$PATH"
|
||||||
|
cd "$INSTALL_DIR"
|
||||||
|
exec "$NODE_BIN/npm" start
|
||||||
|
EOF
|
||||||
|
chmod +x "$HOME/.local/bin/Lightning.Pub"
|
||||||
|
|
||||||
|
# Add aliases to shell profile
|
||||||
|
local shell_profile="$HOME/.zshrc"
|
||||||
|
[ -f "$HOME/.bash_profile" ] && ! [ -f "$HOME/.zshrc" ] && shell_profile="$HOME/.bash_profile"
|
||||||
|
|
||||||
|
if ! grep -q 'lpub-start' "$shell_profile" 2>/dev/null; then
|
||||||
|
cat >> "$shell_profile" <<'ALIASES'
|
||||||
|
|
||||||
|
# Lightning.Pub service management
|
||||||
|
alias lpub-start='launchctl load ~/Library/LaunchAgents/local.lightning_pub.plist ~/Library/LaunchAgents/local.lnd.plist'
|
||||||
|
alias lpub-stop='launchctl unload ~/Library/LaunchAgents/local.lightning_pub.plist ~/Library/LaunchAgents/local.lnd.plist'
|
||||||
|
alias lpub-restart='lpub-stop; lpub-start'
|
||||||
|
alias lpub-log='tail -f ~/Library/Logs/Lightning.Pub/pub.log'
|
||||||
|
alias lnd-log='tail -f ~/Library/Logs/Lightning.Pub/lnd.log'
|
||||||
|
alias lpub-status='launchctl list | grep local.lightning_pub; launchctl list | grep local.lnd'
|
||||||
|
ALIASES
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create log directory
|
||||||
|
mkdir -p "$HOME/Library/Logs/Lightning.Pub"
|
||||||
|
|
||||||
|
# LND plist
|
||||||
|
if [ ! -f "$LAUNCH_AGENTS_DIR/local.lnd.plist" ]; then
|
||||||
|
cat > "$LAUNCH_AGENTS_DIR/local.lnd.plist" <<EOF
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>Label</key>
|
||||||
|
<string>local.lnd</string>
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>$HOME/.local/bin/LND</string>
|
||||||
|
</array>
|
||||||
|
<key>RunAtLoad</key>
|
||||||
|
<true/>
|
||||||
|
<key>KeepAlive</key>
|
||||||
|
<true/>
|
||||||
|
<key>StandardOutPath</key>
|
||||||
|
<string>$HOME/Library/Logs/Lightning.Pub/lnd.log</string>
|
||||||
|
<key>StandardErrorPath</key>
|
||||||
|
<string>$HOME/Library/Logs/Lightning.Pub/lnd.log</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Lightning.Pub plist
|
||||||
|
if [ ! -f "$LAUNCH_AGENTS_DIR/local.lightning_pub.plist" ]; then
|
||||||
|
cat > "$LAUNCH_AGENTS_DIR/local.lightning_pub.plist" <<EOF
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>Label</key>
|
||||||
|
<string>local.lightning_pub</string>
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>$HOME/.local/bin/Lightning.Pub</string>
|
||||||
|
</array>
|
||||||
|
<key>WorkingDirectory</key>
|
||||||
|
<string>$INSTALL_DIR</string>
|
||||||
|
<key>RunAtLoad</key>
|
||||||
|
<true/>
|
||||||
|
<key>KeepAlive</key>
|
||||||
|
<true/>
|
||||||
|
<key>StandardOutPath</key>
|
||||||
|
<string>$HOME/Library/Logs/Lightning.Pub/pub.log</string>
|
||||||
|
<key>StandardErrorPath</key>
|
||||||
|
<string>$HOME/Library/Logs/Lightning.Pub/pub.log</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -6,12 +6,13 @@ TMP_LOG_FILE=$(mktemp)
|
||||||
|
|
||||||
log() {
|
log() {
|
||||||
local message="$(date '+%Y-%m-%d %H:%M:%S') $1"
|
local message="$(date '+%Y-%m-%d %H:%M:%S') $1"
|
||||||
echo -e "$message"
|
# Use printf for cross-platform compatibility (macOS echo -e issues)
|
||||||
# Write to the temporary log file.
|
printf "%b\n" "$message"
|
||||||
echo -e "$(echo "$message" | sed 's/\\e\[[0-9;]*m//g')" >> "$TMP_LOG_FILE"
|
# Write to the temporary log file (strip colors)
|
||||||
|
echo "$message" | sed 's/\\e\[[0-9;]*m//g' >> "$TMP_LOG_FILE"
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPT_VERSION="0.2.2"
|
SCRIPT_VERSION="0.3.0"
|
||||||
REPO="shocknet/Lightning.Pub"
|
REPO="shocknet/Lightning.Pub"
|
||||||
BRANCH="master"
|
BRANCH="master"
|
||||||
|
|
||||||
|
|
@ -28,14 +29,121 @@ log_error() {
|
||||||
exit $2
|
exit $2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Detect OS early for bootstrap
|
||||||
|
OS="$(uname -s)"
|
||||||
|
case "$OS" in
|
||||||
|
Linux*) OS=Linux;;
|
||||||
|
Darwin*) OS=Mac;;
|
||||||
|
*) OS="UNKNOWN"
|
||||||
|
esac
|
||||||
|
|
||||||
|
detect_os_arch() {
|
||||||
|
# OS already detected above, but we need ARCH and systemctl check
|
||||||
|
ARCH="$(uname -m)"
|
||||||
|
case "$ARCH" in
|
||||||
|
x86_64) ARCH=amd64;;
|
||||||
|
arm64|aarch64|armv8*) ARCH=arm64;;
|
||||||
|
armv7*) ARCH=armv7;;
|
||||||
|
*) ARCH="UNKNOWN"
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ "$OS" = "Linux" ] && command -v systemctl &> /dev/null; then
|
||||||
|
SYSTEMCTL_AVAILABLE=true
|
||||||
|
else
|
||||||
|
SYSTEMCTL_AVAILABLE=false
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
PRIMARY_COLOR="\e[38;5;208m"
|
||||||
|
SECONDARY_COLOR="\e[38;5;165m"
|
||||||
|
RESET_COLOR="\e[0m"
|
||||||
|
|
||||||
|
check_deps() {
|
||||||
|
for cmd in grep stat tar; do
|
||||||
|
if ! command -v $cmd &> /dev/null; then
|
||||||
|
log "Missing system dependency: $cmd. Install $cmd via your package manager and retry."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check for wget or curl (one is required)
|
||||||
|
if ! command -v wget &> /dev/null && ! command -v curl &> /dev/null; then
|
||||||
|
log "Missing system dependency: wget or curl. Install via your package manager and retry."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v sha256sum &> /dev/null && ! command -v shasum &> /dev/null; then
|
||||||
|
log "Missing system dependency: sha256sum or shasum."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cross-platform sed in-place
|
||||||
|
sed_i() {
|
||||||
|
if [ "$OS" = "Mac" ]; then
|
||||||
|
sed -i '' "$@"
|
||||||
|
else
|
||||||
|
sed -i "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cross-platform mktemp with parent directory
|
||||||
|
mktemp_in() {
|
||||||
|
local parent="$1"
|
||||||
|
if [ "$OS" = "Mac" ]; then
|
||||||
|
mktemp -d "${parent}/tmp.XXXXXX"
|
||||||
|
else
|
||||||
|
mktemp -d -p "$parent"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Extract JSON value (cross-platform)
|
||||||
|
json_value() {
|
||||||
|
local key="$1"
|
||||||
|
if [ "$OS" = "Mac" ]; then
|
||||||
|
echo "$2" | grep "\"${key}\"" | awk -F'"' '{print $4; exit}'
|
||||||
|
else
|
||||||
|
echo "$2" | grep -oP "\"${key}\": \"\\K[^\"]+"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Download file (wget or curl)
|
||||||
|
download() {
|
||||||
|
local url="$1"
|
||||||
|
local dest="$2"
|
||||||
|
if [ "$OS" = "Mac" ]; then
|
||||||
|
curl -fsL "$url" -o "$dest"
|
||||||
|
else
|
||||||
|
wget -q "$url" -O "$dest"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Download to stdout (wget or curl)
|
||||||
|
download_stdout() {
|
||||||
|
local url="$1"
|
||||||
|
if [ "$OS" = "Mac" ]; then
|
||||||
|
curl -fsL "$url"
|
||||||
|
else
|
||||||
|
wget -qO- "$url"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get latest release tag from GitHub (via API)
|
||||||
|
get_latest_release_tag() {
|
||||||
|
local repo="$1"
|
||||||
|
local url="https://api.github.com/repos/${repo}/releases/latest"
|
||||||
|
local api_json=$(download_stdout "$url")
|
||||||
|
json_value "tag_name" "$api_json"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
modules=(
|
modules=(
|
||||||
"utils"
|
|
||||||
"ports"
|
"ports"
|
||||||
"install_lnd"
|
"install_lnd"
|
||||||
"install_nodejs"
|
"install_nodejs"
|
||||||
"install_lightning_pub"
|
"install_lightning_pub"
|
||||||
"start_services"
|
"start_services"
|
||||||
|
"handle_macos"
|
||||||
"extract_nprofile"
|
"extract_nprofile"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -65,7 +173,7 @@ SCRIPTS_URL="${BASE_URL}/scripts/"
|
||||||
TMP_DIR=$(mktemp -d)
|
TMP_DIR=$(mktemp -d)
|
||||||
|
|
||||||
for module in "${modules[@]}"; do
|
for module in "${modules[@]}"; do
|
||||||
wget -q "${SCRIPTS_URL}${module}.sh" -O "${TMP_DIR}/${module}.sh" || log_error "Failed to download ${module}.sh" 1
|
download "${SCRIPTS_URL}${module}.sh" "${TMP_DIR}/${module}.sh" || log_error "Failed to download ${module}.sh" 1
|
||||||
source "${TMP_DIR}/${module}.sh" || log_error "Failed to source ${module}.sh" 1
|
source "${TMP_DIR}/${module}.sh" || log_error "Failed to source ${module}.sh" 1
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
@ -91,26 +199,22 @@ log "Detected OS: $OS"
|
||||||
log "Detected ARCH: $ARCH"
|
log "Detected ARCH: $ARCH"
|
||||||
|
|
||||||
if [ "$OS" = "Mac" ]; then
|
if [ "$OS" = "Mac" ]; then
|
||||||
log_error "macOS is not currently supported by this install script. Please use a Linux-based system." 1
|
handle_macos "$REPO_URL"
|
||||||
else
|
else
|
||||||
# Explicit kickoff log for LND so the flow is clear in the install log
|
# Explicit kickoff log for LND so the flow is clear in the install log
|
||||||
log "${PRIMARY_COLOR}Installing${RESET_COLOR} ${SECONDARY_COLOR}LND${RESET_COLOR}..."
|
log "${PRIMARY_COLOR}Installing${RESET_COLOR} ${SECONDARY_COLOR}LND${RESET_COLOR}..."
|
||||||
lnd_output=$(install_lnd)
|
LND_STATUS_FILE=$(mktemp)
|
||||||
|
install_lnd "$LND_STATUS_FILE"
|
||||||
install_result=$?
|
install_result=$?
|
||||||
|
|
||||||
if [ $install_result -ne 0 ]; then
|
if [ $install_result -ne 0 ]; then
|
||||||
|
rm -f "$LND_STATUS_FILE"
|
||||||
log_error "LND installation failed" $install_result
|
log_error "LND installation failed" $install_result
|
||||||
fi
|
fi
|
||||||
|
|
||||||
lnd_status=$(echo "$lnd_output" | grep "LND_STATUS:" | cut -d':' -f2)
|
lnd_status=$(cat "$LND_STATUS_FILE")
|
||||||
|
rm -f "$LND_STATUS_FILE"
|
||||||
case $lnd_status in
|
|
||||||
0) log "LND fresh installation completed successfully." ;;
|
|
||||||
1) log "LND upgrade completed successfully." ;;
|
|
||||||
2) log "LND is already up-to-date. No action needed." ;;
|
|
||||||
*) log "WARNING: Unexpected status from install_lnd: $lnd_status" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
install_nodejs || log_error "Failed to install Node.js" 1
|
install_nodejs || log_error "Failed to install Node.js" 1
|
||||||
|
|
||||||
# Run install_lightning_pub and capture its exit code directly.
|
# Run install_lightning_pub and capture its exit code directly.
|
||||||
|
|
@ -127,7 +231,6 @@ else
|
||||||
pub_upgrade_status=100 # Indicates an upgrade, services should restart
|
pub_upgrade_status=100 # Indicates an upgrade, services should restart
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
log "Lightning.Pub is already up-to-date. No action needed."
|
|
||||||
pub_upgrade_status=2 # Special status to skip service restart
|
pub_upgrade_status=2 # Special status to skip service restart
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ install_lightning_pub() {
|
||||||
USER_HOME=$HOME
|
USER_HOME=$HOME
|
||||||
USER_NAME=$(whoami)
|
USER_NAME=$(whoami)
|
||||||
|
|
||||||
wget -q $REPO_URL -O $USER_HOME/lightning_pub.tar.gz > /dev/null 2>&1 || {
|
download "$REPO_URL" "$USER_HOME/lightning_pub.tar.gz" > /dev/null 2>&1 || {
|
||||||
log "${PRIMARY_COLOR}Failed to download Lightning.Pub.${RESET_COLOR}"
|
log "${PRIMARY_COLOR}Failed to download Lightning.Pub.${RESET_COLOR}"
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
@ -34,10 +34,10 @@ install_lightning_pub() {
|
||||||
# Decide flow based on whether a valid previous installation exists.
|
# Decide flow based on whether a valid previous installation exists.
|
||||||
if [ -f "$INSTALL_DIR/.installed_commit" ] || [ -f "$INSTALL_DIR/db.sqlite" ]; then
|
if [ -f "$INSTALL_DIR/.installed_commit" ] || [ -f "$INSTALL_DIR/db.sqlite" ]; then
|
||||||
# --- UPGRADE PATH ---
|
# --- UPGRADE PATH ---
|
||||||
log "Existing installation found. Checking for updates..."
|
log "Existing ${SECONDARY_COLOR}Lightning.Pub${RESET_COLOR} installation found. Checking for updates..."
|
||||||
|
|
||||||
# Check if update is needed by comparing commit hashes
|
# Check if update is needed by comparing commit hashes
|
||||||
API_RESPONSE=$(wget -qO- "https://api.github.com/repos/${REPO}/commits/${BRANCH}" 2>&1 | tee /tmp/api_response.log)
|
API_RESPONSE=$(download_stdout "https://api.github.com/repos/${REPO}/commits/${BRANCH}" 2>&1 | tee /tmp/api_response.log)
|
||||||
if grep -q '"message"[[:space:]]*:[[:space:]]*"API rate limit exceeded"' <<< "$API_RESPONSE"; then
|
if grep -q '"message"[[:space:]]*:[[:space:]]*"API rate limit exceeded"' <<< "$API_RESPONSE"; then
|
||||||
log_error "GitHub API rate limit exceeded. Please wait a while before trying again." 1
|
log_error "GitHub API rate limit exceeded. Please wait a while before trying again." 1
|
||||||
fi
|
fi
|
||||||
|
|
@ -89,12 +89,17 @@ install_lightning_pub() {
|
||||||
upgrade_status=0
|
upgrade_status=0
|
||||||
mkdir -p "$(dirname "$INSTALL_DIR")"
|
mkdir -p "$(dirname "$INSTALL_DIR")"
|
||||||
mv "$EXTRACT_DIR" "$INSTALL_DIR"
|
mv "$EXTRACT_DIR" "$INSTALL_DIR"
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
# Load nvm and npm
|
# Load nvm (Linux) or add node to PATH (Mac)
|
||||||
export NVM_DIR="${NVM_DIR}"
|
if [ "$OS" = "Mac" ]; then
|
||||||
[ -s "${NVM_DIR}/nvm.sh" ] && \. "${NVM_DIR}/nvm.sh"
|
export PATH="$HOME/node/bin:$PATH"
|
||||||
|
else
|
||||||
|
export NVM_DIR="${NVM_DIR}"
|
||||||
|
[ -s "${NVM_DIR}/nvm.sh" ] && \. "${NVM_DIR}/nvm.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
cd "$INSTALL_DIR"
|
cd "$INSTALL_DIR"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,55 +1,47 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
install_lnd() {
|
install_lnd() {
|
||||||
|
local status_file="$1"
|
||||||
local lnd_status=0
|
local lnd_status=0
|
||||||
|
|
||||||
log "Starting LND installation/check process..."
|
|
||||||
|
|
||||||
USER_HOME=$HOME
|
USER_HOME=$HOME
|
||||||
USER_NAME=$(whoami)
|
USER_NAME=$(whoami)
|
||||||
|
|
||||||
log "Checking latest LND version..."
|
# LND data directory (Mac uses Application Support, Linux uses .lnd)
|
||||||
LND_VERSION=$(wget -qO- https://api.github.com/repos/lightningnetwork/lnd/releases/latest | grep -oP '"tag_name": "\K(.*)(?=")')
|
if [ "$OS" = "Mac" ]; then
|
||||||
log "Latest LND version: $LND_VERSION"
|
LND_DIR="$USER_HOME/Library/Application Support/Lnd"
|
||||||
|
else
|
||||||
|
LND_DIR="$USER_HOME/.lnd"
|
||||||
|
fi
|
||||||
|
|
||||||
LND_URL="https://github.com/lightningnetwork/lnd/releases/download/${LND_VERSION}/lnd-${OS}-${ARCH}-${LND_VERSION}.tar.gz"
|
LND_VERSION=$(get_latest_release_tag "lightningnetwork/lnd")
|
||||||
|
|
||||||
|
if [ -z "$LND_VERSION" ]; then
|
||||||
|
log "${PRIMARY_COLOR}Failed to fetch latest LND version.${RESET_COLOR}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local LND_OS="$OS"; [ "$OS" = "Mac" ] && LND_OS="darwin"
|
||||||
|
LND_URL="https://github.com/lightningnetwork/lnd/releases/download/${LND_VERSION}/lnd-${LND_OS}-${ARCH}-${LND_VERSION}.tar.gz"
|
||||||
|
|
||||||
# Check if LND is already installed
|
# Check if LND is already installed
|
||||||
if [ -d "$USER_HOME/lnd" ]; then
|
if [ -d "$USER_HOME/lnd" ]; then
|
||||||
log "LND directory found. Checking current version..."
|
CURRENT_VERSION=$("$USER_HOME/lnd/lnd" --version | awk '/version/ {print $3}')
|
||||||
CURRENT_VERSION=$("$USER_HOME/lnd/lnd" --version | grep -oP 'version \K[^\s]+')
|
|
||||||
log "Current LND version: $CURRENT_VERSION"
|
|
||||||
|
|
||||||
if [ "$CURRENT_VERSION" == "${LND_VERSION#v}" ]; then
|
if [ "$CURRENT_VERSION" == "${LND_VERSION#v}" ]; then
|
||||||
log "${SECONDARY_COLOR}LND${RESET_COLOR} is already up-to-date (version $CURRENT_VERSION)."
|
log "${SECONDARY_COLOR}LND${RESET_COLOR} is already up-to-date (${LND_VERSION})."
|
||||||
lnd_status=2 # Set status to 2 to indicate no action needed
|
lnd_status=2 # Set status to 2 to indicate no action needed
|
||||||
else
|
else
|
||||||
if [ "$SKIP_PROMPT" != true ]; then
|
log "${PRIMARY_COLOR}Upgrading${RESET_COLOR} ${SECONDARY_COLOR}LND${RESET_COLOR} from ${CURRENT_VERSION} to ${LND_VERSION}..."
|
||||||
read -p "LND version $CURRENT_VERSION is installed. Do you want to upgrade to version $LND_VERSION? (y/N): " response
|
lnd_status=1 # Set status to 1 to indicate upgrade
|
||||||
case "$response" in
|
|
||||||
[yY][eE][sS]|[yY])
|
|
||||||
log "${PRIMARY_COLOR}Upgrading${RESET_COLOR} ${SECONDARY_COLOR}LND${RESET_COLOR} from version $CURRENT_VERSION to $LND_VERSION..."
|
|
||||||
lnd_status=1 # Set status to 1 to indicate upgrade
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
log "$(date '+%Y-%m-%d %H:%M:%S') Upgrade cancelled."
|
|
||||||
lnd_status=2 # Set status to 2 to indicate no action needed
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
else
|
|
||||||
log "${PRIMARY_COLOR}Upgrading${RESET_COLOR} ${SECONDARY_COLOR}LND${RESET_COLOR} from version $CURRENT_VERSION to $LND_VERSION..."
|
|
||||||
lnd_status=1 # Set status to 1 to indicate upgrade
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
log "LND not found. Proceeding with fresh installation..."
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $lnd_status -eq 0 ] || [ $lnd_status -eq 1 ]; then
|
if [ $lnd_status -eq 0 ] || [ $lnd_status -eq 1 ]; then
|
||||||
log "${PRIMARY_COLOR}Downloading${RESET_COLOR} ${SECONDARY_COLOR}LND${RESET_COLOR}..."
|
log "${PRIMARY_COLOR}Downloading${RESET_COLOR} ${SECONDARY_COLOR}LND${RESET_COLOR}..."
|
||||||
|
|
||||||
# Start the download
|
# Start the download
|
||||||
wget -q $LND_URL -O $USER_HOME/lnd.tar.gz || {
|
download "$LND_URL" "$USER_HOME/lnd.tar.gz" || {
|
||||||
log "${PRIMARY_COLOR}Failed to download LND.${RESET_COLOR}"
|
log "${PRIMARY_COLOR}Failed to download LND.${RESET_COLOR}"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
@ -60,12 +52,12 @@ install_lnd() {
|
||||||
log "${PRIMARY_COLOR}Stopping${RESET_COLOR} ${SECONDARY_COLOR}LND${RESET_COLOR} user service..."
|
log "${PRIMARY_COLOR}Stopping${RESET_COLOR} ${SECONDARY_COLOR}LND${RESET_COLOR} user service..."
|
||||||
systemctl --user stop lnd
|
systemctl --user stop lnd
|
||||||
fi
|
fi
|
||||||
else
|
elif [ "$OS" = "Mac" ] && launchctl list 2>/dev/null | grep -q "local.lnd"; then
|
||||||
log "${PRIMARY_COLOR}Please stop ${SECONDARY_COLOR}LND${RESET_COLOR} manually if it is running.${RESET_COLOR}"
|
log "${PRIMARY_COLOR}Stopping${RESET_COLOR} ${SECONDARY_COLOR}LND${RESET_COLOR} launchd service..."
|
||||||
|
launchctl unload "$USER_HOME/Library/LaunchAgents/local.lnd.plist" 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log "Extracting LND..."
|
LND_TMP_DIR=$(mktemp_in "$USER_HOME")
|
||||||
LND_TMP_DIR=$(mktemp -d -p "$USER_HOME")
|
|
||||||
|
|
||||||
tar -xzf "$USER_HOME/lnd.tar.gz" -C "$LND_TMP_DIR" --strip-components=1 > /dev/null || {
|
tar -xzf "$USER_HOME/lnd.tar.gz" -C "$LND_TMP_DIR" --strip-components=1 > /dev/null || {
|
||||||
log "${PRIMARY_COLOR}Failed to extract LND.${RESET_COLOR}"
|
log "${PRIMARY_COLOR}Failed to extract LND.${RESET_COLOR}"
|
||||||
|
|
@ -76,37 +68,34 @@ install_lnd() {
|
||||||
|
|
||||||
rm "$USER_HOME/lnd.tar.gz"
|
rm "$USER_HOME/lnd.tar.gz"
|
||||||
|
|
||||||
if [ -d "$USER_HOME/lnd" ]; then
|
rm -rf "$USER_HOME/lnd" 2>/dev/null || true
|
||||||
log "Removing old LND directory..."
|
|
||||||
rm -rf "$USER_HOME/lnd"
|
|
||||||
fi
|
|
||||||
|
|
||||||
mv "$LND_TMP_DIR" "$USER_HOME/lnd" || {
|
mv "$LND_TMP_DIR" "$USER_HOME/lnd" || {
|
||||||
log "${PRIMARY_COLOR}Failed to move new LND version into place.${RESET_COLOR}"
|
log "${PRIMARY_COLOR}Failed to move new LND version into place.${RESET_COLOR}"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create .lnd directory if it doesn't exist
|
# Create LND data directory if it doesn't exist
|
||||||
mkdir -p $USER_HOME/.lnd
|
mkdir -p "$LND_DIR"
|
||||||
|
|
||||||
# Ensure lnd.conf exists.
|
# Ensure lnd.conf exists.
|
||||||
touch $USER_HOME/.lnd/lnd.conf
|
touch "$LND_DIR/lnd.conf"
|
||||||
|
|
||||||
# Check for and add default settings only if the keys are missing.
|
# Check for and add default settings only if the keys are missing.
|
||||||
grep -q "^bitcoin.mainnet=" $USER_HOME/.lnd/lnd.conf || echo "bitcoin.mainnet=true" >> $USER_HOME/.lnd/lnd.conf
|
grep -q "^bitcoin.mainnet=" "$LND_DIR/lnd.conf" || echo "bitcoin.mainnet=true" >> "$LND_DIR/lnd.conf"
|
||||||
grep -q "^bitcoin.node=" $USER_HOME/.lnd/lnd.conf || echo "bitcoin.node=neutrino" >> $USER_HOME/.lnd/lnd.conf
|
grep -q "^bitcoin.node=" "$LND_DIR/lnd.conf" || echo "bitcoin.node=neutrino" >> "$LND_DIR/lnd.conf"
|
||||||
grep -q "^neutrino.addpeer=neutrino.shock.network" $USER_HOME/.lnd/lnd.conf || echo "neutrino.addpeer=neutrino.shock.network" >> $USER_HOME/.lnd/lnd.conf
|
grep -q "^neutrino.addpeer=neutrino.shock.network" "$LND_DIR/lnd.conf" || echo "neutrino.addpeer=neutrino.shock.network" >> "$LND_DIR/lnd.conf"
|
||||||
grep -q "^neutrino.addpeer=asia.blixtwallet.com" $USER_HOME/.lnd/lnd.conf || echo "neutrino.addpeer=asia.blixtwallet.com" >> $USER_HOME/.lnd/lnd.conf
|
grep -q "^neutrino.addpeer=asia.blixtwallet.com" "$LND_DIR/lnd.conf" || echo "neutrino.addpeer=asia.blixtwallet.com" >> "$LND_DIR/lnd.conf"
|
||||||
grep -q "^neutrino.addpeer=europe.blixtwallet.com" $USER_HOME/.lnd/lnd.conf || echo "neutrino.addpeer=europe.blixtwallet.com" >> $USER_HOME/.lnd/lnd.conf
|
grep -q "^neutrino.addpeer=europe.blixtwallet.com" "$LND_DIR/lnd.conf" || echo "neutrino.addpeer=europe.blixtwallet.com" >> "$LND_DIR/lnd.conf"
|
||||||
grep -q "^neutrino.addpeer=btcd.lnolymp.us" $USER_HOME/.lnd/lnd.conf || echo "neutrino.addpeer=btcd.lnolymp.us" >> $USER_HOME/.lnd/lnd.conf
|
grep -q "^neutrino.addpeer=btcd.lnolymp.us" "$LND_DIR/lnd.conf" || echo "neutrino.addpeer=btcd.lnolymp.us" >> "$LND_DIR/lnd.conf"
|
||||||
grep -q "^neutrino.addpeer=btcd-mainnet.lightning.computer" $USER_HOME/.lnd/lnd.conf || echo "neutrino.addpeer=btcd-mainnet.lightning.computer" >> $USER_HOME/.lnd/lnd.conf
|
grep -q "^neutrino.addpeer=btcd-mainnet.lightning.computer" "$LND_DIR/lnd.conf" || echo "neutrino.addpeer=btcd-mainnet.lightning.computer" >> "$LND_DIR/lnd.conf"
|
||||||
grep -q "^fee.url=" $USER_HOME/.lnd/lnd.conf || echo "fee.url=https://nodes.lightning.computer/fees/v1/btc-fee-estimates.json" >> $USER_HOME/.lnd/lnd.conf
|
grep -q "^fee.url=" "$LND_DIR/lnd.conf" || echo "fee.url=https://nodes.lightning.computer/fees/v1/btc-fee-estimates.json" >> "$LND_DIR/lnd.conf"
|
||||||
|
|
||||||
chmod 600 $USER_HOME/.lnd/lnd.conf
|
chmod 600 "$LND_DIR/lnd.conf"
|
||||||
|
|
||||||
# Port conflict resolution.
|
# Port conflict resolution.
|
||||||
local lnd_port=9735
|
local lnd_port=9735
|
||||||
if ! is_port_available $lnd_port; then
|
if [ "$OS" = "Linux" ] && ! is_port_available $lnd_port; then
|
||||||
# The port is occupied. We should intervene if our service is either in a failed state
|
# The port is occupied. We should intervene if our service is either in a failed state
|
||||||
# or not active at all (which covers fresh installs and failure loops).
|
# or not active at all (which covers fresh installs and failure loops).
|
||||||
if systemctl --user -q is-failed lnd.service 2>/dev/null || ! systemctl --user -q is-active lnd.service 2>/dev/null; then
|
if systemctl --user -q is-failed lnd.service 2>/dev/null || ! systemctl --user -q is-active lnd.service 2>/dev/null; then
|
||||||
|
|
@ -114,19 +103,20 @@ install_lnd() {
|
||||||
lnd_port_new=$(find_available_port $lnd_port)
|
lnd_port_new=$(find_available_port $lnd_port)
|
||||||
log "Configuring LND to use new port $lnd_port_new."
|
log "Configuring LND to use new port $lnd_port_new."
|
||||||
|
|
||||||
sed -i '/^listen=/d' $USER_HOME/.lnd/lnd.conf
|
sed_i '/^listen=/d' "$LND_DIR/lnd.conf"
|
||||||
echo "listen=0.0.0.0:$lnd_port_new" >> $USER_HOME/.lnd/lnd.conf
|
echo "listen=0.0.0.0:$lnd_port_new" >> "$LND_DIR/lnd.conf"
|
||||||
log "LND configuration updated. The service will be restarted by the installer."
|
log "LND configuration updated. The service will be restarted by the installer."
|
||||||
else
|
else
|
||||||
log "Port $lnd_port is in use by a healthy LND service (assumed to be our own). No changes will be made."
|
log "Port $lnd_port is in use by a healthy LND service (assumed to be our own). No changes will be made."
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log "${SECONDARY_COLOR}LND${RESET_COLOR} installation and configuration completed."
|
log "${SECONDARY_COLOR}LND${RESET_COLOR} installed successfully."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log "LND installation/check process complete. Status: $lnd_status"
|
if [ -n "$status_file" ]; then
|
||||||
# Echo the LND status
|
echo "$lnd_status" > "$status_file"
|
||||||
echo "LND_STATUS:$lnd_status"
|
fi
|
||||||
|
|
||||||
return 0 # Always return 0 to indicate success
|
return 0 # Always return 0 to indicate success
|
||||||
}
|
}
|
||||||
|
|
@ -2,23 +2,112 @@
|
||||||
|
|
||||||
install_nodejs() {
|
install_nodejs() {
|
||||||
USER_HOME=$HOME
|
USER_HOME=$HOME
|
||||||
USER_NAME=$(whoami)
|
MINIMUM_VERSION="24.0.0"
|
||||||
|
|
||||||
export NVM_DIR="$USER_HOME/.nvm"
|
|
||||||
log "${PRIMARY_COLOR}Checking${RESET_COLOR} for Node.js..."
|
log "${PRIMARY_COLOR}Checking${RESET_COLOR} for Node.js..."
|
||||||
MINIMUM_VERSION="18.0.0"
|
|
||||||
|
if [ "$OS" = "Mac" ]; then
|
||||||
|
install_nodejs_mac
|
||||||
|
else
|
||||||
|
install_nodejs_linux
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
install_nodejs_mac() {
|
||||||
|
local NODE_BIN="$USER_HOME/node/bin/node"
|
||||||
|
|
||||||
|
# Check if node exists and meets minimum version
|
||||||
|
if [ -x "$NODE_BIN" ]; then
|
||||||
|
NODE_VERSION=$("$NODE_BIN" -v | sed 's/v//')
|
||||||
|
if [ "$(printf '%s\n' "$MINIMUM_VERSION" "$NODE_VERSION" | sort -V | awk 'NR==1')" = "$MINIMUM_VERSION" ]; then
|
||||||
|
log "Node.js is already installed and meets the minimum version requirement."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get latest LTS version from Node.js
|
||||||
|
local node_tmp=$(mktemp)
|
||||||
|
download_stdout "https://nodejs.org/dist/index.json" > "$node_tmp"
|
||||||
|
local lts_version=$(grep -o '"version":"v[0-9.]*"[^}]*"lts":"[A-Za-z]*"' "$node_tmp" | grep -v '"lts":false' | head -1 | awk -F'"' '{print $4}')
|
||||||
|
rm -f "$node_tmp"
|
||||||
|
|
||||||
|
if [ -z "$lts_version" ]; then
|
||||||
|
log "Failed to fetch Node.js LTS version."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "${PRIMARY_COLOR}Installing${RESET_COLOR} Node.js ${lts_version}..."
|
||||||
|
|
||||||
|
local node_arch="x64"
|
||||||
|
[ "$ARCH" = "arm64" ] && node_arch="arm64"
|
||||||
|
|
||||||
|
local node_url="https://nodejs.org/dist/${lts_version}/node-${lts_version}-darwin-${node_arch}.tar.gz"
|
||||||
|
local node_tar="$USER_HOME/node.tar.gz"
|
||||||
|
|
||||||
|
download "$node_url" "$node_tar" || {
|
||||||
|
log "Failed to download Node.js."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Extract to ~/node
|
||||||
|
rm -rf "$USER_HOME/node"
|
||||||
|
mkdir -p "$USER_HOME/node"
|
||||||
|
tar -xzf "$node_tar" -C "$USER_HOME/node" --strip-components=1 || {
|
||||||
|
log "Failed to extract Node.js."
|
||||||
|
rm -f "$node_tar"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
rm -f "$node_tar"
|
||||||
|
|
||||||
|
# Add to PATH for current session
|
||||||
|
export PATH="$USER_HOME/node/bin:$PATH"
|
||||||
|
|
||||||
|
# Add to shell profile if not already there
|
||||||
|
local shell_profile="$USER_HOME/.zshrc"
|
||||||
|
[ -f "$USER_HOME/.bash_profile" ] && shell_profile="$USER_HOME/.bash_profile"
|
||||||
|
|
||||||
|
if ! grep -q 'node/bin' "$shell_profile" 2>/dev/null; then
|
||||||
|
echo 'export PATH="$HOME/node/bin:$PATH"' >> "$shell_profile"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Node.js ${lts_version} installation completed."
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
install_nodejs_linux() {
|
||||||
|
export NVM_DIR="$USER_HOME/.nvm"
|
||||||
|
|
||||||
|
# Check for snap curl which cannot access hidden folders, nvm falls back to wget if curl is not installed
|
||||||
|
if snap list 2>/dev/null | grep -q "^curl "; then
|
||||||
|
log "ERROR: Snap curl detected"
|
||||||
|
log ""
|
||||||
|
log "Snap curl cannot access hidden folders needed for Node.js installation."
|
||||||
|
log "Please remove snap curl and install native curl:"
|
||||||
|
log " sudo snap remove curl"
|
||||||
|
log " sudo apt install curl"
|
||||||
|
log ""
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Load nvm if it already exists
|
# Load nvm if it already exists
|
||||||
export NVM_DIR="${NVM_DIR}"
|
|
||||||
[ -s "${NVM_DIR}/nvm.sh" ] && \. "${NVM_DIR}/nvm.sh"
|
[ -s "${NVM_DIR}/nvm.sh" ] && \. "${NVM_DIR}/nvm.sh"
|
||||||
|
|
||||||
if ! command -v nvm &> /dev/null; then
|
if ! command -v nvm &> /dev/null; then
|
||||||
NVM_VERSION=$(wget -qO- https://api.github.com/repos/nvm-sh/nvm/releases/latest | grep -oP '"tag_name": "\K(.*)(?=")')
|
NVM_VERSION=$(get_latest_release_tag "nvm-sh/nvm")
|
||||||
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh | bash > /dev/null 2>&1
|
if [ -z "$NVM_VERSION" ]; then
|
||||||
export NVM_DIR="${NVM_DIR}"
|
log "Failed to fetch latest NVM version."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
log "Installing NVM ${NVM_VERSION}..."
|
||||||
|
download_stdout "https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh" | bash > /dev/null 2>&1
|
||||||
[ -s "${NVM_DIR}/nvm.sh" ] && \. "${NVM_DIR}/nvm.sh"
|
[ -s "${NVM_DIR}/nvm.sh" ] && \. "${NVM_DIR}/nvm.sh"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if ! command -v nvm &> /dev/null; then
|
||||||
|
log "NVM installation failed."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
if command -v node &> /dev/null; then
|
if command -v node &> /dev/null; then
|
||||||
NODE_VERSION=$(node -v | sed 's/v//')
|
NODE_VERSION=$(node -v | sed 's/v//')
|
||||||
if [ "$(printf '%s\n' "$MINIMUM_VERSION" "$NODE_VERSION" | sort -V | head -n1)" = "$MINIMUM_VERSION" ]; then
|
if [ "$(printf '%s\n' "$MINIMUM_VERSION" "$NODE_VERSION" | sort -V | head -n1)" = "$MINIMUM_VERSION" ]; then
|
||||||
|
|
@ -31,8 +120,7 @@ install_nodejs() {
|
||||||
log "Node.js is not installed. ${PRIMARY_COLOR}Installing the LTS version...${RESET_COLOR}"
|
log "Node.js is not installed. ${PRIMARY_COLOR}Installing the LTS version...${RESET_COLOR}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Silence all nvm output to keep installer logs clean
|
if ! nvm install --lts > /dev/null 2>&1; then
|
||||||
if ! bash -c "source ${NVM_DIR}/nvm.sh && nvm install --lts" >/dev/null 2>&1; then
|
|
||||||
log "${PRIMARY_COLOR}Failed to install Node.js.${RESET_COLOR}"
|
log "${PRIMARY_COLOR}Failed to install Node.js.${RESET_COLOR}"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
15
scripts/qr_generator.js
Executable file
15
scripts/qr_generator.js
Executable file
|
|
@ -0,0 +1,15 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import qrcode from 'qrcode-terminal';
|
||||||
|
|
||||||
|
const text = process.argv[2];
|
||||||
|
|
||||||
|
if (!text) {
|
||||||
|
console.error('Usage: qr_generator.js <text>');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
qrcode.generate(text, { small: true }, (qr) => {
|
||||||
|
console.log(qr);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
start_services_mac() {
|
|
||||||
create_launchd_plist
|
|
||||||
launchctl load "${LAUNCH_AGENTS_DIR}/local.lnd.plist"
|
|
||||||
launchctl load "${LAUNCH_AGENTS_DIR}/local.lightning_pub.plist"
|
|
||||||
log "${SECONDARY_COLOR}LND${RESET_COLOR} and ${SECONDARY_COLOR}Lightning.Pub${RESET_COLOR} services started using launchd."
|
|
||||||
}
|
|
||||||
|
|
||||||
handle_macos() {
|
|
||||||
check_homebrew
|
|
||||||
install_rsync_mac
|
|
||||||
install_nodejs
|
|
||||||
install_lightning_pub
|
|
||||||
create_launchd_plist
|
|
||||||
start_services_mac
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
PRIMARY_COLOR="\e[38;5;208m"
|
|
||||||
SECONDARY_COLOR="\e[38;5;165m"
|
|
||||||
RESET_COLOR="\e[0m"
|
|
||||||
|
|
||||||
detect_os_arch() {
|
|
||||||
OS="$(uname -s)"
|
|
||||||
ARCH="$(uname -m)"
|
|
||||||
case "$OS" in
|
|
||||||
Linux*) OS=Linux;;
|
|
||||||
Darwin*) OS=Mac;;
|
|
||||||
CYGWIN*) OS=Cygwin;;
|
|
||||||
MINGW*) OS=MinGw;;
|
|
||||||
*) OS="UNKNOWN"
|
|
||||||
esac
|
|
||||||
case "$ARCH" in
|
|
||||||
x86_64) ARCH=amd64;;
|
|
||||||
arm64|aarch64|armv8*) ARCH=arm64;;
|
|
||||||
armv7*) ARCH=armv7;;
|
|
||||||
*) ARCH="UNKNOWN"
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ "$OS" = "Linux" ] && command -v systemctl &> /dev/null; then
|
|
||||||
SYSTEMCTL_AVAILABLE=true
|
|
||||||
else
|
|
||||||
SYSTEMCTL_AVAILABLE=false
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
check_deps() {
|
|
||||||
for cmd in wget grep stat tar sha256sum; do
|
|
||||||
if ! command -v $cmd &> /dev/null; then
|
|
||||||
log "Missing system dependency: $cmd. Install $cmd via your package manager and retry."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
@ -95,18 +95,25 @@ const resolveHome = (filepath: string) => {
|
||||||
return path.join(homeDir, filepath);
|
return path.join(homeDir, filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const lndDir = () => {
|
||||||
|
if (os.platform() === 'darwin') {
|
||||||
|
return path.join(os.homedir(), 'Library', 'Application Support', 'Lnd');
|
||||||
|
}
|
||||||
|
return resolveHome('/.lnd');
|
||||||
|
}
|
||||||
|
|
||||||
export const LoadLndNodeSettingsFromEnv = (dbEnv: Record<string, string | undefined>, addToDb?: EnvCacher): LndNodeSettings => {
|
export const LoadLndNodeSettingsFromEnv = (dbEnv: Record<string, string | undefined>, addToDb?: EnvCacher): LndNodeSettings => {
|
||||||
return {
|
return {
|
||||||
lndAddr: chooseEnv('LND_ADDRESS', dbEnv, "127.0.0.1:10009", addToDb),
|
lndAddr: chooseEnv('LND_ADDRESS', dbEnv, "127.0.0.1:10009", addToDb),
|
||||||
lndCertPath: chooseEnv('LND_CERT_PATH', dbEnv, resolveHome("/.lnd/tls.cert"), addToDb),
|
lndCertPath: chooseEnv('LND_CERT_PATH', dbEnv, path.join(lndDir(), "tls.cert"), addToDb),
|
||||||
lndMacaroonPath: chooseEnv('LND_MACAROON_PATH', dbEnv, resolveHome("/.lnd/data/chain/bitcoin/mainnet/admin.macaroon"), addToDb),
|
lndMacaroonPath: chooseEnv('LND_MACAROON_PATH', dbEnv, path.join(lndDir(), "data", "chain", "bitcoin", "mainnet", "admin.macaroon"), addToDb),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LoadLndSettingsFromEnv = (dbEnv: Record<string, string | undefined>, addToDb?: EnvCacher): LndSettings => {
|
export const LoadLndSettingsFromEnv = (dbEnv: Record<string, string | undefined>, addToDb?: EnvCacher): LndSettings => {
|
||||||
const feeRateBps: number = chooseEnvInt('OUTBOUND_MAX_FEE_BPS', dbEnv, 60, addToDb)
|
const feeRateBps: number = chooseEnvInt('OUTBOUND_MAX_FEE_BPS', dbEnv, 60, addToDb)
|
||||||
return {
|
return {
|
||||||
lndLogDir: chooseEnv('LND_LOG_DIR', dbEnv, resolveHome("/.lnd/logs/bitcoin/mainnet/lnd.log"), addToDb),
|
lndLogDir: chooseEnv('LND_LOG_DIR', dbEnv, path.join(lndDir(), "logs", "bitcoin", "mainnet", "lnd.log"), addToDb),
|
||||||
feeRateBps: feeRateBps,
|
feeRateBps: feeRateBps,
|
||||||
feeRateLimit: feeRateBps / 10000,
|
feeRateLimit: feeRateBps / 10000,
|
||||||
feeFixedLimit: chooseEnvInt('OUTBOUND_MAX_FEE_EXTRA_SATS', dbEnv, 100, addToDb),
|
feeFixedLimit: chooseEnvInt('OUTBOUND_MAX_FEE_EXTRA_SATS', dbEnv, 100, addToDb),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue