diff --git a/README.md b/README.md index 1439b510..d0a5d7a2 100644 --- a/README.md +++ b/README.md @@ -3,44 +3,14 @@ lspd is a simple deamon that provides [LSP](https://medium.com/breez-technology/ This is a simple example of an lspd that works with an [lnd](https://github.com/lightningnetwork/lnd) node or a [cln](https://github.com/ElementsProject/lightning) node. -## Installation -### Build -1. git clone https://github.com/breez/lspd (or fork) -1. Compile lspd using `go build .` - -### Before running -1. Create a random token (for instance using the command `openssl rand -base64 48`, or `./lspd genkey`) -1. Define the environment variables as described in sample.env. If `CERTMAGIC_DOMAIN` is defined, certificate for this domain is automatically obtained and renewed from Let's Encrypt. In this case, the port needs to be 443. If `CERTMAGIC_DOMAIN` is not defined, lspd needs to run behind a reverse proxy like treafik or nginx. - -### Running lspd on LND -1. Run LND with the following options set: - - `--protocol.zero-conf`: for being able to open zero conf channels - - `--protocol.option-scid-alias`: required for zero conf channels - - `--requireinterceptor`: to make sure all htlcs are intercepted by lspd - - `--bitcoin.chanreservescript="0"` to allow the client to have zero reserve on their side -1. Run lspd - -### Running lspd on CLN -In order to run lspd on top of CLN, you need to run the lspd process and run cln with the provided cln plugin. - -The cln plugin (go build -o lspd_plugin cln_plugin/cmd) is best started with a bash script to pass environment variables (note this LISTEN_ADDRESS is the listen address for communication between lspd and the plugin, this is not the listen address mentioned in the 'final step') - -```bash -#!/bin/bash - -export LISTEN_ADDRESS= -/path/to/lspd_plugin -``` - -1. Run cln with the following options set: - - `--plugin=/path/to/shell/script.sh`: to use lspd as plugin - - `--max-concurrent-htlcs=30`: In order to use zero reserve channels on the client side, (local max_accepted_htlcs + remote max_accepted_htlcs + 2) * dust limit must be lower than the channel capacity. Reduce max-concurrent-htlcs or increase channel capacity accordingly. - - `--dev-allowdustreserve=true`: In order to allow zero reserve on the client side, you'll need to enable developer mode on cln (`./configure --enable-developer`) - - `--experimental-anchors`: In order to allow opening anchor channels. -1. Run lspd - -### Final step -1. Share with Breez the TOKEN and the LISTEN_ADDRESS you've defined (send to contact@breez.technology) +## Deployment +Installation and configuration instructions for both implementations can be found here: +### Manual install +- [CLN](./docs/CLN.md) - step by step installation instructions for CLN +- [LND](./docs/LND.md) - step by step installation instructions for LND +### Automated deployment +- [AWS](./docs/aws.md) - automated deployment of bitcoind, CLN and lspd to AWS, together with +- [Bash](./docs/bash.md) - install everything on any debian/ubuntu server ## Implement your own lspd You can create your own lsdp by implementing the grpc methods described [here](https://github.com/breez/lspd/blob/master/rpc/lspd.md). @@ -98,5 +68,4 @@ up some artefacts. Here's where to look: - bitcoind process - docker container for postgres with default name -It may be a good idea to clean your testdir every once in a while if you're -using the `preservelogs` or `preservestate` flags. \ No newline at end of file +It may be a good idea to clean your testdir every once in a while if you're using the `preservelogs` or `preservestate` flags. \ No newline at end of file diff --git a/deploy/deploy.yml b/deploy/deploy.yml new file mode 100644 index 00000000..6852edfa --- /dev/null +++ b/deploy/deploy.yml @@ -0,0 +1,385 @@ +AWSTemplateFormatVersion: '2010-09-09' + +Parameters: + KeyName: + Description: Name of an existing EC2 KeyPair to enable SSH access + Type: 'AWS::EC2::KeyPair::KeyName' + + LSPName: + Description: LSP Name + Type: String + + VPCID: + Description: The ID of the VPC in which to create the resources + Type: 'AWS::EC2::VPC::Id' + +Mappings: + AMIRegionMap: + ap-northeast-1: + AMIID: ami-0deffe25fb08894f5 + ap-northeast-2: + AMIID: ami-097243fad67b35a40 + ap-northeast-3: + AMIID: ami-03ad2f651aaddff3a + ap-south-1: + AMIID: ami-0361008010558ea2d + ap-southeast-1: + AMIID: ami-07bf64b7ca62c96ee + ap-southeast-2: + AMIID: ami-0cc8e61f3957442b8 + ca-central-1: + AMIID: ami-0cfe1aac5d0b881ff + eu-central-1: + AMIID: ami-0042e6537994c4181 + eu-north-1: + AMIID: ami-00347e40213620217 + eu-west-1: + AMIID: ami-04620cb5b85309067 + eu-west-2: + AMIID: ami-0315c69b482426e70 + eu-west-3: + AMIID: ami-0dcc6ef9e7a6e70f2 + sa-east-1: + AMIID: ami-027ba68d27297f530 + us-east-1: + AMIID: ami-01e8fbda99c153c6b + us-east-2: + AMIID: ami-0ef27e70f95b439e8 + us-west-1: + AMIID: ami-09d529cbaf5cc7e6f + us-west-2: + AMIID: ami-0acfc42b227d0b719 + +Resources: + # EC2 Instance + EC2Instance: + Type: 'AWS::EC2::Instance' + Properties: + InstanceType: m6a.xlarge + ImageId: !FindInMap [AMIRegionMap, !Ref "AWS::Region", AMIID] + KeyName: !Ref KeyName + BlockDeviceMappings: # resize root volume to 1TB + - DeviceName: "/dev/xvda" + Ebs: + VolumeSize: 1024 + VolumeType: gp2 + DeleteOnTermination: true + UserData: + Fn::Base64: + !Sub | + #!/bin/bash + + # Elevate privileges + if [ "$EUID" -ne 0 ]; then + sudo bash "$0" "$@" + exit + fi + # Redirect all outputs to a log file + exec > >(tee -a "/tmp/deployment.log") 2>&1 + # fix locale if on debian + if grep -q "Debian" /etc/os-release; then + sed -i '/^# en_US.UTF-8 UTF-8/s/^# //' /etc/locale.gen + locale-gen + echo "export LC_ALL=en_US.UTF-8" >> /etc/bash.bashrc + echo "export LANG=en_US.UTF-8" >> /etc/bash.bashrc + + fi + source /etc/bash.bashrc + # create users + sudo adduser --disabled-password --gecos "" lightning + sudo adduser --disabled-password --gecos "" bitcoin + sudo adduser --disabled-password --gecos "" lspd + + # Create a file to store the credentials + CREDENTIALS="/home/lspd/credentials.txt" + touch "$CREDENTIALS" + # Generate a random password for PostgreSQL users + LSPD_DB_PASSWORD=$(> "$CREDENTIALS" + echo "postgres lspd:" >> "$CREDENTIALS" + echo "username: lspd " >> "$CREDENTIALS" + echo "password: $LSPD_DB_PASSWORD" >> "$CREDENTIALS" + echo "postgres lightning:" >> "$CREDENTIALS" + echo "username: lightning" >> "$CREDENTIALS" + echo "password: $LIGHTNING_DB_PASSWORD" >> "$CREDENTIALS" + + # Generic name if no name is provided (running locally) + if [ -z "$LSPName" ]; then + LSPName="lsp-$(> "$CREDENTIALS" + echo "rpcuser: cln" >> "$CREDENTIALS" + echo "rpcpassword: $RPCPASSWORD" >> "$CREDENTIALS" + sudo mkdir /etc/bitcoin/ + sudo touch /etc/bitcoin/bitcoin.conf + cat <> "$CREDENTIALS" + sudo echo "cln hsm_secret backup:" >> "$CREDENTIALS" + sudo xxd /home/lightning/.lightning/bitcoin/hsm_secret >> "$CREDENTIALS" + + # Post install + PUBKEY=$(sudo -u lightning lightning-cli getinfo | jq .id | cut -d "\"" -f 2) + + LSPD_PRIVATE_KEY=$(lspd genkey | awk -F= '{print $2}' | cut -d "\"" -f 2) + TOKEN=$(lspd genkey | awk -F= '{print $2}' | cut -d "\"" -f 2) + EXTERNAL_IP=$(curl -s http://whatismyip.akamai.com/) + echo "### LSPD Credentials ###" >> "$CREDENTIALS" + echo "token: $TOKEN" >> "$CREDENTIALS" + echo "lspd_private_key: $LSPD_PRIVATE_KEY" >> "$CREDENTIALS" + + cat < >(tee -a "/tmp/deployment.log") 2>&1 +# fix locale if on debian +if grep -q "Debian" /etc/os-release; then + sed -i '/^# en_US.UTF-8 UTF-8/s/^# //' /etc/locale.gen + locale-gen + echo "export LC_ALL=en_US.UTF-8" >> /etc/bash.bashrc + echo "export LANG=en_US.UTF-8" >> /etc/bash.bashrc + +fi +source /etc/bash.bashrc +# create users +sudo adduser --disabled-password --gecos "" lightning +sudo adduser --disabled-password --gecos "" bitcoin +sudo adduser --disabled-password --gecos "" lspd + +# Create a file to store the credentials +CREDENTIALS="/home/lspd/credentials.txt" +touch "$CREDENTIALS" +# Generate a random password for PostgreSQL users +LSPD_DB_PASSWORD=$(> "$CREDENTIALS" +echo "postgres lspd:" >> "$CREDENTIALS" +echo "username: lspd " >> "$CREDENTIALS" +echo "password: $LSPD_DB_PASSWORD" >> "$CREDENTIALS" +echo "postgres lightning:" >> "$CREDENTIALS" +echo "username: lightning" >> "$CREDENTIALS" +echo "password: $LIGHTNING_DB_PASSWORD" >> "$CREDENTIALS" + +# Generic name if no name is provided (running locally) +if [ -z "$LSPName" ]; then +LSPName="lsp-$(> "$CREDENTIALS" +echo "rpcuser: cln" >> "$CREDENTIALS" +echo "rpcpassword: $RPCPASSWORD" >> "$CREDENTIALS" +sudo mkdir /etc/bitcoin/ +sudo touch /etc/bitcoin/bitcoin.conf +cat <> "$CREDENTIALS" +sudo echo "cln hsm_secret backup:" >> "$CREDENTIALS" +sudo xxd /home/lightning/.lightning/bitcoin/hsm_secret >> "$CREDENTIALS" + +# Post install +PUBKEY=$(sudo -u lightning lightning-cli getinfo | jq .id | cut -d "\"" -f 2) + +LSPD_PRIVATE_KEY=$(lspd genkey | awk -F= '{print $2}' | cut -d "\"" -f 2) +TOKEN=$(lspd genkey | awk -F= '{print $2}' | cut -d "\"" -f 2) +EXTERNAL_IP=$(curl -s http://whatismyip.akamai.com/) +echo "### LSPD Credentials ###" >> "$CREDENTIALS" +echo "token: $TOKEN" >> "$CREDENTIALS" +echo "lspd_private_key: $LSPD_PRIVATE_KEY" >> "$CREDENTIALS" + +cat <; +ALTER ROLE WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB LOGIN NOREPLICATION NOBYPASSRLS PASSWORD ''; +CREATE DATABASE WITH TEMPLATE = template0 ENCODING = 'UTF8' LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8'; +ALTER DATABASE OWNER TO ; +``` +##### RDS on AWS +``` +CREATE ROLE ; +ALTER ROLE WITH INHERIT NOCREATEROLE NOCREATEDB LOGIN NOBYPASSRLS PASSWORD ''; +CREATE DATABASE WITH TEMPLATE = template0 ENCODING = 'UTF8' LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8'; +ALTER DATABASE OWNER TO ; +``` + +### Configuration +1. Create a random token (for instance using the command `openssl rand -base64 48`, or `./lspd genkey`) +1. Define the environment variables as described in [sample.env](./sample.env). If `CERTMAGIC_DOMAIN` is defined, certificate for this domain is automatically obtained and renewed from Let's Encrypt. In this case, the port needs to be 443. If `CERTMAGIC_DOMAIN` is not defined, lspd needs to run behind a reverse proxy like treafik or nginx. + +ENV variables: +- `LISTEN_ADDRESS` defines the host:port for the lspd grpc server +- `CERTMAGIC_DOMAIN` domain on which lspd will be accessible +- `DATABASE_URL` postgresql db url +- `AWS_REGION` AWS region for SES emailing +- `AWS_ACCESS_KEY_ID` API key for SES emailing +- `AWS_SECRET_ACCESS_KEY`API secret for SES emailing +- `MEMPOOL_API_BASE_URL` uses fee estimation for opening new channels (default: https://mempool.space/api/v1/) +- `MEMPOOL_PRIORITY` priority with which open new channels using mempool api + (options: minimum, economy, hour, halfhour, fastest) (default: economy) +- `NODES` which nodes are used by lspd (see below for example, multiple nodes supported and more examples can be found in [sample.env](../sample.env)) + +Example of NODES variable: +``` +NODES='[ { "name": "${LSPName}", "nodePubkey": "$PUBKEY", "lspdPrivateKey": "$LSPD_PRIVATE_KEY", "token": "$TOKEN", "host": "$EXTERNAL_IP:8888", "publicChannelAmount": "1000183", "channelAmount": "100000", "channelPrivate": false, "targetConf": "6", "minConfs": "6", "minHtlcMsat": "600", "baseFeeMsat": "1000", "feeRate": "0.000001", "timeLockDelta": "144", "channelFeePermyriad": "40", "channelMinimumFeeMsat": "2000000", "additionalChannelCapacity": "100000", "maxInactiveDuration": "3888000", "cln": { "pluginAddress": "127.0.0.1:12312", "socketPath": "/home/lightning/.lightning/bitcoin/lightning-rpc" } } ]' +``` + +### Running lspd on CLN +In order to run lspd on top of CLN, you need to run the lspd process and run cln with the provided cln plugin. You also need lightningd compiled with developer mode on (`./configure --enable-developer`) + +1. Run cln with the following options set: + - `--plugin=/path/to/lspd_plugin`: to use lspd as plugin + - `--max-concurrent-htlcs=30`: In order to use zero reserve channels on the client side, (local max_accepted_htlcs + remote max_accepted_htlcs + 2) * dust limit must be lower than the channel capacity. Reduce max-concurrent-htlcs or increase channel capacity accordingly. + - `--dev-allowdustreserve=true`: In order to allow zero reserve on the client side (requires developer mode turned on) + - `--allow-deprecated-apis=true`: lspd currently uses a deprecated api, so needs this flag set. + - `--lsp-listen=127.0.0.1:`: Set on which port the lspd_plugin will listen for lspd communication, must be the same port that is used in pluginAddress parameter in NODES env variable. +1. Run lspd + +### Final step +1. Share with Breez the TOKEN and the LISTEN_ADDRESS you've defined (send to contact@breez.technology) \ No newline at end of file diff --git a/docs/LND.md b/docs/LND.md new file mode 100644 index 00000000..fbd63fda --- /dev/null +++ b/docs/LND.md @@ -0,0 +1,52 @@ + +## Installation instructions for lnd and lspd +### Requirements +- lnd +- lspd +- postgresql + +### Installation +#### LND +Follow LND installation instructions [here](https://github.com/lightningnetwork/lnd/blob/master/docs/INSTALL.md). + +#### lspd +Needs to be build from source: +``` +git clone https://github.com/breez/lspd +cd lspd +go build . # compile lspd +``` +### Postgresql +Lspd supports postgresql backend. Create new database and user for lspd: +``` +CREATE ROLE ; +ALTER ROLE WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB LOGIN NOREPLICATION NOBYPASSRLS PASSWORD ''; +CREATE DATABASE WITH TEMPLATE = template0 ENCODING = 'UTF8' LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8'; +ALTER DATABASE OWNER TO ; +`````` + + +### Configure +1. Create a random token (for instance using the command `openssl rand -base64 48`, or `./lspd genkey`) +1. Define the environment variables as described in [sample.env](./sample.env). If `CERTMAGIC_DOMAIN` is defined, certificate for this domain is automatically obtained and renewed from Let's Encrypt. In this case, the port needs to be 443. If `CERTMAGIC_DOMAIN` is not defined, lspd needs to run behind a reverse proxy like treafik or nginx. + +ENV variables: +- `LISTEN_ADDRESS` defines the host:port for the lspd grpc server +- `CERTMAGIC_DOMAIN` domain on which lspd will be accessible +- `DATABASE_URL` postgresql db url +- `AWS_REGION` +- `AWS_ACCESS_KEY_ID` +- `AWS_SECRET_ACCESS_KEY` +- `MEMPOOL_API_BASE_URL` uses fee estimation for opening new channels (default: https://mempool.space) +- `MEMPOOL_PRIORITY` priority with which open new channels using mempool api (default: economy) + +### Running lspd on LND +1. Run LND with the following options set: + - `--protocol.zero-conf`: for being able to open zero conf channels + - `--protocol.option-scid-alias`: required for zero conf channels + - `--requireinterceptor`: to make sure all htlcs are intercepted by lspd + - `--bitcoin.chanreservescript="0"` to allow the client to have zero reserve on their side +1. Run lspd + +### Final step +1. Share with Breez the TOKEN and the LISTEN_ADDRESS you've defined (send to contact@breez.technology) diff --git a/docs/aws.md b/docs/aws.md new file mode 100644 index 00000000..f19513a3 --- /dev/null +++ b/docs/aws.md @@ -0,0 +1,42 @@ +## Automated deployment of LSPD stack to AWS +Cloudformation template for automated deployment of lspd, bitcoind and cln with postgresql backend. +### Requirements +- AWS account +- AWS SES configured + +### Deployment +[Cloudformation template](../deploy/deploy.yml) will automatically deploy several things: +- new ec2 instance (m6a.xlarge) to your selected VPC +- bitcoind +- cln (with postgresql as backend) +- lspd + +### After deployment steps +#### Configure email notifications + +Edit file ```/home/lspd/.env```. + +1) set your SES credentials: +``` +AWS_REGION="" +AWS_ACCESS_KEY_ID="" +AWS_SECRET_ACCESS_KEY="" +``` + +2) configure email +``` +OPENCHANNEL_NOTIFICATION_TO='["REPLACE ME "]' +OPENCHANNEL_NOTIFICATION_CC='["REPLACE ME "]' +OPENCHANNEL_NOTIFICATION_FROM="test@example.com" + +CHANNELMISMATCH_NOTIFICATION_TO='["REPLACE ME "]' +CHANNELMISMATCH_NOTIFICATION_CC='["REPLACE ME "]' +CHANNELMISMATCH_NOTIFICATION_FROM="replaceme@example.com" +``` +#### Backup credentials + +All credentials are generated automatically and are written down in ```/home/lspd/credentials.txt``` + +**Store them securely and delete the file.** +### Debugging +Log file of deployment is written to ```/tmp/deployment.log``` where you can see the entire output of what happend during deployment. diff --git a/docs/bash.md b/docs/bash.md new file mode 100644 index 00000000..8c4900e3 --- /dev/null +++ b/docs/bash.md @@ -0,0 +1,57 @@ +## Automated install of LSPD stack for linux +### Requirements +- ubuntu or debian based distribution +- AWS SES credentials +- root / user without sudo password + +### Installation +To install bitcoind,cln and lspd to your system simply run: + +```curl -sL https://raw.githubusercontent.com/breez/lspd/master/deploy/lspd-install.sh | sudo bash -``` + +It will automatically configure your server and install all needed dependencies for running LSPD stack. You will have to manually change the name of your LSPD and your cln alias. + +LSPD: + +``` +vim /home/lspd/.env +# change the name variable in the last line, it will have randomly generated name like "lsp-53v4" +NODES='[ { "name": "${LSPName}" +``` + +CLN: +``` +vim /home/lightning/.lightning/config +# change alias row, it will have randomly generated name like "lsp-53v4" +alias="${LSPName}" +``` + +### After deployment steps +#### Configure email notifications + +Edit file ```/home/lspd/.env```. + +1) set your SES credentials: +``` +AWS_REGION="" +AWS_ACCESS_KEY_ID="" +AWS_SECRET_ACCESS_KEY="" +``` + +2) configure email +``` +OPENCHANNEL_NOTIFICATION_TO='["REPLACE ME "]' +OPENCHANNEL_NOTIFICATION_CC='["REPLACE ME "]' +OPENCHANNEL_NOTIFICATION_FROM="test@example.com" + +CHANNELMISMATCH_NOTIFICATION_TO='["REPLACE ME "]' +CHANNELMISMATCH_NOTIFICATION_CC='["REPLACE ME "]' +CHANNELMISMATCH_NOTIFICATION_FROM="replaceme@example.com" +``` +#### Backup credentials + +All credentials are generated automatically and are written down in ```/home/lspd/credentials.txt``` + +**Store them securely and delete the file.** +### Debugging +Log file of deployment is written to ```/tmp/deployment.log``` where you can see the entire output of what happend during deployment. \ No newline at end of file