diff --git a/bin/thundercloud.ts b/bin/thundercloud.ts index 8f72986..6176139 100644 --- a/bin/thundercloud.ts +++ b/bin/thundercloud.ts @@ -1,10 +1,10 @@ #!/usr/bin/env node import 'source-map-support/register'; import * as cdk from '@aws-cdk/core'; -import { ThundercloudStack } from '../lib/thundercloud-stack'; +import { LightningNode } from '../lib/lightningnode-stack'; const app = new cdk.App(); -new ThundercloudStack(app, 'ThundercloudStack', { +new LightningNode(app, 'ThundercloudStack', { /* If you don't specify 'env', this stack will be environment-agnostic. * Account/Region-dependent features and context lookups will not work, * but a single synthesized template can be deployed anywhere. */ diff --git a/lib/configure-node.sh b/lib/configure-node.sh new file mode 100644 index 0000000..f6b6690 --- /dev/null +++ b/lib/configure-node.sh @@ -0,0 +1,176 @@ +#!/bin/bash + +wget https://github.com/lightningnetwork/lnd/releases/download/v0.13.1-beta/lnd-linux-arm64-v0.13.1-beta.tar.gz +tar xf lnd-linux-arm64-v0.13.1-beta.tar.gz +mkdir /home/ec2-user/bin +cp lnd-linux-arm64-v0.13.1-beta/* /home/ec2-user/bin/ +rm -rf lnd-linux-arm64-v0.13.1-beta* + +mkdir /home/ec2-user/.lnd +PUBLIC_IPV4=$(curl http://169.254.169.254/latest/meta-data/public-ipv4/) +cat << EOF > /home/ec2-user/.lnd/lnd.conf +[Application Options] +# Allow push payments +accept-keysend=1 + +# Public network name +alias=CloudPleb + +# Allow gift routes +allow-circular-route=1 + +# Public hex color +color=#000000 + +# Reduce the cooperative close chain fee +coop-close-target-confs=1000 + +# Log levels +debuglevel=CNCT=debug,CRTR=debug,HSWC=debug,NTFN=debug,RPCS=debug + +# Public P2P IP (remove this if using Tor) +externalip=$PUBLIC_IPV4 + +# Mark unpayable, unpaid invoices as deleted +gc-canceled-invoices-on-startup=1 +gc-canceled-invoices-on-the-fly=1 + +# Avoid historical graph data sync +ignore-historical-gossip-filters=1 + +# Set the maximum amount of commit fees in a channel +max-channel-fee-allocation=1.0 + +# Set the max timeout blocks of a payment +max-cltv-expiry=5000 + +# Allow commitment fee to rise on anchor channels +max-commit-fee-rate-anchors=100 + +# Pending channel limit +maxpendingchannels=10 + +# Min inbound channel limit +#minchansize=5000000 + +listen=0.0.0.0:9735 + +# gRPC socket binding +rpclisten=0.0.0.0:10009 + +# Avoid slow startup time +sync-freelist=1 + +# Avoid high startup overhead +stagger-initial-reconnect=1 + +# Delete and recreate RPC TLS certificate when details change or cert expires +tlsautorefresh=1 + +# Do not include IPs in the RPC TLS certificate +tlsdisableautofill=1 + +[Bitcoin] +# Turn on Bitcoin mode +bitcoin.active=1 + +# Set the channel confs to wait for channels +bitcoin.defaultchanconfs=2 + +# Forward fee rate in parts per million +bitcoin.feerate=1000 + +# Set bitcoin.testnet=1 or bitcoin.mainnet=1 as appropriate +bitcoin.mainnet=1 + +# Set the lower bound for HTLCs +bitcoin.minhtlc=1 + +# Set backing node, bitcoin.node=neutrino or bitcoin.node=bitcoind +bitcoin.node=neutrino + +[neutrino] +# Mainnet addpeers +neutrino.addpeer=btcd-mainnet.lightning.computer +neutrino.addpeer=mainnet1-btcd.zaphq.io +neutrino.addpeer=mainnet2-btcd.zaphq.io +neutrino.addpeer=mainnet3-btcd.zaphq.io +neutrino.addpeer=mainnet4-btcd.zaphq.io + +# Testnet addpeers +neutrino.addpeer=btcd-testnet.ion.radar.tech +neutrino.addpeer=btcd-testnet.lightning.computer +neutrino.addpeer=lnd.bitrefill.com:18333 +neutrino.addpeer=faucet.lightning.community +neutrino.addpeer=testnet1-btcd.zaphq.io +neutrino.addpeer=testnet2-btcd.zaphq.io +neutrino.addpeer=testnet3-btcd.zaphq.io +neutrino.addpeer=testnet4-btcd.zaphq.io + +# Set fee data URL, change to btc-fee-estimates.json if mainnet +neutrino.feeurl=https://nodes.lightning.computer/fees/v1/btctestnet-fee-estimates.json + + +[protocol] +# Enable large channels support +protocol.wumbo-channels=1 + +[routerrpc] +# Set default chance of a hop success +routerrpc.apriorihopprob=0.5 + +# Start to ignore nodes if they return many failures (set to 1 to turn off) +routerrpc.aprioriweight=0.75 + +# Set minimum desired savings of trying a cheaper path +routerrpc.attemptcost=10 +routerrpc.attemptcostppm=10 + +# Set the number of historical routing records +routerrpc.maxmchistory=10000 + +# Set the min confidence in a path worth trying +routerrpc.minrtprob=0.005 + +# Set the time to forget past routing failures +routerrpc.penaltyhalflife=6h0m0s + +[routing] +# Set validation of channels off: only if using Neutrino +routing.assumechanvalid=1 + +EOF +openssl rand -hex 21 > /home/ec2-user/.lnd/wallet_password + +cat << EOF > /etc/systemd/system/lnd.service +[Service] +Environment=HOME=/home/ec2-user +ExecStart=/home/ec2-user/bin/lnd +ExecStop=/home/ec2-user/bin/lncli stop +Restart=always +RestartSec=30 +StandardOutput=null +StandardError=null +SyslogIdentifier=lnd +User=ec2-user +Group=ec2-user + +[Install] +WantedBy=multi-user.target + +EOF + +curl -sL https://rpm.nodesource.com/setup_14.x | sudo bash - +yum install -y nodejs +mkdir /home/ec2-user/.npm-global +npm config set prefix '/home/ec2-user/.npm-global' +echo 'PATH=/home/ec2-user/.npm-global/bin:$PATH' >> /home/ec2-user/.bashrc +npm install -g balanceofsatoshis + +chown -R ec2-user: /home/ec2-user/.lnd +chown -R ec2-user: /home/ec2-user/.npm-global +chown -R ec2-user: /home/ec2-user/bin + + +echo '*/5 * * * * ec2-user /home/ec2-user/.npm-global/bin/bos unlock /home/ec2-user/.lnd/wallet_password' >> /etc/crontab +systemctl start lnd.service \ No newline at end of file diff --git a/lib/lightningnode-stack.ts b/lib/lightningnode-stack.ts new file mode 100644 index 0000000..cf2fabd --- /dev/null +++ b/lib/lightningnode-stack.ts @@ -0,0 +1,66 @@ +import * as cdk from '@aws-cdk/core'; +import * as ec2 from '@aws-cdk/aws-ec2'; +import {Asset} from '@aws-cdk/aws-s3-assets'; +import { KeyPair } from 'cdk-ec2-key-pair'; +import * as path from 'path'; + + +export class LightningNode extends cdk.Stack { + get availabilityZones(): string[] { + return ['us-east-1b', 'us-east-1c', 'us-east-1d', 'us-east-1e', 'us-east-1f'] + } + constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + const vpc = new ec2.Vpc(this, "vpc", { + cidr: "10.0.0.0/16", + natGateways: 0, + maxAzs: 3, + }); + const key = new KeyPair(this, 'KeyPair', { + name: 'cdk-keypair', + description: 'Key Pair created with CDK Deployment', + }); + key.grantReadOnPublicKey + const securityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', { + vpc, + description: 'Allow SSH (TCP port 22) in', + allowAllOutbound: true + }); + securityGroup.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(22), 'Allow SSH Access') + const lightningSg = new ec2.SecurityGroup(this, "LightningSecurityGroup", { + vpc, + description: 'Allow lightning protocol (port 9735) traffic from the Internet', + allowAllOutbound: true + }); + lightningSg.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(9735)); + const setupScript = new Asset(this, "SetupScript", { + path: path.join(__dirname, 'configure-node.sh') + }); + const ami = new ec2.AmazonLinuxImage({ + generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2, + cpuType: ec2.AmazonLinuxCpuType.ARM_64 + }); + const instance = new ec2.Instance(this, "lightningNode", { + instanceType: new ec2.InstanceType("t4g.micro"), + vpc: vpc, + machineImage: ami, + vpcSubnets: {subnetType: ec2.SubnetType.PUBLIC}, + keyName: key.keyPairName, + }); + instance.addSecurityGroup(securityGroup); + instance.addSecurityGroup(lightningSg); + const localPath = instance.userData.addS3DownloadCommand({ + bucket:setupScript.bucket, + bucketKey:setupScript.s3ObjectKey, + }); + instance.userData.addExecuteFileCommand({ + filePath:localPath, + arguments: '--verbose -y' + }); + setupScript.grantRead( instance.role ); + new cdk.CfnOutput(this, 'IP Address', { value: instance.instancePublicIp }); + new cdk.CfnOutput(this, 'Key Name', { value: key.keyPairName }) + new cdk.CfnOutput(this, 'Download Key Command', { value: 'aws secretsmanager get-secret-value --secret-id ec2-ssh-key/cdk-keypair/private --query SecretString --output text > cdk-key.pem && chmod 400 cdk-key.pem' }) + new cdk.CfnOutput(this, 'ssh command', { value: 'ssh -i cdk-key.pem -o IdentitiesOnly=yes ec2-user@' + instance.instancePublicIp }) + } +} diff --git a/lib/thundercloud-stack.ts b/lib/thundercloud-stack.ts deleted file mode 100644 index 7c56b3c..0000000 --- a/lib/thundercloud-stack.ts +++ /dev/null @@ -1,9 +0,0 @@ -import * as cdk from '@aws-cdk/core'; - -export class ThundercloudStack extends cdk.Stack { - constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - // The code that defines your stack goes here - } -} diff --git a/package.json b/package.json index 2af3f60..65cadae 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,9 @@ }, "dependencies": { "@aws-cdk/core": "1.120.0", - "source-map-support": "^0.5.16" + "source-map-support": "^0.5.16", + "@aws-cdk/aws-ec2": "^1.120.0", + "@aws-cdk/aws-s3-assets": "^1.120.0", + "cdk-ec2-key-pair": "^2.2.1" } }