diff --git a/rootfs/standard/etc/systemd/system/dojo.service b/rootfs/standard/etc/systemd/system/dojo.service new file mode 100644 index 00000000..2de93972 --- /dev/null +++ b/rootfs/standard/etc/systemd/system/dojo.service @@ -0,0 +1,22 @@ +# samourai dojo service +# /etc/systemd/system/dojo.service + +[Unit] +Description=Dojo +After=network.target mynode.service + +[Service] +Type=forking +RemainAfterExit=yes +WorkingDirectory=/opt/mynode/dojo/docker/my-dojo +ExecStart=/opt/mynode/dojo/docker/my-dojo/dojo.sh start +ExecStop=/opt/mynode/dojo/docker/my-dojo/dojo.sh stop +User=root +Group=root +KillMode=process +TimeoutSec=420 +Restart=always +RestartSec=60 + +[Install] +WantedBy=multi-user.target diff --git a/rootfs/standard/usr/bin/mynode_firewall.sh b/rootfs/standard/usr/bin/mynode_firewall.sh index dcc07d6a..54a16602 100755 --- a/rootfs/standard/usr/bin/mynode_firewall.sh +++ b/rootfs/standard/usr/bin/mynode_firewall.sh @@ -16,8 +16,14 @@ ufw allow 10009 comment 'allow Lightning gRPC' ufw allow 10080 comment 'allow Lightning REST RPC' ufw allow 9735 comment 'allow Lightning' ufw allow 8332 comment 'allow Bitcoin RPC - filtered by rpcallowip' -ufw allow 8333 comment 'allow Bitcoin Mainnet' -ufw allow 18333 comment 'allow Bitcoin Testnet' +ufw allow 8333 comment 'allow Bitcoin mainnet' +ufw allow 18333 comment 'allow Bitcoin testnet' +ufw allow from 172.17.0.0/16 to any port 28332 comment 'allow Dojo zmqrawblock' +ufw allow from 172.28.0.0/16 to any port 28332 comment 'allow Dojo zmqrawblock' +ufw allow from 172.17.0.0/16 to any port 28333 comment 'allow Dojo zmqrawtx' +ufw allow from 172.28.0.0/16 to any port 28333 comment 'allow Dojo zmqrawtx' +ufw allow from 172.17.0.0/16 to any port 28334 comment 'allow Dojo zmqhashblock' +ufw allow from 172.28.0.0/16 to any port 28334 comment 'allow Dojo zmqhashblock' ufw allow 2222 comment 'allow WebSSH2' ufw allow 3000 comment 'allow LndHub' ufw allow 3002 comment 'allow BTC RPC Explorer' diff --git a/rootfs/standard/usr/bin/mynode_gen_dojo_config.sh b/rootfs/standard/usr/bin/mynode_gen_dojo_config.sh new file mode 100755 index 00000000..0ee33960 --- /dev/null +++ b/rootfs/standard/usr/bin/mynode_gen_dojo_config.sh @@ -0,0 +1,129 @@ +#!/bin/bash + +set -x +set -e + +source /usr/share/mynode/mynode_config.sh + +# replace Dojo bitcoind.conf.tpl with custom conf for MyNode +rm -rf /opt/mynode/dojo/docker/my-dojo/conf/docker-bitcoind.conf.tpl +touch /opt/mynode/dojo/docker/my-dojo/conf/docker-bitcoind.conf.tpl + +RPC_PASS=$(cat /mnt/hdd/mynode/settings/.btcrpc_environment | cut -c 18- ) + +echo " +######################################### +# CONFIGURATION OF BITCOIND CONTAINER # +######################################### +# User account used for rpc access to bitcoind Type: alphanumeric +BITCOIND_RPC_USER=mynode +# Password of user account used for rpc access to bitcoind Type: +# alphanumeric +BITCOIND_RPC_PASSWORD=$RPC_PASS +# Max number of connections to network peers Type: integer +BITCOIND_MAX_CONNECTIONS=16 +# Mempool maximum size in MB Type: integer +BITCOIND_MAX_MEMPOOL=600 +# Db cache size in MB Type: integer +BITCOIND_DB_CACHE=1024 +# Number of threads to service RPC calls Type: integer +BITCOIND_RPC_THREADS=6 +# Mempool expiry in hours Defines how long transactions stay in your local +# mempool before expiring Type: integer +BITCOIND_MEMPOOL_EXPIRY=72 +# Min relay tx fee in BTC Type: numeric +BITCOIND_MIN_RELAY_TX_FEE=0.00001 +# +# EXPERT SETTINGS +# +# EPHEMERAL ONION ADDRESS FOR BITCOIND THIS PARAMETER HAS NO EFFECT IF +# BITCOIND_INSTALL IS SET TO OFF +# +# Generate a new onion address for bitcoind when Dojo is launched +# Activation of this option is recommended for improved privacy. Values: on +# | off +BITCOIND_EPHEMERAL_HS=on +# +# EXPOSE BITCOIND RPC API AND ZMQ NOTIFICATIONS TO EXTERNAL APPS THESE +# PARAMETERS HAVE NO EFFECT IF BITCOIND_INSTALL IS SET TO OFF +# +# Expose the RPC API to external apps Warning: Do not expose your RPC API +# to internet! See BITCOIND_RPC_EXTERNAL_IP Value: on | off +BITCOIND_RPC_EXTERNAL=off +# IP address used to expose the RPC API to external apps This parameter is +# inactive if BITCOIND_RPC_EXTERNAL isn't set to 'on' Warning: Do not +# expose your RPC API to internet! Recommended value: +# linux: 127.0.0.1 macos or windows: IP address of the VM running the +# docker host +# Type: string +BITCOIND_RPC_EXTERNAL_IP=127.0.0.1 +# +# INSTALL AND RUN BITCOIND INSIDE DOCKER +# +# Install and run bitcoind inside Docker Set this option to 'off' for using +# a bitcoind hosted outside of Docker (not recommended) Value: on | off +BITCOIND_INSTALL=off +# IP address of bitcoind used by Dojo Set value to 172.28.1.5 if +# BITCOIND_INSTALL is set to 'on' Type: string +BITCOIND_IP=172.28.0.1 +# Port of the RPC API Set value to 28256 if BITCOIND_INSTALL is set to 'on' +# Type: integer +BITCOIND_RPC_PORT=8332 +# Port exposing ZMQ notifications for raw transactions Set value to 9501 if +# BITCOIND_INSTALL is set to 'on' Type: integer +BITCOIND_ZMQ_RAWTXS=28333 +# Port exposing ZMQ notifications for block hashes Set value to 9502 if +# BITCOIND_INSTALL is set to 'on' Type: integer +BITCOIND_ZMQ_BLK_HASH=28334 +" | sudo tee -a /opt/mynode/dojo/docker/my-dojo/conf/docker-bitcoind.conf.tpl + +# Turn off explorer for MyNode +sed -i 's|EXPLORER_INSTALL=on|EXPLORER_INSTALL=off|' /opt/mynode/dojo/docker/my-dojo/conf/docker-explorer.conf.tpl + +# check if configuration files have been previously created and skip if yes +if [ -f /opt/mynode/dojo/docker/my-dojo/conf/docker-node.conf ]; then + echo "File present - skip docker-node.conf" +else + # Modify node.conf to enter random generated passwords + NODE_API_KEY=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 64 | head -n 1) + sed -i 's|NODE_API_KEY=.*|NODE_API_KEY='$NODE_API_KEY'|' /opt/mynode/dojo/docker/my-dojo/conf/docker-node.conf.tpl + + NODE_ADMIN_KEY=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 48 | head -n 1) + sed -i 's|NODE_ADMIN_KEY=.*|NODE_ADMIN_KEY='$NODE_ADMIN_KEY'|' /opt/mynode/dojo/docker/my-dojo/conf/docker-node.conf.tpl + + NODE_JWT_SECRET=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 64 | head -n 1) + sed -i 's|NODE_JWT_SECRET=.*|NODE_JWT_SECRET='$NODE_JWT_SECRET'|' /opt/mynode/dojo/docker/my-dojo/conf/docker-node.conf.tpl +fi + +# check if configuration files have been previously created and skip if yes +if [ -f /opt/mynode/dojo/docker/my-dojo/conf/docker-mysql.conf ]; then + echo "File present - skip docker-mysql.conf" +else + # Modify mysql.conf to enter random generated passwords + MYSQL_ROOT_PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 64 | head -n 1) + sed -i 's|MYSQL_ROOT_PASSWORD=.*|MYSQL_ROOT_PASSWORD='$MYSQL_ROOT_PASSWORD'|' /opt/mynode/dojo/docker/my-dojo/conf/docker-mysql.conf.tpl + + MYSQL_USER=mynode + sed -i 's|MYSQL_USER=.*|MYSQL_USER='$MYSQL_USER'|' /opt/mynode/dojo/docker/my-dojo/conf/docker-mysql.conf.tpl + + MYSQL_PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 64 | head -n 1) + sed -i 's|MYSQL_PASSWORD=.*|MYSQL_PASSWORD='$MYSQL_PASSWORD'|' /opt/mynode/dojo/docker/my-dojo/conf/docker-mysql.conf.tpl +fi + +# Modify for Raspbian devices +if [ $IS_RASPI = 1 ]; then + # Modify mysql Dockerfile for Raspbian devices + sed -i 's|FROM.*|FROM hypriot/rpi-mysql:latest|' /opt/mynode/dojo/docker/my-dojo/mysql/Dockerfile + # Modify Tor Dockerfile for ARMv6/7 devices + sed -i 's|ENV GOLANG_ARCHIVE.*|ENV GOLANG_ARCHIVE go1.13.6.linux-armv6l.tar.gz|' /opt/mynode/dojo/docker/my-dojo/tor/Dockerfile + sed -i 's|ENV GOLANG_SHA256.*|ENV GOLANG_SHA256 37a1a83e363dcf146a67fa839d170fd1afb13009585fdd493d0a3370fbe6f785|' /opt/mynode/dojo/docker/my-dojo/tor/Dockerfile +fi + +# Modify for Rock64 devices +if [ $IS_ROCK64 = 1 ] || [ $IS_ROCKPRO64 = 1 ]; then + # Modify mysql Dockerfile for Rock64 devices + sed -i 's|FROM.*|FROM mariadb:latest|' /opt/mynode/dojo/docker/my-dojo/mysql/Dockerfile + # Modify Tor Dockerfile for ARMv8 devices + sed -i 's|ENV GOLANG_ARCHIVE.*|ENV GOLANG_ARCHIVE go1.13.6.linux-arm64.tar.gz|' /opt/mynode/dojo/docker/my-dojo/tor/Dockerfile + sed -i 's|ENV GOLANG_SHA256.*|ENV GOLANG_SHA256 0a18125c4ed80f9c3045cf92384670907c4796b43ed63c4307210fe93e5bbca5|' /opt/mynode/dojo/docker/my-dojo/tor/Dockerfile +fi diff --git a/rootfs/standard/usr/bin/mynode_post_dojo.sh b/rootfs/standard/usr/bin/mynode_post_dojo.sh new file mode 100755 index 00000000..bcb8166b --- /dev/null +++ b/rootfs/standard/usr/bin/mynode_post_dojo.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +set -e + +sleep 10s #dojo needs time to start before passing next line + +# initalize mysql db (REQUIRED TO START MYSQL) +counter=0 +target=50 +isRunning="" +MYSQL_DATABASE=samourai-main + +# check on loop if mysql db is running. when running initialize +while [ $counter != $target ] +do + + source /opt/mynode/dojo/docker/my-dojo/conf/docker-mysql.conf || exit 0 + + # Check if dojo mysql db is running (check the db container) + isRunning=$(docker inspect --format="{{.State.Running}}" db) + if [ $isRunning == "true" ]; then + sleep 20s + docker exec -i db bash -c "mysql -h db -u root -p$MYSQL_ROOT_PASSWORD $MYSQL_DATABASE" $WHIRLPOOL_UPGRADE_URL_FILE fi +# Install Dojo +DOJO_VERSION="v1.4.1" +DOJO_UPGRADE_URL=https://github.com/Samourai-Wallet/samourai-dojo/archive/$DOJO_VERSION.tar.gz +DOJO_UPGRADE_URL_FILE=/home/bitcoin/.mynode/.dojo_url +CURRENT="" +INSTALL=true +if [ -f $DOJO_UPGRADE_URL_FILE ]; then + INSTALL=false + CURRENT=$(cat $DOJO_UPGRADE_URL_FILE) +fi +if [ "$CURRENT" != "$DOJO_UPGRADE_URL" ]; then + sudo systemctl stop bitcoind + sudo mkdir -p /opt/mynode/.dojo + sudo mkdir -p /opt/mynode/dojo + sudo rm -rf /opt/mynode/.dojo/* + cd /opt/mynode/.dojo + sudo wget -O dojo.tar.gz $DOJO_UPGRADE_URL + sudo tar -zxvf dojo.tar.gz + sudo cp -r samourai-dojo*/* /opt/mynode/dojo + cd /usr/bin + sudo rm -rf /opt/mynode/.dojo/* + + # Configure Dojo for MyNode + sudo ./mynode_gen_dojo_config.sh + + # Run Dojo Install or Upgrade + cd /opt/mynode/dojo/docker/my-dojo + if [ "$INSTALL" = "true" ]; then + echo 'y' | sudo ./dojo.sh install & + else + echo 'y' | sudo ./dojo.sh upgrade & + fi + + #Check for install/upgrade to finish to initialize Dojo mysql db + cd /usr/bin + sudo ./mynode_post_dojo.sh + + echo $DOJO_UPGRADE_URL > $DOJO_UPGRADE_URL_FILE +fi + + # Upgrade RTL RTL_VERSION="v0.6.7" RTL_UPGRADE_URL=https://github.com/Ride-The-Lightning/RTL/archive/$RTL_VERSION.tar.gz diff --git a/rootfs/standard/usr/bin/mynode_stop_critical_services.sh b/rootfs/standard/usr/bin/mynode_stop_critical_services.sh index 737f1155..c257cf3c 100755 --- a/rootfs/standard/usr/bin/mynode_stop_critical_services.sh +++ b/rootfs/standard/usr/bin/mynode_stop_critical_services.sh @@ -8,12 +8,14 @@ systemctl stop glances systemctl stop rtl systemctl stop webssh2 systemctl stop whirlpool +systemctl stop dojo systemctl stop btcpayserver + # Stop core services systemctl stop electrs systemctl stop lnd systemctl stop quicksync systemctl stop bitcoind -sync \ No newline at end of file +sync diff --git a/rootfs/standard/usr/share/mynode/bitcoin.conf b/rootfs/standard/usr/share/mynode/bitcoin.conf index 2311c0cd..f8a2fdcd 100644 --- a/rootfs/standard/usr/share/mynode/bitcoin.conf +++ b/rootfs/standard/usr/share/mynode/bitcoin.conf @@ -20,13 +20,15 @@ rpcauth=mynode:7b7e11c032ddd3fc3835e4e463afd305$6c6a32bbd08cb1b67b5ea89b66865c5c rpcport=8332 rpcbind=0.0.0.0 +rpcbind=172.17.0.1 +rpcbind=172.28.0.1 rpcallowip=127.0.0.1 rpcallowip=10.0.0.0/8 rpcallowip=172.0.0.0/8 rpcallowip=192.0.0.0/8 -zmqpubrawblock=tcp://127.0.0.1:28332 -zmqpubrawtx=tcp://127.0.0.1:28333 +zmqpubrawblock=tcp://0.0.0.0:28332 +zmqpubrawtx=tcp://0.0.0.0:28333 zmqpubhashblock=tcp://0.0.0.0:28334 # myNode Optimizations diff --git a/rootfs/standard/var/www/mynode/dojo.py b/rootfs/standard/var/www/mynode/dojo.py new file mode 100644 index 00000000..4d37f5d2 --- /dev/null +++ b/rootfs/standard/var/www/mynode/dojo.py @@ -0,0 +1,71 @@ + +from flask import Blueprint, render_template, redirect +from settings import read_ui_settings +from user_management import check_logged_in +from enable_disable_functions import is_dojo_enabled, enable_dojo, disable_dojo +import subprocess +import os + +mynode_dojo = Blueprint('mynode_dojo',__name__) + +## Status and color +def get_dojo_status(): + # Find dojo status + dojo_status = "Disabled" + dojo_status_color = "gray" + try: + dojo_initialized = subprocess.check_output("docker inspect --format={{.State.Running}} db", shell=True) + dojo_initialized = dojo_initialized.strip() + except: + dojo_initialized = "" + if is_dojo_enabled(): + if dojo_initialized != "false": + dojo_status = "Running" + dojo_status_color = "green" + else: + dojo_status = "Issue Starting" + dojo_status_color = "red" + dojo_initialized = "" + return dojo_status, dojo_status_color, dojo_initialized + +### Page functions +@mynode_dojo.route("/dojo") +def dojo_page(): + check_logged_in() + + NODE_ADMIN_KEY = 'Not found' + try: + NODE_ADMIN_KEY = subprocess.check_output("cat /opt/mynode/dojo/docker/my-dojo/conf/docker-node.conf | grep -i NODE_ADMIN_KEY= | cut -c 16-", shell=True) + NODE_ADMIN_KEY = NODE_ADMIN_KEY.strip() + except: + NODE_ADMIN_KEY = 'error' + + DOJO_V3_ADDR = 'Not found' + try: + DOJO_V3_ADDR = subprocess.check_output("docker exec tor cat /var/lib/tor/hsv3dojo/hostname", shell=True) + PAGE = '/admin' + DOJO_V3_ADDR = DOJO_V3_ADDR.strip() + PAGE + except: + DOJO_V3_ADDR = 'error' + + dojo_status, dojo_status_color, dojo_initialized = get_dojo_status() + + # Load page + templateData = { + "title": "myNode Dojo", + "ui_settings": read_ui_settings(), + "dojo_status": dojo_status, + "dojo_status_color": dojo_status_color, + "dojo_enabled": is_dojo_enabled(), + "dojo_initialized": dojo_initialized, + "NODE_ADMIN_KEY": NODE_ADMIN_KEY, + "DOJO_V3_ADDR": DOJO_V3_ADDR + } + return render_template('dojo.html', **templateData) + +@mynode_dojo.route("/restart-dojo") +def page_toggle_dojo(): + check_logged_in() + disable_dojo() + enable_dojo() + return redirect("/dojo") diff --git a/rootfs/standard/var/www/mynode/enable_disable_functions.py b/rootfs/standard/var/www/mynode/enable_disable_functions.py index e87ad2d8..f976dab6 100644 --- a/rootfs/standard/var/www/mynode/enable_disable_functions.py +++ b/rootfs/standard/var/www/mynode/enable_disable_functions.py @@ -128,4 +128,15 @@ def enable_whirlpool(): def disable_whirlpool(): os.system("systemctl stop whirlpool --no-pager") - os.system("systemctl disable whirlpool --no-pager") \ No newline at end of file + os.system("systemctl disable whirlpool --no-pager") + +def is_dojo_enabled(): + return is_service_enabled("dojo") + +def enable_dojo(): + os.system("systemctl enable dojo --no-pager") + os.system("systemctl start dojo --no-pager") + +def disable_dojo(): + os.system("systemctl stop dojo --no-pager") + os.system("systemctl disable dojo --no-pager") diff --git a/rootfs/standard/var/www/mynode/mynode.py b/rootfs/standard/var/www/mynode/mynode.py index 53cea034..765d4fc1 100644 --- a/rootfs/standard/var/www/mynode/mynode.py +++ b/rootfs/standard/var/www/mynode/mynode.py @@ -5,6 +5,7 @@ from user_management import * from bitcoind import mynode_bitcoind from bitcoin_cli import mynode_bitcoin_cli from whirlpool import mynode_whirlpool, get_whirlpool_status +from dojo import mynode_dojo, get_dojo_status from tor import mynode_tor from vpn import mynode_vpn from electrum_server import * @@ -43,6 +44,7 @@ app.register_blueprint(mynode_bitcoind) app.register_blueprint(mynode_lnd) app.register_blueprint(mynode_bitcoin_cli) app.register_blueprint(mynode_whirlpool) +app.register_blueprint(mynode_dojo) app.register_blueprint(mynode_tor) app.register_blueprint(mynode_electrum_server) app.register_blueprint(mynode_vpn) @@ -376,6 +378,9 @@ def index(): # Find whirlpool status whirlpool_status, whirlpool_status_color, whirlpool_initialized = get_whirlpool_status() + # Find dojo status + dojo_status, dojo_status_color, dojo_initialized = get_dojo_status() + # Check for new version of software upgrade_available = False current = get_current_version() @@ -419,6 +424,10 @@ def index(): "whirlpool_status_color": whirlpool_status_color, "whirlpool_enabled": is_whirlpool_enabled(), "whirlpool_initialized": whirlpool_initialized, + "dojo_status": dojo_status, + "dojo_status_color": dojo_status_color, + "dojo_enabled": is_dojo_enabled(), + "dojo_initialized": dojo_initialized, "product_key_skipped": pk_skipped, "product_key_error": pk_error, "fsck_error": has_fsck_error(), @@ -543,6 +552,15 @@ def page_toggle_whirlpool(): enable_whirlpool() return redirect("/") +@app.route("/toggle-dojo") +def page_toggle_dojo(): + check_logged_in() + if is_dojo_enabled(): + disable_dojo() + else: + enable_dojo() + return redirect("/") + @app.route("/login", methods=["GET","POST"]) def page_login(): templateData = { diff --git a/rootfs/standard/var/www/mynode/templates/dojo.html b/rootfs/standard/var/www/mynode/templates/dojo.html new file mode 100644 index 00000000..5b7eb1e2 --- /dev/null +++ b/rootfs/standard/var/www/mynode/templates/dojo.html @@ -0,0 +1,71 @@ + +
+