mirror of
https://github.com/aljazceru/cyphernode.git
synced 2026-02-02 11:14:20 +01:00
Docs and ability to run when not directly in dist folder...
This commit is contained in:
67
dist/setup.sh
vendored
67
dist/setup.sh
vendored
@@ -135,7 +135,6 @@ modify_owner() {
|
||||
}
|
||||
|
||||
configure() {
|
||||
local current_path="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
||||
## build setup docker image
|
||||
local recreate=""
|
||||
|
||||
@@ -188,9 +187,9 @@ configure() {
|
||||
--log-driver=none$pw_env \
|
||||
--network none \
|
||||
--rm$interactive cyphernode/cyphernodeconf:cyphernode-0.05 $user yo --no-insight cyphernode$gen_options $recreate
|
||||
if [[ -f exitStatus.sh ]]; then
|
||||
. ./exitStatus.sh
|
||||
rm ./exitStatus.sh
|
||||
if [[ -f $current_path/exitStatus.sh ]]; then
|
||||
. $current_path/exitStatus.sh
|
||||
rm $current_path/exitStatus.sh
|
||||
fi
|
||||
|
||||
if [[ ! $EXIT_STATUS == 0 ]]; then
|
||||
@@ -350,8 +349,6 @@ install_docker() {
|
||||
archpath="rpi"
|
||||
fi
|
||||
|
||||
local sourceDataPath=.
|
||||
|
||||
if [ ! -d $GATEKEEPER_DATAPATH ]; then
|
||||
step " [32mcreate[0m $GATEKEEPER_DATAPATH"
|
||||
sudo_if_required mkdir -p $GATEKEEPER_DATAPATH
|
||||
@@ -367,12 +364,12 @@ install_docker() {
|
||||
sudo_if_required mkdir $GATEKEEPER_DATAPATH/private > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
copy_file $sourceDataPath/gatekeeper/api.properties $GATEKEEPER_DATAPATH/api.properties 1 $SUDO_REQUIRED
|
||||
copy_file $sourceDataPath/gatekeeper/keys.properties $GATEKEEPER_DATAPATH/keys.properties 1 $SUDO_REQUIRED
|
||||
copy_file $sourceDataPath/config.7z $GATEKEEPER_DATAPATH/config.7z 1 $SUDO_REQUIRED
|
||||
copy_file $sourceDataPath/client.7z $GATEKEEPER_DATAPATH/client.7z 1 $SUDO_REQUIRED
|
||||
copy_file $sourceDataPath/gatekeeper/cert.pem $GATEKEEPER_DATAPATH/certs/cert.pem 1 $SUDO_REQUIRED
|
||||
copy_file $sourceDataPath/gatekeeper/key.pem $GATEKEEPER_DATAPATH/private/key.pem 1 $SUDO_REQUIRED
|
||||
copy_file $current_path/gatekeeper/api.properties $GATEKEEPER_DATAPATH/api.properties 1 $SUDO_REQUIRED
|
||||
copy_file $current_path/gatekeeper/keys.properties $GATEKEEPER_DATAPATH/keys.properties 1 $SUDO_REQUIRED
|
||||
copy_file $current_path/config.7z $GATEKEEPER_DATAPATH/config.7z 1 $SUDO_REQUIRED
|
||||
copy_file $current_path/client.7z $GATEKEEPER_DATAPATH/client.7z 1 $SUDO_REQUIRED
|
||||
copy_file $current_path/gatekeeper/cert.pem $GATEKEEPER_DATAPATH/certs/cert.pem 1 $SUDO_REQUIRED
|
||||
copy_file $current_path/gatekeeper/key.pem $GATEKEEPER_DATAPATH/private/key.pem 1 $SUDO_REQUIRED
|
||||
fi
|
||||
|
||||
if [ ! -d $PROXY_DATAPATH ]; then
|
||||
@@ -381,7 +378,7 @@ install_docker() {
|
||||
next
|
||||
fi
|
||||
|
||||
copy_file $sourceDataPath/installer/config.sh $PROXY_DATAPATH/config.sh 1 $SUDO_REQUIRED
|
||||
copy_file $current_path/installer/config.sh $PROXY_DATAPATH/config.sh 1 $SUDO_REQUIRED
|
||||
|
||||
if [[ $BITCOIN_INTERNAL == true ]]; then
|
||||
if [ ! -d $BITCOIN_DATAPATH ]; then
|
||||
@@ -391,18 +388,18 @@ install_docker() {
|
||||
fi
|
||||
if [ -d $BITCOIN_DATAPATH ]; then
|
||||
|
||||
local cmpStatus=$(compare_bitcoinconf $sourceDataPath/bitcoin/bitcoin.conf $BITCOIN_DATAPATH/bitcoin.conf)
|
||||
local cmpStatus=$(compare_bitcoinconf $current_path/bitcoin/bitcoin.conf $BITCOIN_DATAPATH/bitcoin.conf)
|
||||
|
||||
if [[ $cmpStatus == 'dataloss' ]]; then
|
||||
if [[ $ALWAYSYES == 1 ]]; then
|
||||
copy_file $sourceDataPath/bitcoin/bitcoin.conf $BITCOIN_DATAPATH/bitcoin.conf 1 $SUDO_REQUIRED
|
||||
copy_file $current_path/bitcoin/bitcoin.conf $BITCOIN_DATAPATH/bitcoin.conf 1 $SUDO_REQUIRED
|
||||
else
|
||||
while true; do
|
||||
echo " [31mReally copy bitcoin.conf with pruning option?[0m"
|
||||
read -p " [31mThis will discard some blockchain data. (yn)[0m " yn
|
||||
case $yn in
|
||||
[Yy]* ) copy_file $sourceDataPath/bitcoin/bitcoin.conf $BITCOIN_DATAPATH/bitcoin.conf 1 $SUDO_REQUIRED; break;;
|
||||
[Nn]* ) copy_file $sourceDataPath/bitcoin/bitcoin.conf $BITCOIN_DATAPATH/bitcoin.conf.cyphernode 0 $SUDO_REQUIRED
|
||||
[Yy]* ) copy_file $current_path/bitcoin/bitcoin.conf $BITCOIN_DATAPATH/bitcoin.conf 1 $SUDO_REQUIRED; break;;
|
||||
[Nn]* ) copy_file $current_path/bitcoin/bitcoin.conf $BITCOIN_DATAPATH/bitcoin.conf.cyphernode 0 $SUDO_REQUIRED
|
||||
echo " [31mYour cyphernode installation is most likely broken.[0m"
|
||||
echo " [31mPlease check bitcoin.conf.cyphernode on how to repair it manually.[0m";
|
||||
break;;
|
||||
@@ -411,7 +408,7 @@ install_docker() {
|
||||
done
|
||||
fi
|
||||
elif [[ $cmpStatus == 'incompatible' ]]; then
|
||||
copy_file $sourceDataPath/bitcoin/bitcoin.conf $BITCOIN_DATAPATH/bitcoin.conf.cyphernode 0 $SUDO_REQUIRED
|
||||
copy_file $current_path/bitcoin/bitcoin.conf $BITCOIN_DATAPATH/bitcoin.conf.cyphernode 0 $SUDO_REQUIRED
|
||||
echo " [31mBlockchain data is not compatible, due to misconfigured nets.[0m"
|
||||
echo " [31mYour cyphernode installation is most likely broken.[0m"
|
||||
echo " [31mPlease check bitcoin.conf.cyphernode on how to repair it manually.[0m"
|
||||
@@ -419,7 +416,7 @@ install_docker() {
|
||||
if [[ $cmpStatus == 'reindex' ]]; then
|
||||
echo " [33mWarning[0m Reindexing will take some time."
|
||||
fi
|
||||
copy_file $sourceDataPath/bitcoin/bitcoin.conf $BITCOIN_DATAPATH/bitcoin.conf 1 $SUDO_REQUIRED
|
||||
copy_file $current_path/bitcoin/bitcoin.conf $BITCOIN_DATAPATH/bitcoin.conf 1 $SUDO_REQUIRED
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
@@ -436,8 +433,8 @@ install_docker() {
|
||||
next
|
||||
fi
|
||||
if [ -d $LIGHTNING_DATAPATH ]; then
|
||||
copy_file $sourceDataPath/lightning/c-lightning/config $LIGHTNING_DATAPATH/config 1 $SUDO_REQUIRED
|
||||
copy_file $sourceDataPath/lightning/c-lightning/bitcoin.conf $LIGHTNING_DATAPATH/bitcoin.conf 1 $SUDO_REQUIRED
|
||||
copy_file $current_path/lightning/c-lightning/config $LIGHTNING_DATAPATH/config 1 $SUDO_REQUIRED
|
||||
copy_file $current_path/lightning/c-lightning/bitcoin.conf $LIGHTNING_DATAPATH/bitcoin.conf 1 $SUDO_REQUIRED
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
@@ -485,26 +482,26 @@ install_docker() {
|
||||
fi
|
||||
fi
|
||||
|
||||
copy_file $sourceDataPath/installer/docker/docker-compose.yaml docker-compose.yaml
|
||||
copy_file $sourceDataPath/installer/testfeatures.sh testfeatures.sh 0
|
||||
copy_file $sourceDataPath/installer/start.sh start.sh 0
|
||||
copy_file $sourceDataPath/installer/stop.sh stop.sh 0
|
||||
copy_file $current_path/installer/docker/docker-compose.yaml $current_path/docker-compose.yaml
|
||||
copy_file $current_path/installer/testfeatures.sh $current_path/testfeatures.sh 0
|
||||
copy_file $current_path/installer/start.sh $current_path/start.sh 0
|
||||
copy_file $current_path/installer/stop.sh $current_path/stop.sh 0
|
||||
|
||||
if [[ ! -x start.sh ]]; then
|
||||
if [[ ! -x $current_path/start.sh ]]; then
|
||||
step " [32mmake[0m start.sh executable"
|
||||
try chmod +x start.sh
|
||||
try chmod +x $current_path/start.sh
|
||||
next
|
||||
fi
|
||||
|
||||
if [[ ! -x stop.sh ]]; then
|
||||
if [[ ! -x $current_path/stop.sh ]]; then
|
||||
step " [32mmake[0m stop.sh executable"
|
||||
try chmod +x stop.sh
|
||||
try chmod +x $current_path/stop.sh
|
||||
next
|
||||
fi
|
||||
|
||||
if [[ ! -x testfeatures.sh ]]; then
|
||||
if [[ ! -x $current_path/testfeatures.sh ]]; then
|
||||
step " [32mmake[0m testfeatures.sh executable"
|
||||
try chmod +x testfeatures.sh
|
||||
try chmod +x $current_path/testfeatures.sh
|
||||
next
|
||||
fi
|
||||
}
|
||||
@@ -627,6 +624,8 @@ function ctrl_c() {
|
||||
exit
|
||||
}
|
||||
|
||||
export current_path="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
||||
|
||||
while getopts ":cirhys" opt; do
|
||||
case $opt in
|
||||
r)
|
||||
@@ -667,8 +666,8 @@ if [[ $CONFIGURE == 1 ]]; then
|
||||
configure $RECREATE
|
||||
fi
|
||||
|
||||
if [[ -f installer/config.sh ]]; then
|
||||
. installer/config.sh
|
||||
if [[ -f $current_path/installer/config.sh ]]; then
|
||||
. $current_path/installer/config.sh
|
||||
fi
|
||||
|
||||
if [[ $CLEANUP == 'true' && $(docker image ls | grep cyphernodeconf) =~ cyphernodeconf ]]; then
|
||||
@@ -686,7 +685,7 @@ if [[ $INSTALL == 1 ]]; then
|
||||
fi
|
||||
|
||||
if [[ $AUTOSTART == 1 ]]; then
|
||||
exec ./start.sh
|
||||
exec $current_path/start.sh
|
||||
else
|
||||
cowsay
|
||||
fi
|
||||
|
||||
2
dist/sr.sh
vendored
2
dist/sr.sh
vendored
@@ -1 +1 @@
|
||||
curl -fsSL https://raw.githubusercontent.com/schulterklopfer/cyphernode/features/install/dist/setup.sh -o setup_cyphernode.sh && chmod +x setup_cyphernode.sh && ./setup_cyphernode.sh
|
||||
curl -fsSL https://raw.githubusercontent.com/SatoshiPortal/cyphernode/master/dist/setup.sh -o setup_cyphernode.sh && chmod +x setup_cyphernode.sh && ./setup_cyphernode.sh
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# This README file can be used if you want to install manually. This is the old documentation before there was the installer.
|
||||
|
||||
# Here are the exact steps I did to install cyphernode on a debian server running on x86 arch, as user debian.
|
||||
|
||||
## Update server and install git
|
||||
|
||||
142
doc/INSTALL-MANUALLY.md
Normal file
142
doc/INSTALL-MANUALLY.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# This README file can be used if you want to install manually. This is the old documentation before there was the installer.
|
||||
|
||||
# Cyphernode
|
||||
|
||||
Indirection layer between client and Bitcoin-related services.
|
||||
|
||||
Here's the plan:
|
||||
|
||||
- The containers are not publicly exposing ports.
|
||||
- Everything is accessible exclusively within the encrypted overlay network.
|
||||
- If your system is distributed:
|
||||
- ...should be doubly encrypted by an OpenVPN tunnel
|
||||
- ...the hosts should be secured and the VPN tunnel should have limited scope by iptables rules on each host.
|
||||
- We can have different Bitcoin Nodes for watching and spending, giving the flexibility to have different security models one each.
|
||||
- Only the Proxy has Bitcoin Node RPC credentials.
|
||||
- The Proxy is exclusively accessible by the Overlay network's containers.
|
||||
- To manually manage the Proxy (and have access to it), one has to gain access to the Docker host servers as a docker user.
|
||||
- **Coming soon**: added security to use the spending features of the Proxy with Trezor and Coldcard.
|
||||
|
||||
## See [Step-by-step detailed instructions](INSTALL-MANUAL-STEPS.md) for real-world copy-paste standard install instructions
|
||||
|
||||
## Setting up
|
||||
|
||||
Default setup assumes your Bitcoin Node is already running somewhere. The reason is that it takes a lot of disk space and often already exists in your infrastructure, why not reusing it. After all, full blockchain sync takes a while.
|
||||
|
||||
You could also just uncomment it in the docker-compose file. If you run it in pruned mode, say so in config.properties. The computefees feature won't work in pruned mode.
|
||||
|
||||
### Set the swarm
|
||||
(10.8.0.2 is the host's VPN IP address)
|
||||
|
||||
```shell
|
||||
debian@dev:~/dev/Cyphernode$ docker swarm init --task-history-limit 1 --advertise-addr 10.8.0.2
|
||||
Swarm initialized: current node (hufy324d291dyakizsuvjd0uw) is now a manager.
|
||||
|
||||
To add a worker to this swarm, run the following command:
|
||||
|
||||
docker swarm join --token SWMTKN-1-2pxouynn9g8si42e8g9ujwy0v9po45axx367fy0fkjhzo3l1z8-75nirjfkobl7htvpfh986pyz3 10.8.0.2:2377
|
||||
|
||||
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
|
||||
```
|
||||
|
||||
### Create the Overlay Network and make sure your app joins it!
|
||||
(if your app is not a Docker container, you will have to expose Cyphernode's port and secure it! In that case, use a reverse proxy with TLS)
|
||||
|
||||
```shell
|
||||
debian@dev:~/dev/Cyphernode$ docker network create --driver=overlay --attachable --opt encrypted cyphernodenet
|
||||
debian@dev:~/dev/Cyphernode$ docker network connect cyphernodenet yourappcontainer
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
```shell
|
||||
debian@dev:~/dev/Cyphernode$ vi proxy_docker/env.properties
|
||||
debian@dev:~/dev/Cyphernode$ vi cron_docker/env.properties
|
||||
debian@dev:~/dev/Cyphernode$ vi pycoin_docker/env.properties
|
||||
debian@dev:~/dev/Cyphernode$ vi api_auth_docker/env.properties
|
||||
```
|
||||
|
||||
### Build cron image
|
||||
|
||||
[See how to build proxycron image](../cron_docker)
|
||||
|
||||
### Build btcproxy image
|
||||
|
||||
[See how to build btcproxy image](../proxy_docker)
|
||||
|
||||
### Build pycoin image
|
||||
|
||||
[See how to build pycoin image](../pycoin_docker)
|
||||
|
||||
### Build btcnode image
|
||||
|
||||
[See how to build btcnode image](https://github.com/SatoshiPortal/dockers/tree/master/x86_64/bitcoin-core)
|
||||
|
||||
### Build clightning image
|
||||
|
||||
[See how to build clightning image](https://github.com/SatoshiPortal/dockers/tree/master/x86_64/LN/c-lightning)
|
||||
|
||||
### Build the authenticated HTTP API image
|
||||
|
||||
[See how to build authapi image](../api_auth_docker)
|
||||
|
||||
### Deploy
|
||||
|
||||
**Edit docker-compose.yml to specify special deployment constraints or if you want to run the Bitcoin node on the same machine: uncomment corresponding lines.**
|
||||
|
||||
```shell
|
||||
debian@dev:~/dev/Cyphernode$ USER=`id -u cyphernode`:`id -g cyphernode` docker stack deploy --compose-file docker-compose.yml cyphernodestack
|
||||
Creating service cyphernodestack_authapi
|
||||
Creating service cyphernodestack_cyphernode
|
||||
Creating service cyphernodestack_proxycronnode
|
||||
Creating service cyphernodestack_pycoinnode
|
||||
Creating service cyphernodestack_clightningnode
|
||||
```
|
||||
|
||||
## Off-site Bitcoin Node
|
||||
|
||||
This section is useful if you already have a Bitcoin Core node running and you want to use it in Cyphernode. In that case, please comment out the btcnode section from docker-compose.yml.
|
||||
|
||||
### Join swarm created on Cyphernode server
|
||||
|
||||
```shell
|
||||
pi@SP-BTC01:~ $ docker swarm join --token SWMTKN-1-2pxouynn9g8si42e8g9ujwy0v9po45axx367fy0fkjhzo3l1z8-75nirjfkobl7htvpfh986pyz3 10.8.0.2:2377
|
||||
```
|
||||
|
||||
### Build node container image
|
||||
|
||||
[See how to build Bitcoin Node image](https://github.com/SatoshiPortal/dockers/tree/master/rpi/bitcoin-core)
|
||||
|
||||
### Connect already-running node
|
||||
|
||||
```shell
|
||||
pi@SP-BTC01:~ $ docker network connect cyphernodenet btcnode
|
||||
```
|
||||
|
||||
## Test deployment from outside of the Swarm
|
||||
|
||||
```shell
|
||||
id="001";h64=$(echo -n "{\"alg\":\"HS256\",\"typ\":\"JWT\"}" | base64);p64=$(echo -n "{\"id\":\"$id\",\"exp\":$((`date +"%s"`+10))}" | base64);k="2df1eeea370eacdc5cf7e96c2d82140d1568079a5d4d87006ec8718a98883b36";s=$(echo -n "$h64.$p64" | openssl dgst -hmac "$k" -sha256 -r | cut -sd ' ' -f1);token="$h64.$p64.$s";curl -v -H "Authorization: Bearer $token" -k https://127.0.0.1/getbestblockhash
|
||||
id="003";h64=$(echo -n "{\"alg\":\"HS256\",\"typ\":\"JWT\"}" | base64);p64=$(echo -n "{\"id\":\"$id\",\"exp\":$((`date +"%s"`+10))}" | base64);k="b9b8d527a1a27af2ad1697db3521f883760c342fc386dbc42c4efbb1a4d5e0af";s=$(echo -n "$h64.$p64" | openssl dgst -hmac "$k" -sha256 -r | cut -sd ' ' -f1);token="$h64.$p64.$s";curl -v -H "Authorization: Bearer $token" -k https://127.0.0.1/getbalance
|
||||
id="003";h64=$(echo -n "{\"alg\":\"HS256\",\"typ\":\"JWT\"}" | base64);p64=$(echo -n "{\"id\":\"$id\",\"exp\":$((`date +"%s"`+10))}" | base64);k="b9b8d527a1a27af2ad1697db3521f883760c342fc386dbc42c4efbb1a4d5e0af";s=$(echo -n "$h64.$p64" | openssl dgst -hmac "$k" -sha256 -r | cut -sd ' ' -f1);token="$h64.$p64.$s";curl -v -H "Content-Type: application/json" -d '{"hash":"123","callbackUrl":"http://callback"}' -H "Authorization: Bearer $token" -k https://127.0.0.1/ots_stamp
|
||||
```
|
||||
|
||||
If you need the authorization header to copy/paste in another tool:
|
||||
|
||||
```shell
|
||||
id="003";h64=$(echo -n "{\"alg\":\"HS256\",\"typ\":\"JWT\"}" | base64);p64=$(echo -n "{\"id\":\"$id\",\"exp\":$((`date +"%s"`+60))}" | base64);k="b9b8d527a1a27af2ad1697db3521f883760c342fc386dbc42c4efbb1a4d5e0af";s=$(echo -n "$h64.$p64" | openssl dgst -hmac "$k" -sha256 -r | cut -sd ' ' -f1);token="$h64.$p64.$s";echo "Bearer $token"
|
||||
```
|
||||
|
||||
## Test deployment from any host of the swarm
|
||||
|
||||
```shell
|
||||
echo "GET /getbestblockinfo" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -
|
||||
echo "GET /getbalance" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -
|
||||
echo "GET /getbestblockhash" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -
|
||||
echo "GET /getblockinfo/00000000a64e0d1ae0c39166f4e8717a672daf3d61bf7bbb41b0f487fcae74d2" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -
|
||||
curl -v -H "Content-Type: application/json" -d '{"address":"2MsWyaQ8APbnqasFpWopqUKqsdpiVY3EwLE","amount":0.2}' proxy:8888/spend
|
||||
echo "GET /ln_getinfo" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -
|
||||
echo "GET /ln_newaddr" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -
|
||||
curl -v -H "Content-Type: application/json" -d '{"msatoshi":10000,"label":"koNCcrSvhX3dmyFhW","description":"Bylls order #10649","expiry":900}' proxy:8888/ln_create_invoice
|
||||
curl -v -H "Content-Type: application/json" -d '{"bolt11":"lntb1pdca82tpp5gv8mn5jqlj6xztpnt4r472zcyrwf3y2c3cvm4uzg2gqcnj90f83qdp2gf5hgcm0d9hzqnm4w3kx2apqdaexgetjyq3nwvpcxgcqp2g3d86wwdfvyxcz7kce7d3n26d2rw3wf5tzpm2m5fl2z3mm8msa3xk8nv2y32gmzlhwjved980mcmkgq83u9wafq9n4w28amnmwzujgqpmapcr3","msatoshi":10000,"description":"Bitcoin Outlet order #7082"}' proxy:8888/ln_pay
|
||||
```
|
||||
123
doc/INSTALL.md
123
doc/INSTALL.md
@@ -1,117 +1,34 @@
|
||||
# Cyphernode
|
||||
|
||||
Indirection layer between client and Bitcoin-related services.
|
||||
## Setting Up
|
||||
|
||||
Here's the plan:
|
||||
### Installer
|
||||
|
||||
- The containers are not publicly exposing ports.
|
||||
- Everything is accessible exclusively within the encrypted overlay network.
|
||||
- If your system is distributed:
|
||||
- ...should be doubly encrypted by an OpenVPN tunnel
|
||||
- ...the hosts should be secured and the VPN tunnel should have limited scope by iptables rules on each host.
|
||||
- We can have different Bitcoin Nodes for watching and spending, giving the flexibility to have different security models one each.
|
||||
- Only the Proxy has Bitcoin Node RPC credentials.
|
||||
- The Proxy is exclusively accessible by the Overlay network's containers.
|
||||
- To manually manage the Proxy (and have access to it), one has to gain access to the Docker host servers as a docker user.
|
||||
- **Coming soon**: added security to use the spending features of the Proxy with Trezor and Coldcard.
|
||||
We are providing an installer to help you setup Cyphernode. All the Docker images used by Cyphernode have been prebuilt for x86 and ARM (RPi) architectures and are hosted on the Docker hub public registry, Cyphernode repository (https://hub.docker.com/u/cyphernode/).
|
||||
|
||||
## See [Step-by-step detailed instructions](INSTALL-MANUAL-STEPS.md) for real-world copy-paste standard install instructions
|
||||
|
||||
## Setting up
|
||||
|
||||
Default setup assumes your Bitcoin Node is already running somewhere. The reason is that it takes a lot of disk space and often already exists in your infrastructure, why not reusing it. After all, full blockchain sync takes a while.
|
||||
|
||||
You could also just uncomment it in the docker-compose file. If you run it in pruned mode, say so in config.properties. The computefees feature won't work in pruned mode.
|
||||
|
||||
### Set the swarm
|
||||
(10.8.0.2 is the host's VPN IP address)
|
||||
You can clone the git repository and install:
|
||||
|
||||
```shell
|
||||
debian@dev:~/dev/Cyphernode$ docker swarm init --task-history-limit 1 --advertise-addr 10.8.0.2
|
||||
Swarm initialized: current node (hufy324d291dyakizsuvjd0uw) is now a manager.
|
||||
|
||||
To add a worker to this swarm, run the following command:
|
||||
|
||||
docker swarm join --token SWMTKN-1-2pxouynn9g8si42e8g9ujwy0v9po45axx367fy0fkjhzo3l1z8-75nirjfkobl7htvpfh986pyz3 10.8.0.2:2377
|
||||
|
||||
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
|
||||
git clone https://github.com/SatoshiPortal/cyphernode.git
|
||||
cd cyphernode/dist
|
||||
./setup.sh
|
||||
```
|
||||
|
||||
### Create the Overlay Network and make sure your app joins it!
|
||||
(if your app is not a Docker container, you will have to expose Cyphernode's port and secure it! In that case, use a reverse proxy with TLS)
|
||||
Or you can simply run this magic command to start setup and installation:
|
||||
|
||||
```shell
|
||||
debian@dev:~/dev/Cyphernode$ docker network create --driver=overlay --attachable --opt encrypted cyphernodenet
|
||||
debian@dev:~/dev/Cyphernode$ docker network connect cyphernodenet yourappcontainer
|
||||
curl -fsSL https://raw.githubusercontent.com/SatoshiPortal/cyphernode/master/dist/setup.sh -o setup_cyphernode.sh && chmod +x setup_cyphernode.sh && ./setup_cyphernode.sh
|
||||
```
|
||||
|
||||
### Configuration
|
||||
## Manually test your installation through the Gatekeeper
|
||||
|
||||
If you need the authorization header to copy/paste in another tool, put your API ID (id=) and API key (k=) in the following command:
|
||||
|
||||
```shell
|
||||
debian@dev:~/dev/Cyphernode$ vi proxy_docker/env.properties
|
||||
debian@dev:~/dev/Cyphernode$ vi cron_docker/env.properties
|
||||
debian@dev:~/dev/Cyphernode$ vi pycoin_docker/env.properties
|
||||
debian@dev:~/dev/Cyphernode$ vi api_auth_docker/env.properties
|
||||
id="003";h64=$(echo -n "{\"alg\":\"HS256\",\"typ\":\"JWT\"}" | base64);p64=$(echo -n "{\"id\":\"$id\",\"exp\":$((`date +"%s"`+60))}" | base64);k="b9b8d527a1a27af2ad1697db3521f883760c342fc386dbc42c4efbb1a4d5e0af";s=$(echo -n "$h64.$p64" | openssl dgst -hmac "$k" -sha256 -r | cut -sd ' ' -f1);token="$h64.$p64.$s";echo "Bearer $token"
|
||||
```
|
||||
|
||||
### Build cron image
|
||||
|
||||
[See how to build proxycron image](../cron_docker)
|
||||
|
||||
### Build btcproxy image
|
||||
|
||||
[See how to build btcproxy image](../proxy_docker)
|
||||
|
||||
### Build pycoin image
|
||||
|
||||
[See how to build pycoin image](../pycoin_docker)
|
||||
|
||||
### Build btcnode image
|
||||
|
||||
[See how to build btcnode image](https://github.com/SatoshiPortal/dockers/tree/master/x86_64/bitcoin-core)
|
||||
|
||||
### Build clightning image
|
||||
|
||||
[See how to build clightning image](https://github.com/SatoshiPortal/dockers/tree/master/x86_64/LN/c-lightning)
|
||||
|
||||
### Build the authenticated HTTP API image
|
||||
|
||||
[See how to build authapi image](../api_auth_docker)
|
||||
|
||||
### Deploy
|
||||
|
||||
**Edit docker-compose.yml to specify special deployment constraints or if you want to run the Bitcoin node on the same machine: uncomment corresponding lines.**
|
||||
|
||||
```shell
|
||||
debian@dev:~/dev/Cyphernode$ USER=`id -u cyphernode`:`id -g cyphernode` docker stack deploy --compose-file docker-compose.yml cyphernodestack
|
||||
Creating service cyphernodestack_authapi
|
||||
Creating service cyphernodestack_cyphernode
|
||||
Creating service cyphernodestack_proxycronnode
|
||||
Creating service cyphernodestack_pycoinnode
|
||||
Creating service cyphernodestack_clightningnode
|
||||
```
|
||||
|
||||
## Off-site Bitcoin Node
|
||||
|
||||
This section is useful if you already have a Bitcoin Core node running and you want to use it in Cyphernode. In that case, please comment out the btcnode section from docker-compose.yml.
|
||||
|
||||
### Join swarm created on Cyphernode server
|
||||
|
||||
```shell
|
||||
pi@SP-BTC01:~ $ docker swarm join --token SWMTKN-1-2pxouynn9g8si42e8g9ujwy0v9po45axx367fy0fkjhzo3l1z8-75nirjfkobl7htvpfh986pyz3 10.8.0.2:2377
|
||||
```
|
||||
|
||||
### Build node container image
|
||||
|
||||
[See how to build Bitcoin Node image](https://github.com/SatoshiPortal/dockers/tree/master/rpi/bitcoin-core)
|
||||
|
||||
### Connect already-running node
|
||||
|
||||
```shell
|
||||
pi@SP-BTC01:~ $ docker network connect cyphernodenet btcnode
|
||||
```
|
||||
|
||||
## Test deployment from outside of the Swarm
|
||||
Directly using curl on command line, put your API ID (id=) and API key (k=) in the following commands:
|
||||
|
||||
```shell
|
||||
id="001";h64=$(echo -n "{\"alg\":\"HS256\",\"typ\":\"JWT\"}" | base64);p64=$(echo -n "{\"id\":\"$id\",\"exp\":$((`date +"%s"`+10))}" | base64);k="2df1eeea370eacdc5cf7e96c2d82140d1568079a5d4d87006ec8718a98883b36";s=$(echo -n "$h64.$p64" | openssl dgst -hmac "$k" -sha256 -r | cut -sd ' ' -f1);token="$h64.$p64.$s";curl -v -H "Authorization: Bearer $token" -k https://127.0.0.1/getbestblockhash
|
||||
@@ -119,22 +36,12 @@ id="003";h64=$(echo -n "{\"alg\":\"HS256\",\"typ\":\"JWT\"}" | base64);p64=$(ech
|
||||
id="003";h64=$(echo -n "{\"alg\":\"HS256\",\"typ\":\"JWT\"}" | base64);p64=$(echo -n "{\"id\":\"$id\",\"exp\":$((`date +"%s"`+10))}" | base64);k="b9b8d527a1a27af2ad1697db3521f883760c342fc386dbc42c4efbb1a4d5e0af";s=$(echo -n "$h64.$p64" | openssl dgst -hmac "$k" -sha256 -r | cut -sd ' ' -f1);token="$h64.$p64.$s";curl -v -H "Content-Type: application/json" -d '{"hash":"123","callbackUrl":"http://callback"}' -H "Authorization: Bearer $token" -k https://127.0.0.1/ots_stamp
|
||||
```
|
||||
|
||||
If you need the authorization header to copy/paste in another tool:
|
||||
|
||||
```shell
|
||||
id="003";h64=$(echo -n "{\"alg\":\"HS256\",\"typ\":\"JWT\"}" | base64);p64=$(echo -n "{\"id\":\"$id\",\"exp\":$((`date +"%s"`+60))}" | base64);k="b9b8d527a1a27af2ad1697db3521f883760c342fc386dbc42c4efbb1a4d5e0af";s=$(echo -n "$h64.$p64" | openssl dgst -hmac "$k" -sha256 -r | cut -sd ' ' -f1);token="$h64.$p64.$s";echo "Bearer $token"
|
||||
```
|
||||
|
||||
## Test deployment from any host of the swarm
|
||||
## Manually test your installation directly on the Proxy:
|
||||
|
||||
```shell
|
||||
echo "GET /getbestblockinfo" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -
|
||||
echo "GET /getbalance" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -
|
||||
echo "GET /getbestblockhash" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -
|
||||
echo "GET /getblockinfo/00000000a64e0d1ae0c39166f4e8717a672daf3d61bf7bbb41b0f487fcae74d2" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -
|
||||
curl -v -H "Content-Type: application/json" -d '{"address":"2MsWyaQ8APbnqasFpWopqUKqsdpiVY3EwLE","amount":0.2}' proxy:8888/spend
|
||||
echo "GET /ln_getinfo" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -
|
||||
echo "GET /ln_newaddr" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -
|
||||
curl -v -H "Content-Type: application/json" -d '{"msatoshi":10000,"label":"koNCcrSvhX3dmyFhW","description":"Bylls order #10649","expiry":900}' proxy:8888/ln_create_invoice
|
||||
curl -v -H "Content-Type: application/json" -d '{"bolt11":"lntb1pdca82tpp5gv8mn5jqlj6xztpnt4r472zcyrwf3y2c3cvm4uzg2gqcnj90f83qdp2gf5hgcm0d9hzqnm4w3kx2apqdaexgetjyq3nwvpcxgcqp2g3d86wwdfvyxcz7kce7d3n26d2rw3wf5tzpm2m5fl2z3mm8msa3xk8nv2y32gmzlhwjved980mcmkgq83u9wafq9n4w28amnmwzujgqpmapcr3","msatoshi":10000,"description":"Bitcoin Outlet order #7082"}' proxy:8888/ln_pay
|
||||
```
|
||||
|
||||
102
doc/README.md
Normal file
102
doc/README.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Cyphernode
|
||||
|
||||
Indirection layer (API) between your applications and Bitcoin-related services.
|
||||
|
||||
Your application <-----> Cyphernode
|
||||
|
||||
Cyphernode is:
|
||||
|
||||
Gatekeeper (TLS, JWT) <-----> Proxy (Cyphernode Core) <-----> Feature Containers
|
||||
|
||||
- By default, the only exposed (published) port is 443 (HTTPS) on the Gatekeeper.
|
||||
- By default, everything else is accessible exclusively within the encrypted overlay network.
|
||||
- If your system is distributed (customized Cyphernode setup), the overlay network...
|
||||
- ...should be doubly encrypted with a VPN or SSH tunnel
|
||||
- ...the hosts should be secured and the VPN/SSH tunnel should have limited scope by iptables rules on each host.
|
||||
- We can have different Bitcoin Nodes for watching and spending, giving the flexibility to have different security models one each.
|
||||
- Only the Proxy has Bitcoin Node RPC credentials.
|
||||
- To manually manage the Proxy (and have access to it), one has to gain access to the Docker host servers as a docker user.
|
||||
|
||||
## Setting Up
|
||||
|
||||
### Installer
|
||||
|
||||
We are providing an installer to help you setup Cyphernode.
|
||||
|
||||
#### See [Instructions for installation](INSTALL.md) for automatic install instructions
|
||||
|
||||
All the Docker images used by Cyphernode have been prebuilt for x86 and ARM (RPi) architectures and are hosted on the Docker hub public registry, Cyphernode repository (https://hub.docker.com/u/cyphernode/).
|
||||
|
||||
### Build from sources
|
||||
|
||||
However, it is possible for you to build from sources. In that case, please refer to the files INSTALL-MANUALLY.md and INSTALL-MANUAL-STEPS.md.
|
||||
|
||||
#### See [Instructions for manual installation](INSTALL-MANUALLY.md) for manual build and install instructions
|
||||
#### See [Step-by-step detailed instructions](INSTALL-MANUAL-STEPS.md) for real-world copy-paste standard install instructions
|
||||
|
||||
# For Your Information
|
||||
|
||||
Current components in Cyphernode:
|
||||
|
||||
- Gatekeeper: front door where all requests hit Cyphernode. Takes care of: TLS, authentication and authorization.
|
||||
- Proxy: request handler. Well dispatch authenticated and authorized requests to the right component. Use a SQLite3 database for its tasks.
|
||||
- Proxy Cron: scheduler. Can call the proxy on regular interval for asynchronous tasks like payment notifications on watches, callbacks when OTS files are ready, etc.
|
||||
- Pycoin: Bitcoin keys and addresses tool. Used by Cyphernode to derive addresses from an xPub and a derivation path.
|
||||
- Bitcoin: Bitcoin Core node. Cyphernode uses a watching wallet for watchers (no funds) and a spending wallet for spending. Mandatory component, but optionally part of Cyphernode installation, as we can use an already running Bitcoin Core node.
|
||||
- Lightning: optional. C-Lightning node. The LN node will use the Bitcoin node for its tasks.
|
||||
- OTSclient: optional. Used to stamp hashes on the Bitcoin blockchain.
|
||||
|
||||
Future components:
|
||||
|
||||
- Trezor-connect: use a Trezor to authenticate. Will be used to log into control panel (see next point) and other.
|
||||
- Control Panel: web control panel, with different functionalities depending on user's group: admin, spender, watcher.
|
||||
- Grafana: displays stats graphics on Cyphernode use and load.
|
||||
- PGP: signs anything with your PGP key.
|
||||
- PSBT: sign transactions using a Coldcard.
|
||||
- Electrum (Personal) Server: would be part of the installation for your convenience, but not really used by Cyphernode.
|
||||
|
||||
## Bitcoin Core Node
|
||||
|
||||
If you decide to have a prune Bitcoin Core node, the fee calculation on incoming transactions won't work. We can't compute the fees on someone else's transactions without having the whole indexed blockchain.
|
||||
|
||||
## Lightning Network
|
||||
|
||||
Currently, the LN functionalities of Cyphernode are very limited. Maybe even hard to use. You can:
|
||||
|
||||
- Get information on your LN node: ln_getinfo
|
||||
- Get a Bitcoin address where to send your funds to be used by your LN node: ln_newaddr
|
||||
- Create an invoice, so people can send you payment; the burden of creating a channel/route to you is on the payer: ln_create_invoice
|
||||
- Pay an invoice. You have to have the invoice and your LN node must already be connected to the network: ln_pay
|
||||
|
||||
Basic and crucial functionalities that's missing (you have to manually use lightning-cli on your LN node):
|
||||
|
||||
- Be notified when a LN payment is received
|
||||
- Connect your node to the LN network
|
||||
- Open/close channels
|
||||
|
||||
## Manually test your installation through the Gatekeeper
|
||||
|
||||
If you need the authorization header to copy/paste in another tool, put your API ID (id=) and API key (k=) in the following command:
|
||||
|
||||
```shell
|
||||
id="003";h64=$(echo -n "{\"alg\":\"HS256\",\"typ\":\"JWT\"}" | base64);p64=$(echo -n "{\"id\":\"$id\",\"exp\":$((`date +"%s"`+60))}" | base64);k="b9b8d527a1a27af2ad1697db3521f883760c342fc386dbc42c4efbb1a4d5e0af";s=$(echo -n "$h64.$p64" | openssl dgst -hmac "$k" -sha256 -r | cut -sd ' ' -f1);token="$h64.$p64.$s";echo "Bearer $token"
|
||||
```
|
||||
|
||||
Directly using curl on command line, put your API ID (id=) and API key (k=) in the following commands:
|
||||
|
||||
```shell
|
||||
id="001";h64=$(echo -n "{\"alg\":\"HS256\",\"typ\":\"JWT\"}" | base64);p64=$(echo -n "{\"id\":\"$id\",\"exp\":$((`date +"%s"`+10))}" | base64);k="2df1eeea370eacdc5cf7e96c2d82140d1568079a5d4d87006ec8718a98883b36";s=$(echo -n "$h64.$p64" | openssl dgst -hmac "$k" -sha256 -r | cut -sd ' ' -f1);token="$h64.$p64.$s";curl -v -H "Authorization: Bearer $token" -k https://127.0.0.1/getbestblockhash
|
||||
id="003";h64=$(echo -n "{\"alg\":\"HS256\",\"typ\":\"JWT\"}" | base64);p64=$(echo -n "{\"id\":\"$id\",\"exp\":$((`date +"%s"`+10))}" | base64);k="b9b8d527a1a27af2ad1697db3521f883760c342fc386dbc42c4efbb1a4d5e0af";s=$(echo -n "$h64.$p64" | openssl dgst -hmac "$k" -sha256 -r | cut -sd ' ' -f1);token="$h64.$p64.$s";curl -v -H "Authorization: Bearer $token" -k https://127.0.0.1/getbalance
|
||||
id="003";h64=$(echo -n "{\"alg\":\"HS256\",\"typ\":\"JWT\"}" | base64);p64=$(echo -n "{\"id\":\"$id\",\"exp\":$((`date +"%s"`+10))}" | base64);k="b9b8d527a1a27af2ad1697db3521f883760c342fc386dbc42c4efbb1a4d5e0af";s=$(echo -n "$h64.$p64" | openssl dgst -hmac "$k" -sha256 -r | cut -sd ' ' -f1);token="$h64.$p64.$s";curl -v -H "Content-Type: application/json" -d '{"hash":"123","callbackUrl":"http://callback"}' -H "Authorization: Bearer $token" -k https://127.0.0.1/ots_stamp
|
||||
```
|
||||
|
||||
|
||||
## Manually test your installation directly on the Proxy:
|
||||
|
||||
```shell
|
||||
echo "GET /getbestblockinfo" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -
|
||||
echo "GET /getbalance" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -
|
||||
echo "GET /getbestblockhash" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -
|
||||
echo "GET /getblockinfo/00000000a64e0d1ae0c39166f4e8717a672daf3d61bf7bbb41b0f487fcae74d2" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -
|
||||
echo "GET /ln_getinfo" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -
|
||||
```
|
||||
120
docker-compose-sample.yml
Normal file
120
docker-compose-sample.yml
Normal file
@@ -0,0 +1,120 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
|
||||
gatekeeper:
|
||||
# HTTP authentication API gate
|
||||
environment:
|
||||
- "TRACING=1"
|
||||
image: cyphernode/gatekeeper:latest
|
||||
ports:
|
||||
- "443:443"
|
||||
volumes:
|
||||
- "~/cn-files/cn-gatekeeper/certs:/etc/ssl/certs"
|
||||
- "~/cn-files/cn-gatekeeper/private:/etc/ssl/private"
|
||||
- "~/cn-files/cn-gatekeeper/keys.properties:/etc/nginx/conf.d/keys.properties"
|
||||
- "~/cn-files/cn-gatekeeper/api.properties:/etc/nginx/conf.d/api.properties"
|
||||
command: $USER
|
||||
# deploy:
|
||||
# placement:
|
||||
# constraints: [node.hostname==dev]
|
||||
networks:
|
||||
- cyphernodenet
|
||||
restart: always
|
||||
|
||||
proxy:
|
||||
command: $USER ./startproxy.sh
|
||||
# Bitcoin Mini Proxy
|
||||
environment:
|
||||
- "TRACING=1"
|
||||
- "WATCHER_BTC_NODE_RPC_URL=bitcoin:18332/wallet/watching01.dat"
|
||||
- "WATCHER_BTC_NODE_RPC_USER=bitcoin:CHANGEME"
|
||||
- "WATCHER_BTC_NODE_RPC_CFG=/tmp/watcher_btcnode_curlcfg.properties"
|
||||
- "SPENDER_BTC_NODE_RPC_URL=bitcoin:18332/wallet/spending01.dat"
|
||||
- "SPENDER_BTC_NODE_RPC_USER=bitcoin:CHANGEME"
|
||||
- "SPENDER_BTC_NODE_RPC_CFG=/tmp/spender_btcnode_curlcfg.properties"
|
||||
- "PROXY_LISTENING_PORT=8888"
|
||||
- "DB_PATH=/proxy/db"
|
||||
- "DB_FILE=/proxy/db/proxydb"
|
||||
- "PYCOIN_CONTAINER=pycoin:7777"
|
||||
- "WATCHER_BTC_NODE_PRUNED=false"
|
||||
- "OTSCLIENT_CONTAINER=otsclient:6666"
|
||||
- "OTS_FILES=/proxy/otsfiles"
|
||||
image: cyphernode/proxy:latest
|
||||
|
||||
volumes:
|
||||
- "~/cn-files/cn-proxydb:/proxy/db"
|
||||
- "~/cn-files/cn-lndata:/.lightning"
|
||||
- "~/cn-files/cn-otsfiles:/proxy/otsfiles"
|
||||
# deploy:
|
||||
# placement:
|
||||
# constraints: [node.hostname==dev]
|
||||
networks:
|
||||
- cyphernodenet
|
||||
restart: always
|
||||
|
||||
proxycron:
|
||||
environment:
|
||||
- "PROXY_URL=proxy:8888/executecallbacks"
|
||||
image: cyphernode/proxycron:latest
|
||||
# deploy:
|
||||
# placement:
|
||||
# constraints: [node.hostname==dev]
|
||||
networks:
|
||||
- cyphernodenet
|
||||
restart: always
|
||||
|
||||
pycoin:
|
||||
# Pycoin
|
||||
command: $USER ./startpycoin.sh
|
||||
image: cyphernode/pycoin:latest
|
||||
environment:
|
||||
- "TRACING=1"
|
||||
- "PYCOIN_LISTENING_PORT=7777"
|
||||
# deploy:
|
||||
# placement:
|
||||
# constraints: [node.hostname==dev]
|
||||
networks:
|
||||
- cyphernodenet
|
||||
restart: always
|
||||
|
||||
lightning:
|
||||
command: $USER lightningd
|
||||
image: cyphernode/clightning:v0.6.2
|
||||
volumes:
|
||||
- "~/cn-files/cn-lndata:/.lightning"
|
||||
- "~/cn-files/cn-lndata/bitcoin.conf:/.bitcoin/bitcoin.conf"
|
||||
# deploy:
|
||||
# placement:
|
||||
# constraints: [node.hostname==dev]
|
||||
networks:
|
||||
- cyphernodenet
|
||||
restart: always
|
||||
|
||||
otsclient:
|
||||
environment:
|
||||
- "TRACING=1"
|
||||
- "OTSCLIENT_LISTENING_PORT=6666"
|
||||
image: cyphernode/otsclient:latest
|
||||
# deploy:
|
||||
# placement:
|
||||
# constraints: [node.hostname==dev]
|
||||
volumes:
|
||||
- "~/cn-files/cn-otsfiles:/otsfiles"
|
||||
command: $USER /script/startotsclient.sh
|
||||
networks:
|
||||
- cyphernodenet
|
||||
restart: always
|
||||
|
||||
bitcoin:
|
||||
command: $USER bitcoind
|
||||
image: cyphernode/bitcoin:v0.17.0
|
||||
volumes:
|
||||
- "~/cn-files/cn-btcdata:/.bitcoin"
|
||||
networks:
|
||||
- cyphernodenet
|
||||
restart: always
|
||||
|
||||
networks:
|
||||
cyphernodenet:
|
||||
external: true
|
||||
@@ -1,108 +0,0 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
gatekeeper:
|
||||
# HTTP authentication API gate
|
||||
env_file:
|
||||
- api_auth_docker/env.properties
|
||||
image: cyphernode/gatekeeper:cyphernode-0.05
|
||||
ports:
|
||||
# - "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- "~/cyphernode-ssl/certs:/etc/ssl/certs"
|
||||
- "~/cyphernode-ssl/private:/etc/ssl/private"
|
||||
# deploy:
|
||||
# placement:
|
||||
# constraints: [node.hostname==dev]
|
||||
networks:
|
||||
- cyphernodenet
|
||||
|
||||
proxy:
|
||||
# Bitcoin Mini Proxy
|
||||
env_file:
|
||||
- proxy_docker/env.properties
|
||||
image: cyphernode/proxy:cyphernode-0.05
|
||||
volumes:
|
||||
# Variable substitutions don't work
|
||||
# Match with DB_PATH in proxy_docker/env.properties
|
||||
- "~/btcproxydb:/proxy/db"
|
||||
# c-lightning looks for $HOME/.lightning/, and $HOME is set to / in the container
|
||||
- "~/lndata:/.lightning"
|
||||
# OTS files, shared with otsclient container
|
||||
- "~/otsfiles:/otsfiles"
|
||||
# deploy:
|
||||
# placement:
|
||||
# constraints: [node.hostname==dev]
|
||||
command: $USER ./startproxy.sh
|
||||
networks:
|
||||
- cyphernodenet
|
||||
|
||||
proxycron:
|
||||
# Async jobs
|
||||
env_file:
|
||||
- cron_docker/env.properties
|
||||
image: cyphernode/proxycron:cyphernode-0.05
|
||||
# deploy:
|
||||
# placement:
|
||||
# constraints: [node.hostname==dev]
|
||||
networks:
|
||||
- cyphernodenet
|
||||
|
||||
pycoin:
|
||||
# Pycoin
|
||||
env_file:
|
||||
- pycoin_docker/env.properties
|
||||
image: cyphernode/pycoin:cyphernode-0.05
|
||||
# deploy:
|
||||
# placement:
|
||||
# constraints: [node.hostname==dev]
|
||||
command: $USER ./startpycoin.sh
|
||||
networks:
|
||||
- cyphernodenet
|
||||
|
||||
otsclient:
|
||||
# otsclient JS
|
||||
env_file:
|
||||
- otsclient_docker/env.properties
|
||||
image: cyphernode/otsclient:cyphernode-0.05
|
||||
# deploy:
|
||||
# placement:
|
||||
# constraints: [node.hostname==dev]
|
||||
volumes:
|
||||
- "~/otsfiles:/otsfiles"
|
||||
command: $USER /script/startotsclient.sh
|
||||
networks:
|
||||
- cyphernodenet
|
||||
|
||||
lightning:
|
||||
# c-lightning lightning network node
|
||||
image: cyphernode/clightning:dev
|
||||
ports:
|
||||
- "9735:9735"
|
||||
volumes:
|
||||
- "~/lndata:/.lightning"
|
||||
- "~/lndata/bitcoin.conf:/.bitcoin/bitcoin.conf"
|
||||
# deploy:
|
||||
# placement:
|
||||
# constraints: [node.hostname==dev]
|
||||
command: $USER lightningd
|
||||
networks:
|
||||
- cyphernodenet
|
||||
|
||||
bitcoin:
|
||||
# Bitcoin node
|
||||
image: cyphernode/bitcoin:0.17.0
|
||||
# ports:
|
||||
# - "18333:18333"
|
||||
# - "29000:29000"
|
||||
# - "8333:8333"
|
||||
volumes:
|
||||
- "~/btcdata:/.bitcoin"
|
||||
command: $USER bitcoind
|
||||
networks:
|
||||
- cyphernodenet
|
||||
|
||||
networks:
|
||||
cyphernodenet:
|
||||
external: true
|
||||
@@ -3,16 +3,17 @@
|
||||
# run as user <%= username %>
|
||||
export USER=$(id -u <%= run_as_different_user?username:default_username %>):$(id -g <%= run_as_different_user?username:default_username %>)
|
||||
export ARCH=$(uname -m)
|
||||
current_path="$(cd "$(dirname "$0")" >/dev/null && pwd)"
|
||||
|
||||
<% if (docker_mode == 'swarm') { %>
|
||||
docker stack deploy -c docker-compose.yaml cyphernode
|
||||
docker stack deploy -c $current_path/docker-compose.yaml cyphernode
|
||||
<% } else if(docker_mode == 'compose') { %>
|
||||
docker-compose -f docker-compose.yaml up -d --remove-orphans
|
||||
docker-compose -f $current_path/docker-compose.yaml up -d --remove-orphans
|
||||
<% } %>
|
||||
|
||||
# Will test if Cyphernode is fully up and running...
|
||||
docker run --rm -it -v `pwd`/testfeatures.sh:/testfeatures.sh \
|
||||
-v `pwd`/gatekeeper/keys.properties:/keys.properties \
|
||||
-v `pwd`/gatekeeper/cert.pem:/cert.pem \
|
||||
docker run --rm -it -v $current_path/testfeatures.sh:/testfeatures.sh \
|
||||
-v $current_path/gatekeeper/keys.properties:/keys.properties \
|
||||
-v $current_path/gatekeeper/cert.pem:/cert.pem \
|
||||
-v <%= proxy_datapath %>:/proxy \
|
||||
--network cyphernodenet alpine:3.8 /testfeatures.sh
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
current_path="$(cd "$(dirname "$0")" >/dev/null && pwd)"
|
||||
|
||||
<% if (docker_mode == 'swarm') { %>
|
||||
export USER=$(id -u):$(id -g)
|
||||
export ARCH=$(uname -m)
|
||||
@@ -7,5 +9,5 @@ docker stack rm cyphernode
|
||||
<% } else if(docker_mode == 'compose') { %>
|
||||
export USER=$(id -u):$(id -g)
|
||||
export ARCH=$(uname -m)
|
||||
docker-compose -f docker-compose.yaml down
|
||||
<% } %>
|
||||
docker-compose -f $current_path/docker-compose.yaml down
|
||||
<% } %>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
apk add --update --no-cache openssl curl
|
||||
apk add --update --no-cache openssl curl > /dev/null
|
||||
|
||||
. keys.properties
|
||||
|
||||
checkgatekeeper() {
|
||||
echo -e "\r\nTesting Gatekeeper..." > /dev/console
|
||||
echo -e "\r\n\e[1;36mTesting Gatekeeper...\e[0;32m" > /dev/console
|
||||
|
||||
local rc
|
||||
local id="001"
|
||||
@@ -20,7 +20,7 @@ checkgatekeeper() {
|
||||
local s=$(echo -n "$h64.$p64" | openssl dgst -hmac "$k" -sha256 -r | cut -sd ' ' -f1)
|
||||
local token="$h64.$p64.$s"
|
||||
|
||||
echo " Sleeping 2 seconds... " > /dev/console
|
||||
echo -e " Sleeping 2 seconds... " > /dev/console
|
||||
sleep 2
|
||||
|
||||
echo " Testing expired request... " > /dev/console
|
||||
@@ -66,13 +66,13 @@ checkgatekeeper() {
|
||||
rc=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $token" --cacert /cert.pem https://gatekeeper/conf)
|
||||
[ "${rc}" -ne "403" ] && return 60
|
||||
|
||||
echo "***** Gatekeeper rocks!" > /dev/console
|
||||
echo -e "\e[1;36mGatekeeper rocks!" > /dev/console
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
checkpycoin() {
|
||||
echo -e "\r\nTesting Pycoin..." > /dev/console
|
||||
echo -en "\r\n\e[1;36mTesting Pycoin... " > /dev/console
|
||||
local rc
|
||||
local id="002"
|
||||
local k
|
||||
@@ -87,13 +87,13 @@ checkpycoin() {
|
||||
rc=$(curl -H "Content-Type: application/json" -d "{\"pub32\":\"upub5GtUcgGed1aGH4HKQ3vMYrsmLXwmHhS1AeX33ZvDgZiyvkGhNTvGd2TA5Lr4v239Fzjj4ZY48t6wTtXUy2yRgapf37QHgt6KWEZ6bgsCLpb\",\"path\":\"0/25-30\"}" -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $token" --cacert /cert.pem https://gatekeeper/derivepubpath)
|
||||
[ "${rc}" -ne "200" ] && return 100
|
||||
|
||||
echo "***** Pycoin rocks!" > /dev/console
|
||||
echo -e "\e[1;36mPycoin rocks!" > /dev/console
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
checkots() {
|
||||
echo -e "\r\nTesting OTSclient..." > /dev/console
|
||||
echo -en "\r\n\e[1;36mTesting OTSclient... " > /dev/console
|
||||
local rc
|
||||
local id="002"
|
||||
local k
|
||||
@@ -109,13 +109,13 @@ checkots() {
|
||||
echo "${rc}" | grep "Invalid hash 123 for sha256" > /dev/null
|
||||
[ "$?" -ne "0" ] && return 200
|
||||
|
||||
echo "***** OTSclient rocks!" > /dev/console
|
||||
echo -e "\e[1;36mOTSclient rocks!" > /dev/console
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
checkbitcoinnode() {
|
||||
echo -e "\r\nTesting Bitcoin..." > /dev/console
|
||||
echo -en "\r\n\e[1;36mTesting Bitcoin... " > /dev/console
|
||||
local rc
|
||||
local id="002"
|
||||
local k
|
||||
@@ -130,13 +130,13 @@ checkbitcoinnode() {
|
||||
rc=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $token" --cacert /cert.pem https://gatekeeper/getbestblockhash)
|
||||
[ "${rc}" -ne "200" ] && return 300
|
||||
|
||||
echo "***** Bitcoin node rocks!" > /dev/console
|
||||
echo -e "\e[1;36mBitcoin node rocks!" > /dev/console
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
checklnnode() {
|
||||
echo -e "\r\nTesting Lightning..." > /dev/console
|
||||
echo -en "\r\n\e[1;36mTesting Lightning... " > /dev/console
|
||||
local rc
|
||||
local id="002"
|
||||
local k
|
||||
@@ -151,13 +151,13 @@ checklnnode() {
|
||||
rc=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $token" --cacert /cert.pem https://gatekeeper/ln_getinfo)
|
||||
[ "${rc}" -ne "200" ] && return 400
|
||||
|
||||
echo "***** LN node rocks!" > /dev/console
|
||||
echo -e "\e[1;36mLN node rocks!" > /dev/console
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
checkservice() {
|
||||
echo -e "\r\nTesting if Cyphernode is up and running... I will keep trying during up to 5 minutes to give time to Docker to deploy everything..." > /dev/console
|
||||
echo -e "\r\n\e[1;36mTesting if Cyphernode is up and running... \e[0;36mI will keep trying during up to 5 minutes to give time to Docker to deploy everything...\e[0;32m" > /dev/console
|
||||
|
||||
local outcome
|
||||
local returncode=0
|
||||
@@ -168,8 +168,8 @@ checkservice() {
|
||||
do
|
||||
outcome=0
|
||||
for container in gatekeeper proxy proxycron pycoin <%= (features.indexOf('otsclient') != -1)?'otsclient ':'' %>bitcoin <%= (features.indexOf('lightning') != -1)?'lightning ':'' %>; do
|
||||
echo " Verifying ${container}..." > /dev/console
|
||||
(ping -c 10 ${container} | grep "0% packet loss" > /dev/null) &
|
||||
echo -e " \e[0;32mVerifying \e[0;33m${container}\e[0;32m..." > /dev/console
|
||||
(ping -c 10 ${container} 2> /dev/null | grep "0% packet loss" > /dev/null) &
|
||||
eval ${container}=$!
|
||||
done
|
||||
for container in gatekeeper proxy proxycron pycoin <%= (features.indexOf('otsclient') != -1)?'otsclient ':'' %>bitcoin <%= (features.indexOf('lightning') != -1)?'lightning ':'' %>; do
|
||||
@@ -180,7 +180,7 @@ checkservice() {
|
||||
# If '0% packet loss' everywhere or 5 minutes passed, we get out of this loop
|
||||
([ "${outcome}" -eq "0" ] || [ $(date +%s) -gt ${endtime} ]) && break
|
||||
|
||||
echo " Cyphernode still not ready, will retry in 5 seconds for max 5 minutes..." > /dev/console
|
||||
echo -e "\e[1;31mCyphernode still not ready, will retry every 5 seconds for 5 minutes ($((${endtime} - $(date +%s))) seconds left)." > /dev/console
|
||||
|
||||
sleep 5
|
||||
done
|
||||
@@ -225,7 +225,7 @@ timeout_feature() {
|
||||
# If no error or 2 minutes passed, we get out of this loop
|
||||
([ "${returncode}" -eq "0" ] || [ $(date +%s) -gt ${endtime} ]) && break
|
||||
|
||||
echo "xxxxx Maybe it's too early, I'll retry in 5 seconds (for max 2 minutes total)." > /dev/console
|
||||
echo -e "\e[1;31mMaybe it's too early, I'll retry every 5 seconds for 2 minutes ($((${endtime} - $(date +%s))) seconds left)." > /dev/console
|
||||
|
||||
sleep 5
|
||||
done
|
||||
@@ -238,7 +238,7 @@ feature_status() {
|
||||
local errormsg=${2}
|
||||
|
||||
[ "${returncode}" -eq "0" ] && echo "true"
|
||||
[ "${returncode}" -ne "0" ] && echo "false" && echo ${errormsg} > /dev/console
|
||||
[ "${returncode}" -ne "0" ] && echo "false" && echo -e "\e[1;31m${errormsg}" > /dev/console
|
||||
}
|
||||
|
||||
# /proxy/installation.json will contain something like that:
|
||||
@@ -266,9 +266,9 @@ feature_status() {
|
||||
result=$(checkservice)
|
||||
returncode=$?
|
||||
if [ "${returncode}" -ne "0" ]; then
|
||||
echo "xxxxx Cyphernode could not fully start properly within 5 minutes." > /dev/console
|
||||
echo -e "\e[1;31mCyphernode could not fully start properly within 5 minutes." > /dev/console
|
||||
else
|
||||
echo "***** Cyphernode seems to be correctly deployed. Let's run more thourough tests..." > /dev/console
|
||||
echo -e "\e[1;36mCyphernode seems to be correctly deployed. Let's run more thourough tests..." > /dev/console
|
||||
fi
|
||||
|
||||
# Let's now check each feature fonctionality...
|
||||
@@ -283,34 +283,34 @@ fi
|
||||
result="${result},\"features\":[{\"name\":\"gatekeeper\",\"working\":"
|
||||
timeout_feature checkgatekeeper
|
||||
returncode=$?
|
||||
result="${result}$(feature_status ${returncode} 'xxxxx Gatekeeper error!')}"
|
||||
result="${result}$(feature_status ${returncode} 'Gatekeeper error!')}"
|
||||
|
||||
result="${result},{\"name\":\"pycoin\",\"working\":"
|
||||
timeout_feature checkpycoin
|
||||
returncode=$?
|
||||
result="${result}$(feature_status ${returncode} 'xxxxx Pycoin error!')}"
|
||||
result="${result}$(feature_status ${returncode} 'Pycoin error!')}"
|
||||
|
||||
<% if (features.indexOf('otsclient') != -1) { %>
|
||||
result="${result},{\"name\":\"otsclient\",\"working\":"
|
||||
timeout_feature checkots
|
||||
returncode=$?
|
||||
result="${result}$(feature_status ${returncode} 'xxxxx OTSclient error!')}"
|
||||
result="${result}$(feature_status ${returncode} 'OTSclient error!')}"
|
||||
<% } %>
|
||||
|
||||
result="${result},{\"name\":\"bitcoin\",\"working\":"
|
||||
timeout_feature checkbitcoinnode
|
||||
returncode=$?
|
||||
result="${result}$(feature_status ${returncode} 'xxxxx Bitcoin error!')}"
|
||||
result="${result}$(feature_status ${returncode} 'Bitcoin error!')}"
|
||||
|
||||
<% if (features.indexOf('lightning') != -1) { %>
|
||||
result="${result},{\"name\":\"lightning\",\"working\":"
|
||||
timeout_feature checklnnode
|
||||
returncode=$?
|
||||
result="${result}$(feature_status ${returncode} 'xxxxx Lightning error!')}"
|
||||
result="${result}$(feature_status ${returncode} 'Lightning error!')}"
|
||||
<% } %>
|
||||
|
||||
result="{${result}]}"
|
||||
|
||||
echo "${result}" > /proxy/installation.json
|
||||
|
||||
echo ; echo "Tests finished." > /dev/console
|
||||
echo -e "\r\n\e[1;32mTests finished.\e[0m" > /dev/console
|
||||
|
||||
Reference in New Issue
Block a user