Merge pull request #9 from rootzoll/v1.6

Merge from rootzoll/v1.6
This commit is contained in:
arno 2020-07-19 18:53:39 +02:00 committed by GitHub
commit aa486e3f05
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 720 additions and 589 deletions

View file

@ -14,7 +14,6 @@ if [ ${#autoNatDiscovery} -eq 0 ]; then autoNatDiscovery="off"; fi
if [ ${#networkUPnP} -eq 0 ]; then networkUPnP="off"; fi
if [ ${#touchscreen} -eq 0 ]; then touchscreen=0; fi
if [ ${#lcdrotate} -eq 0 ]; then lcdrotate=0; fi
if [ ${#letsencrypt} -eq 0 ]; then letsencrypt="off"; fi
if [ ${#zerotier} -eq 0 ]; then zerotier="off"; fi
echo "map dropboxbackup to on/off"
@ -78,7 +77,6 @@ OPTIONS+=(r 'LCD Rotate' ${lcdrotateMenu})
OPTIONS+=(a 'Channel Autopilot' ${autoPilot})
OPTIONS+=(k 'Accept Keysend' ${keysend})
OPTIONS+=(n 'Testnet' ${chainValue})
OPTIONS+=(c 'Let`s Encrypt Client' ${letsencrypt})
OPTIONS+=(u 'LND Auto-Unlock' ${autoUnlock})
OPTIONS+=(d 'StaticChannelBackup on DropBox' ${DropboxBackup})
OPTIONS+=(e 'StaticChannelBackup on USB Drive' ${LocalBackup})
@ -290,36 +288,6 @@ else
echo "TOR Setting unchanged."
fi
# Let's Encrypt process choice
choice="off"; check=$(echo "${CHOICES}" | grep -c "c")
if [ ${check} -eq 1 ]; then choice="on"; fi
if [ "${letsencrypt}" != "${choice}" ]; then
echo "Let's Encrypt Client Setting changed .."
anychange=1
/home/admin/config.scripts/bonus.letsencrypt.sh ${choice}
errorOnInstall=$?
if [ "${choice}" = "on" ]; then
if [ ${errorOnInstall} -eq 0 ]; then
msg="Successfully installed."
else
msg="Failed to install!"
fi
else
if [ ${errorOnInstall} -eq 0 ]; then
msg="Successfully removed."
else
msg="Failed to remove!"
fi
fi
dialog --backtitle "Additional Services" \
--title "Let's Encrypt Client" \
--infobox "\n${msg}" 5 40 ; sleep 3
else
echo "Let's Encrypt Client Setting unchanged."
fi
# LND Auto-Unlock
choice="off"; check=$(echo "${CHOICES}" | grep -c "u")
if [ ${check} -eq 1 ]; then choice="on"; fi

View file

@ -273,12 +273,12 @@ Please go to MAINMENU > SERVICES and activate KEYSEND first.
exit 1;
;;
FULLY_NODED)
appstoreLink="https://testflight.apple.com/join/PuFnSqgi"
appstoreLink="https://apps.apple.com/us/app/fully-noded/id1436425586"
/home/admin/config.scripts/blitz.lcd.sh qr ${appstoreLink}
whiptail --title "Install Fully Noded on your iOS device" \
--yes-button "continue" \
--no-button "link as QR code" \
--yesno "At the moment this app is in public beta testing:\n\n${appstoreLink}\n\nJoin testing and follow ALL instructions.\n\nWhen installed and started -> continue" 10 60
--yesno "Download the app from the AppStore:\n\n${appstoreLink}\n\nWhen installed and started -> continue" 8 60
if [ $? -eq 1 ]; then
/home/admin/config.scripts/blitz.lcd.sh qr-console ${appstoreLink}
fi

View file

@ -5,6 +5,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [0.3.0] - 2020-07-19
### Added
- add BlitzError Class
## [0.2.0] - 2020-05-23
### Added
- add write() to BlitzPy config Classes

View file

@ -1,8 +1,10 @@
# -*- coding: utf-8 -*-
from .config import RaspiBlitzConfig, RaspiBlitzInfo
from .exceptions import BlitzError
__all__ = [
'RaspiBlitzConfig',
'RaspiBlitzInfo',
'BlitzError'
]

View file

@ -0,0 +1,16 @@
from datetime import datetime
TS_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
class BlitzError(Exception):
def __init__(self, short: str, details: dict = None, org: Exception = None):
self.short: str = str(short)
if details:
self.details: dict = details
self.details.update({'timestamp': datetime.utcnow().strftime(TS_FORMAT)})
else:
self.details = dict()
self.details['timestamp'] = datetime.utcnow().strftime(TS_FORMAT)
self.org: Exception = org

View file

@ -4,5 +4,5 @@
# 3) we can import it into your module module
"""
__version_info__ = ('0', '2', '0')
__version_info__ = ('0', '3', '0')
__version__ = '.'.join(__version_info__)

Binary file not shown.

Binary file not shown.

View file

@ -287,12 +287,15 @@ fi
# BTCPAYSERVER
if [ "${BTCPayServer}" = "on" ]; then
echo "Provisioning BTCPAYSERVER on TOR - run on after bootup script" >> ${logFile}
#sudo sed -i "s/^message=.*/message='Setup BTCPay (takes time)'/g" ${infoFile}
#sudo -u admin /home/admin/config.scripts/bonus.btcpayserver.sh on >> ${logFile} 2>&1
echo "Provisioning BTCPAYSERVER on TOR - running setup" >> ${logFile}
sudo sed -i "s/^message=.*/message='Setup BTCPay (takes time)'/g" ${infoFile}
sudo -u admin /home/admin/config.scripts/bonus.btcpayserver.sh on >> ${logFile} 2>&1
#echo "Provisioning BTCPAYSERVER on TOR - run on after bootup script" >> ${logFile}
# because BTCPAY server freezes during recovery .. it will get installed after reboot
echo "sudo -u admin /home/admin/config.scripts/bonus.btcpayserver.sh on" >> /home/admin/setup.sh
#echo "sudo -u admin /home/admin/config.scripts/bonus.btcpayserver.sh on" >> /home/admin/setup.sh
#sudo chmod +x /home/admin/setup.sh >> ${logFile}
#sudo ls -la /home/admin/setup.sh >> ${logFile}
else
echo "Provisioning BTCPayServer - keep default" >> ${logFile}

View file

@ -58,6 +58,46 @@ if [ "${setupStep}" != "100" ]; then
fi
sudo chmod 777 ${infoFile}
################################
# IDENTIFY CPU ARCHITECTURE
################################
cpu="?"
isARM=$(uname -m | grep -c 'arm')
isAARCH64=$(uname -m | grep -c 'aarch64')
isX86_64=$(uname -m | grep -c 'x86_64')
if [ ${isARM} -gt 0 ]; then
cpu="arm"
elif [ ${isAARCH64} -gt 0 ]; then
cpu="aarch64"
elif [ ${isX86_64} -gt 0 ]; then
cpu="x86_64"
fi
echo "cpu=${cpu}" >> $infoFile
################################
# IDENTIFY BASEIMAGE
################################
baseImage="?"
isDietPi=$(uname -n | grep -c 'DietPi')
isRaspbian=$(cat /etc/os-release 2>/dev/null | grep -c 'Raspbian')
isArmbian=$(cat /etc/os-release 2>/dev/null | grep -c 'Debian')
isUbuntu=$(cat /etc/os-release 2>/dev/null | grep -c 'Ubuntu')
if [ ${isRaspbian} -gt 0 ]; then
baseImage="raspbian"
fi
if [ ${isArmbian} -gt 0 ]; then
baseImage="armbian"
fi
if [ ${isUbuntu} -gt 0 ]; then
baseImage="ubuntu"
fi
if [ ${isDietPi} -gt 0 ]; then
baseImage="dietpi"
fi
echo "baseimage=${baseImage}" >> $infoFile
# resetting start count files
echo "SYSTEMD RESTART LOG: blockchain (bitcoind/litecoind)" > /home/admin/systemd.blockchain.log
echo "SYSTEMD RESTART LOG: lightning (LND)" > /home/admin/systemd.lightning.log
@ -142,7 +182,9 @@ if [ ${afterSetupScriptExists} -eq 1 ]; then
# echo out script to journal logs
sudo cat /home/admin/setup.sh
# execute the after boot script
sudo /home/admin/setup.sh
echo "Logs in stored to: /home/admin/raspiblitz.recover.log"
echo "\n***** RUNNING AFTER BOOT SCRIPT ******** " >> /home/admin/raspiblitz.recover.log
sudo /home/admin/setup.sh >> /home/admin/raspiblitz.recover.log
# delete the after boot script
sudo rm /home/admin/setup.sh
# reboot again
@ -536,46 +578,6 @@ else
sudo chown admin:admin /mnt/hdd/app-data/subscriptions
fi
################################
# IDENTIFY CPU ARCHITECTURE
################################
cpu="?"
isARM=$(uname -m | grep -c 'arm')
isAARCH64=$(uname -m | grep -c 'aarch64')
isX86_64=$(uname -m | grep -c 'x86_64')
if [ ${isARM} -gt 0 ]; then
cpu="arm"
elif [ ${isAARCH64} -gt 0 ]; then
cpu="aarch64"
elif [ ${isX86_64} -gt 0 ]; then
cpu="x86_64"
fi
echo "cpu=${cpu}" >> $infoFile
################################
# IDENTIFY BASEIMAGE
################################
baseImage="?"
isDietPi=$(uname -n | grep -c 'DietPi')
isRaspbian=$(cat /etc/os-release 2>/dev/null | grep -c 'Raspbian')
isArmbian=$(cat /etc/os-release 2>/dev/null | grep -c 'Debian')
isUbuntu=$(cat /etc/os-release 2>/dev/null | grep -c 'Ubuntu')
if [ ${isRaspbian} -gt 0 ]; then
baseImage="raspbian"
fi
if [ ${isArmbian} -gt 0 ]; then
baseImage="armbian"
fi
if [ ${isUbuntu} -gt 0 ]; then
baseImage="ubuntu"
fi
if [ ${isDietPi} -gt 0 ]; then
baseImage="dietpi"
fi
echo "baseimage=${baseImage}" >> $infoFile
################################
# STRESSTEST RASPBERRY PI
################################

View file

@ -12,7 +12,7 @@ from pathlib import Path
import grpc
import requests
import toml
from blitzpy import RaspiBlitzConfig
from blitzpy import RaspiBlitzConfig, BlitzError
from lndlibs import rpc_pb2 as lnrpc
from lndlibs import rpc_pb2_grpc as rpcstub
@ -34,6 +34,12 @@ if len(sys.argv) <= 1 or sys.argv[1] == "-h" or sys.argv[1] == "help":
print("# blitz.subscriptions.ip2tor.py ip-by-tor onionaddress")
sys.exit(1)
# constants for standard services
SERVICE_LND_REST_API = "LND-REST-API"
SERVICE_LND_GRPC_API = "LND-GRPC-API"
SERVICE_LNBITS = "LNBITS"
SERVICE_BTCPAY = "BTCPAY"
#####################
# BASIC SETTINGS
#####################
@ -69,17 +75,6 @@ else:
is_testnet = False
#####################
# HELPER CLASSES
#####################
class BlitzError(Exception):
def __init__(self, errorShort, errorLong="", errorException=None):
self.errorShort = str(errorShort)
self.errorLong = str(errorLong)
self.errorException = errorException
#####################
# HELPER FUNCTIONS
#####################
@ -90,9 +85,9 @@ def eprint(*args, **kwargs):
def handleException(e):
if isinstance(e, BlitzError):
eprint(e.errorLong)
eprint(e.errorException)
print("error='{0}'".format(e.errorShort))
eprint(e.details)
eprint(e.org)
print("error='{0}'".format(e.short))
else:
eprint(e)
print("error='{0}'".format(str(e)))
@ -149,17 +144,17 @@ def apiGetHosts(session, shopurl):
try:
response = session.get(url)
except Exception as e:
raise BlitzError("failed HTTP request", url, e)
raise BlitzError("failed HTTP request", {'url': url}, e)
if response.status_code != 200:
raise BlitzError("failed HTTP code", response.status_code, )
raise BlitzError("failed HTTP code", {'status_code': response.status_code})
# parse & validate data
try:
jData = json.loads(response.content)
except Exception as e:
raise BlitzError("failed JSON parsing", response.content, e)
raise BlitzError("failed JSON parsing", {'content': response.content}, e)
if not isinstance(jData, list):
raise BlitzError("hosts not list", response.content)
raise BlitzError("hosts not list", {'content': response.content})
for idx, hostEntry in enumerate(jData):
try:
# ignore if not offering tor bridge
@ -187,7 +182,7 @@ def apiGetHosts(session, shopurl):
# shorten names to 20 chars max
hostEntry['name'] = hostEntry['name'][:20]
except Exception as e:
raise BlitzError("failed host entry pasring", str(hostEntry), e)
raise BlitzError("failed host entry pasring", hostEntry, e)
hosts.append(hostEntry)
@ -210,11 +205,11 @@ def apiPlaceOrderNew(session, shopurl, hostid, toraddressWithPort):
try:
response = session.post(url, data=postData)
except Exception as e:
raise BlitzError("failed HTTP request", url, e)
raise BlitzError("failed HTTP request", {'url': url}, e)
if response.status_code == 420:
raise BlitzError("forwarding this address was rejected", response.status_code)
raise BlitzError("forwarding this address was rejected", {'status_code': response.status_code})
if response.status_code != 201:
raise BlitzError("failed HTTP code", response.status_code)
raise BlitzError("failed HTTP code", {'status_code': response.status_code})
# parse & validate data
try:
@ -223,7 +218,7 @@ def apiPlaceOrderNew(session, shopurl, hostid, toraddressWithPort):
print("error='MISSING ID'")
return
except Exception as e:
raise BlitzError("failed JSON parsing", response.status_code, e)
raise BlitzError("failed JSON parsing", {'status_code': response.status_code}, e)
return jData['id']
@ -235,11 +230,11 @@ def apiPlaceOrderExtension(session, shopurl, bridgeid):
try:
response = session.post(url)
except Exception as e:
raise BlitzError("failed HTTP request", url, e)
raise BlitzError("failed HTTP request", {'url': url}, e)
if response.status_code == 420:
raise BlitzError("forwarding this address was rejected", response.status_code)
raise BlitzError("forwarding this address was rejected", {'status_code': response.status_code})
if response.status_code != 200 and response.status_code != 201:
raise BlitzError("failed HTTP code", response.status_code)
raise BlitzError("failed HTTP code", {'status_code': response.status_code})
# parse & validate data
print("# parse")
@ -249,12 +244,12 @@ def apiPlaceOrderExtension(session, shopurl, bridgeid):
print("error='MISSING ID'")
return
except Exception as e:
raise BlitzError("failed JSON parsing", response.content, e)
raise BlitzError("failed JSON parsing", {'content': response.content}, e)
return jData['po_id']
def apiGetOrder(session, shopurl, orderid):
def apiGetOrder(session, shopurl, orderid) -> dict:
print("# apiGetOrder")
# make HTTP request
@ -262,19 +257,19 @@ def apiGetOrder(session, shopurl, orderid):
try:
response = session.get(url)
except Exception as e:
raise BlitzError("failed HTTP request", url, e)
raise BlitzError("failed HTTP request", {'url': url}, e)
if response.status_code != 200:
raise BlitzError("failed HTTP code", response.status_code)
raise BlitzError("failed HTTP code", {'status_code': response.status_code})
# parse & validate data
try:
jData = json.loads(response.content)
if len(jData['item_details']) == 0:
raise BlitzError("missing item", response.content)
raise BlitzError("missing item", {'content': response.content})
if len(jData['ln_invoices']) > 1:
raise BlitzError("more than one invoice", response.content)
raise BlitzError("more than one invoice", {'content': response.content})
except Exception as e:
raise BlitzError("failed JSON parsing", response.content, e)
raise BlitzError("failed JSON parsing", {'content': response.content}, e)
return jData
@ -287,16 +282,16 @@ def apiGetBridgeStatus(session, shopurl, bridgeid):
try:
response = session.get(url)
except Exception as e:
raise BlitzError("failed HTTP request", url, e)
raise BlitzError("failed HTTP request", {'url': url}, e)
if response.status_code != 200:
raise BlitzError("failed HTTP code", response.status_code)
raise BlitzError("failed HTTP code", {'status_code': response.status_code})
# parse & validate data
try:
jData = json.loads(response.content)
if len(jData['id']) == 0:
raise BlitzError("missing id", response.content)
raise BlitzError("missing id", {'content': response.content})
except Exception as e:
raise BlitzError("failed JSON parsing", response.content, e)
raise BlitzError("failed JSON parsing", {'content': response.content}, e)
return jData
@ -321,10 +316,10 @@ def lndDecodeInvoice(lnInvoiceString):
# validate results
if response.num_msat <= 0:
raise BlitzError("zero invoice not allowed", lnInvoiceString)
raise BlitzError("zero invoice not allowed", {'invoice': lnInvoiceString})
except Exception as e:
raise BlitzError("failed LND invoice decoding", lnInvoiceString, e)
raise BlitzError("failed LND invoice decoding", {'invoice': lnInvoiceString}, e)
return response
@ -345,10 +340,10 @@ def lndPayInvoice(lnInvoiceString):
# validate results
if len(response.payment_error) > 0:
raise BlitzError(response.payment_error, lnInvoiceString)
raise BlitzError(response.payment_error, {'invoice': lnInvoiceString})
except Exception as e:
raise BlitzError("payment failed", lnInvoiceString, e)
raise BlitzError("payment failed", {'invoice': lnInvoiceString}, e)
return response
@ -411,6 +406,8 @@ def shopOrder(shopUrl, hostid, servicename, torTarget, duration, msatsFirst, msa
bridge = apiGetBridgeStatus(session, shopUrl, bridge_id)
if bridge['status'] == "A":
break
if bridge['status'] == "R":
break
if loopCount > 120:
raise BlitzError("timeout bridge not getting ready", bridge)
@ -430,6 +427,12 @@ def shopOrder(shopUrl, hostid, servicename, torTarget, duration, msatsFirst, msa
if (secondsDelivered + 600) < int(duration):
contract_breached = True
warning_text = "delivered duration shorter than advertised"
if bridge['status'] == "R":
contract_breached = True
try:
warningTXT = "rejected: {0}".format(bridge['message'])
except Exception as e:
warningTXT = "rejected: n/a"
# create subscription data for storage
subscription = dict()
@ -437,7 +440,7 @@ def shopOrder(shopUrl, hostid, servicename, torTarget, duration, msatsFirst, msa
subscription['id'] = bridge['id']
subscription['name'] = servicename
subscription['shop'] = shopUrl
subscription['active'] = True
subscription['active'] = not contract_breached
subscription['ip'] = bridge_ip
subscription['port'] = bridge_port
subscription['duration'] = int(duration)
@ -471,7 +474,7 @@ def shopOrder(shopUrl, hostid, servicename, torTarget, duration, msatsFirst, msa
except Exception as e:
eprint(e)
raise BlitzError("fail on subscription storage", str(subscription), e)
raise BlitzError("fail on subscription storage", subscription, e)
print("# OK - BRIDGE READY: {0}:{1} -> {2}".format(bridge_ip, bridge_port, torTarget))
return subscription
@ -521,6 +524,13 @@ def subscriptionExtend(shopUrl, bridgeid, durationAdvertised, msatsNext, bridge_
print("## Loop {0}".format(loopCount))
try:
bridge = apiGetBridgeStatus(session, shopUrl, bridgeid)
if bridge['status'] == "R":
contract_breached = True
try:
warningTXT = "rejected: {0}".format(bridge['message'])
except Exception as e:
warningTXT = "rejected: n/a"
break
if bridge['suspend_after'] != bridge_suspendafter:
break
except Exception as e:
@ -562,7 +572,7 @@ def subscriptionExtend(shopUrl, bridgeid, durationAdvertised, msatsNext, bridge_
except Exception as e:
eprint(e)
raise BlitzError("fail on subscription storage", "", e)
raise BlitzError("fail on subscription storage", org=e)
print("# BRIDGE GOT EXTENDED: {0} -> {1}".format(bridge_suspendafter, bridge['suspend_after']))
@ -648,7 +658,8 @@ Try again later, enter another address or cancel.
choices=choices, title="Available Subscriptions")
# if user cancels
if code != d.OK: sys.exit(0)
if code != d.OK:
sys.exit(0)
# get data of selected
seletedIndex = int(tag)
@ -696,7 +707,8 @@ More information on the service you can find under:
height=30)
# if user AGREED break loop and continue with selected host
if code == "extra": break
if code == "extra":
break
############################
# PHASE 3: Make Subscription
@ -713,18 +725,25 @@ More information on the service you can find under:
exitcode = 0
if (be.errorShort == "timeout on waiting for extending bridge" or
be.errorShort == "fail on subscription storage" or
be.errorShort == "invalid port" or
be.errorShort == "timeout bridge not getting ready"):
try:
message = be.details['message']
except KeyError:
message = ""
if (be.short == "timeout on waiting for extending bridge" or
be.short == "fail on subscription storage" or
be.short == "invalid port" or
be.short == "timeout bridge not getting ready"):
# error happened after payment
exitcode = Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
You DID PAY the initial fee.
But the service was not able to provide service.
Subscription will be ignored.
Error: {0}
'''.format(be.errorShort), title="Error on Subscription", extra_button=True, extra_label="Details")
Message: {1}
'''.format(be.short, message), title="Error on Subscription", extra_button=True, extra_label="Details")
else:
# error happened before payment
@ -732,8 +751,10 @@ Error: {0}
You DID NOT PAY the initial fee.
The service was not able to provide service.
Subscription will be ignored.
Error: {0}
'''.format(be.errorShort), title="Error on Subscription", extra_button=True, extra_label="Details")
Message: {1}
'''.format(be.short, message), title="Error on Subscription", extra_button=True, extra_label="Details")
# show more details (when user used extra button)
if exitcode == Dialog.EXTRA:
@ -741,13 +762,13 @@ Error: {0}
print('###### ERROR DETAIL FOR DEBUG #######')
print("")
print("Error Short:")
print(be.errorShort)
print(be.short)
print('Shop:')
print(shopurl)
print('Bridge:')
print(str(host))
print("Error Detail:")
print(be.errorLong)
print(be.details)
print("")
input("Press Enter to continue ...")
@ -770,7 +791,7 @@ Error: {0}
sys.exit(1)
# if LND REST or LND GRPC service ... add bridge IP to TLS
if servicename == "LND-REST-API" or servicename == "LND-GRPC-API":
if blitzServiceName == SERVICE_LND_REST_API or blitzServiceName == SERVICE_LND_GRPC_API:
os.system("sudo /home/admin/config.scripts/lnd.tlscert.sh ip-add {0}".format(subscription['ip']))
os.system("sudo /home/admin/config.scripts/lnd.credentials.sh reset tls")
os.system("sudo /home/admin/config.scripts/lnd.credentials.sh sync")
@ -785,7 +806,7 @@ You may want to consider to cancel the subscription later.
# decide if https:// address
protocol = ""
if blitzServiceName == "LNBITS":
if blitzServiceName == SERVICE_LNBITS:
protocol = "https://"
# Give final result feedback to user
@ -821,13 +842,11 @@ MAIN MENU > Manage Subscriptions > My Subscriptions
# CREATE SSH DIALOG
# use for ssh shell menu
###############
if sys.argv[1] == "create-ssh-dialog":
def create_ssh_dialog():
# check parameters
try:
if len(sys.argv) <= 4:
raise BlitzError("incorrect parameters", "")
raise BlitzError("incorrect parameters")
except Exception as e:
handleException(e)
@ -839,17 +858,16 @@ if sys.argv[1] == "create-ssh-dialog":
sys.exit()
###############
# SHOP LIST
# call from web interface
###############
if sys.argv[1] == "shop-list":
def shop_list():
# check parameters
try:
if len(sys.argv) <= 2:
raise BlitzError("incorrect parameters", "")
raise BlitzError("incorrect parameters")
except Exception as e:
handleException(e)
@ -865,17 +883,16 @@ if sys.argv[1] == "shop-list":
sys.exit(0)
##########################
# SHOP ORDER
# call from web interface
##########################
if sys.argv[1] == "shop-order":
def shop_order():
# check parameters
try:
if len(sys.argv) <= 8:
raise BlitzError("incorrect parameters", "")
raise BlitzError("incorrect parameters")
except Exception as e:
handleException(e)
@ -900,13 +917,12 @@ if sys.argv[1] == "shop-order":
except Exception as e:
handleException(e)
#######################
# SUBSCRIPTIONS LIST
# call in intervals from background process
#######################
if sys.argv[1] == "subscriptions-list":
def subscriptions_list():
try:
if Path(SUBSCRIPTIONS_FILE).is_file():
@ -921,15 +937,12 @@ if sys.argv[1] == "subscriptions-list":
except Exception as e:
handleException(e)
sys.exit(0)
#######################
# SUBSCRIPTIONS RENEW
# call in intervals from background process
#######################
if sys.argv[1] == "subscriptions-renew":
def subscriptions_renew():
print("# RUNNING subscriptions-renew")
# check parameters
@ -976,16 +989,16 @@ if sys.argv[1] == "subscriptions-renew":
subs = toml.load(SUBSCRIPTIONS_FILE)
for sub in subs['subscriptions_ip2tor']:
if sub['id'] == subscription['id']:
sub['warning'] = "Exception on Renew: {0}".format(be.errorShort)
if be.errorShort == "invoice bigger amount than advertised":
sub['warning'] = "Exception on Renew: {0}".format(be.short)
if be.short == "invoice bigger amount than advertised":
sub['contract_breached'] = True
sub['active'] = False
with open(SUBSCRIPTIONS_FILE, 'w') as writer:
writer.write(toml.dumps(subs))
writer.close()
break
print("# BLITZERROR on subscriptions-renew of subscription index {0}: {1}".format(idx, be.errorShort))
print("# {0}".format(be.errorShort))
print("# BLITZERROR on subscriptions-renew of subscription index {0}: {1}".format(idx, be.short))
print("# {0}".format(be.short))
except Exception as e:
print("# EXCEPTION on subscriptions-renew of subscription index {0}".format(idx))
@ -996,18 +1009,17 @@ if sys.argv[1] == "subscriptions-renew":
# output - not needed only for debug logs
print("# DONE subscriptions-renew")
sys.exit(1)
#######################
# SUBSCRIPTION CANCEL
# call in intervalls from background process
# call in intervals from background process
#######################
if sys.argv[1] == "subscription-cancel":
def subscription_cancel():
# check parameters
try:
if len(sys.argv) <= 2:
raise BlitzError("incorrect parameters", "")
raise BlitzError("incorrect parameters")
except Exception as e:
handleException(e)
@ -1032,30 +1044,28 @@ if sys.argv[1] == "subscription-cancel":
except Exception as e:
handleException(e)
sys.exit(0)
#######################
# GET ADDRESS BY SERVICENAME
# GET ADDRESS BY SERVICE NAME
# gets called by other scripts to check if service has a ip2tor bridge address
# output is bash key/value style so that it can be imported with source
#######################
if sys.argv[1] == "subscription-by-service":
def subscription_by_service():
# check parameters
try:
if len(sys.argv) <= 2:
raise BlitzError("incorrect parameters", "")
raise BlitzError("incorrect parameters")
except Exception as e:
handleException(e)
servicename = sys.argv[2]
service_name = sys.argv[2]
try:
if os.path.isfile(SUBSCRIPTIONS_FILE):
os.system("sudo chown admin:admin {0}".format(SUBSCRIPTIONS_FILE))
subs = toml.load(SUBSCRIPTIONS_FILE)
for idx, sub in enumerate(subs['subscriptions_ip2tor']):
if sub['active'] and sub['name'] == servicename:
if sub['active'] and sub['name'] == service_name:
print("type='{0}'".format(sub['type']))
print("ip='{0}'".format(sub['ip']))
print("port='{0}'".format(sub['port']))
@ -1063,24 +1073,22 @@ if sys.argv[1] == "subscription-by-service":
sys.exit(0)
print("error='not found'")
sys.exit(0)
except Exception as e:
handleException(e)
sys.exit(1)
#######################
# GET IP BY ONIONADDRESS
# GET IP BY ONION ADDRESS
# gets called by other scripts to check if a onion address as a IP2TOR bridge
# output is bash key/value style so that it can be imported with source
#######################
if sys.argv[1] == "ip-by-tor":
def ip_by_tor():
# check parameters
try:
if len(sys.argv) <= 2:
raise BlitzError("incorrect parameters", "")
raise BlitzError("incorrect parameters")
except Exception as e:
handleException(e)
@ -1100,12 +1108,41 @@ if sys.argv[1] == "ip-by-tor":
sys.exit(0)
print("error='not found'")
sys.exit(0)
except Exception as e:
handleException(e)
sys.exit(1)
# unknown command
print("# unknown command")
def main():
if sys.argv[1] == "create-ssh-dialog":
create_ssh_dialog()
elif sys.argv[1] == "shop-list":
shop_list()
elif sys.argv[1] == "shop-order":
shop_order()
elif sys.argv[1] == "subscriptions-list":
subscriptions_list()
elif sys.argv[1] == "subscriptions-renew":
subscriptions_renew()
elif sys.argv[1] == "subscription-cancel":
subscription_cancel()
elif sys.argv[1] == "subscription-by-service":
subscription_by_service()
elif sys.argv[1] == "ip-by-tor":
ip_by_tor()
else:
# unknown command
print("# unknown command")
if __name__ == '__main__':
main()

View file

@ -10,7 +10,7 @@ from pathlib import Path
import requests
import toml
from blitzpy import RaspiBlitzConfig
from blitzpy import RaspiBlitzConfig,BlitzError
#####################
# SCRIPT INFO
@ -30,6 +30,12 @@ if len(sys.argv) <= 1 or sys.argv[1] == "-h" or sys.argv[1] == "help":
print("# blitz.subscriptions.ip2tor.py subscription-cancel <id>")
sys.exit(1)
# constants for standard services
SERVICE_LND_REST_API = "LND-REST-API"
SERVICE_LND_GRPC_API = "LND-GRPC-API"
SERVICE_LNBITS = "LNBITS"
SERVICE_BTCPAY = "BTCPAY"
#####################
# BASIC SETTINGS
#####################
@ -49,6 +55,7 @@ if cfg.run_behind_tor:
# HELPER CLASSES
#####################
# ToDo(frennkie) replace this with updated BlitzError from blitzpy
class BlitzError(Exception):
def __init__(self, errorShort, errorLong="", errorException=None):
self.errorShort = str(errorShort)
@ -75,19 +82,19 @@ def handleException(e):
sys.exit(1)
def getsubdomain(fulldomainstring):
return fulldomainstring.split('.')[0]
def get_subdomain(fulldomain_str):
return fulldomain_str.split('.')[0]
############################
# API Calls to DNS Servcies
# API Calls to DNS Services
############################
def duckDNSupdate(domain, token, ip):
def duckdns_update(domain, token, ip):
print("# duckDNS update IP API call for {0}".format(domain))
# make HTTP request
url = "https://www.duckdns.org/update?domains={0}&token={1}&ip={2}".format(getsubdomain(domain), token, ip)
url = "https://www.duckdns.org/update?domains={0}&token={1}&ip={2}".format(get_subdomain(domain), token, ip)
try:
response = session.get(url)
if response.status_code != 200:
@ -102,41 +109,33 @@ def duckDNSupdate(domain, token, ip):
# PROCESS FUNCTIONS
#####################
def subscriptionsNew(ip, dnsservice, id, token, target):
# id needs to the full domain name
def subscriptions_new(ip, dnsservice, id, token, target):
# id needs to be the full domain name
if id.find(".") == -1:
raise BlitzError("not a fully qualified domainname", dnsservice_id)
# ToDo(frennkie) dnsservice_id doesn't exit
raise BlitzError("not a fully qualified domain name", dnsservice_id)
# check if id already exists
if len(getSubscription(id)) > 0:
if len(get_subscription(id)) > 0:
raise BlitzError("id already exists", id)
# make sure lets encrypt client is installed
os.system("/home/admin/config.scripts/bonus.letsencrypt.sh on")
# dyndns
realip = ip
real_ip = ip
if ip == "dyndns":
updateURL = ""
update_url = ""
if dnsservice == "duckdns":
updateURL = "https://www.duckdns.org/update?domains={0}&token={1}".format(getsubdomain(domain), token, ip)
subprocess.run(['/home/admin/config.scriprs/internet.dyndomain.sh', 'on', id, updateURL],
# ToDo(frennkie) domain doesn't exit
update_url = "https://www.duckdns.org/update?domains={0}&token={1}".format(get_subdomain(domain), token, ip)
subprocess.run(['/home/admin/config.scriprs/internet.dyndomain.sh', 'on', id, update_url],
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
realip = cfg.public_ip
real_ip = cfg.public_ip
# update DNS with actual IP
if dnsservice == "duckdns":
duckDNSupdate(getsubdomain(id), token, realip)
# run the ACME script
print("# Running letsencrypt ACME script ...")
acmeResult = subprocess.Popen(
["/home/admin/config.scripts/bonus.letsencrypt.sh", "issue-cert", dnsservice, id, token, target],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf8')
out, err = acmeResult.communicate()
if out.find("error=") > -1:
time.sleep(6)
raise BlitzError("letsancrypt acme failed", out)
duckdns_update(get_subdomain(id), token, real_ip)
# create subscription data for storage
subscription = dict()
@ -172,30 +171,40 @@ def subscriptionsNew(ip, dnsservice, id, token, target):
eprint(e)
raise BlitzError("fail on subscription storage", str(subscription), e)
# run the ACME script
print("# Running letsencrypt ACME script ...")
acme_result = subprocess.Popen(
["/home/admin/config.scripts/bonus.letsencrypt.sh", "issue-cert", dnsservice, id, token, target],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf8')
out, err = acme_result.communicate()
eprint(str(out))
eprint(str(err))
if out.find("error=") > -1:
time.sleep(6)
raise BlitzError("letsancrypt acme failed", out)
print("# OK - LETSENCRYPT DOMAIN IS READY")
return subscription
def subscriptionsCancel(id):
# ToDo(frennkie) id is not used..
def subscriptions_cancel(s_id):
os.system("sudo chown admin:admin {0}".format(SUBSCRIPTIONS_FILE))
subs = toml.load(SUBSCRIPTIONS_FILE)
newList = []
removedCert = None
new_list = []
removed_cert = None
for idx, sub in enumerate(subs['subscriptions_letsencrypt']):
if sub['id'] != subscriptionID:
newList.append(sub)
if sub['id'] != s_id:
new_list.append(sub)
else:
removedCert = sub
subs['subscriptions_letsencrypt'] = newList
removed_cert = sub
subs['subscriptions_letsencrypt'] = new_list
# run the ACME script to remove cert
if removedCert:
acmeResult = subprocess.Popen(
["/home/admin/config.scripts/bonus.letsencrypt.sh", "remove-cert", removedCert['id'],
removedCert['target']], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf8')
out, err = acmeResult.communicate()
if removed_cert:
acme_result = subprocess.Popen(
["/home/admin/config.scripts/bonus.letsencrypt.sh", "remove-cert", removed_cert['id'],
removed_cert['target']], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf8')
out, err = acme_result.communicate()
if out.find("error=") > -1:
time.sleep(6)
raise BlitzError("letsencrypt acme failed", out)
@ -210,7 +219,7 @@ def subscriptionsCancel(id):
# todo: deinstall letsencrypt if this was last subscription
def getSubscription(subscriptionID):
def get_subscription(subscription_id):
try:
if Path(SUBSCRIPTIONS_FILE).is_file():
@ -221,7 +230,7 @@ def getSubscription(subscriptionID):
if "subscriptions_letsencrypt" not in subs:
return []
for idx, sub in enumerate(subs['subscriptions_letsencrypt']):
if sub['id'] == subscriptionID:
if sub['id'] == subscription_id:
return sub
return []
@ -229,7 +238,7 @@ def getSubscription(subscriptionID):
return []
def getDomainByIP(ip):
def get_domain_by_ip(ip):
# does subscriptin file exists
if Path(SUBSCRIPTIONS_FILE).is_file():
os.system("sudo chown admin:admin {0}".format(SUBSCRIPTIONS_FILE))
@ -251,7 +260,7 @@ def getDomainByIP(ip):
raise BlitzError("no match")
def menuMakeSubscription():
def menu_make_subscription():
# late imports - so that rest of script can run also if dependency is not available
from dialog import Dialog
@ -297,7 +306,7 @@ If you havent already go to https://duckdns.org
title="DuckDNS Domain")
subdomain = text.strip()
subdomain = subdomain.split(' ')[0]
subdomain = getsubdomain(subdomain)
subdomain = get_subdomain(subdomain)
domain = "{0}.duckdns.org".format(subdomain)
os.system("clear")
@ -324,7 +333,7 @@ This looks not like a valid subdomain.
if len(token) < 20:
Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
This looks not like a valid token.
''', title="Unvalid Input")
''', title="Invalid Input")
sys.exit(0)
else:
@ -348,7 +357,7 @@ This looks not like a valid token.
"\nChoose the kind of IP you want to use:",
choices=choices, width=60, height=10, title="Select Service")
# if user chosses CANCEL
# if user chooses CANCEL
os.system("clear")
if code != d.OK:
sys.exit(0)
@ -360,16 +369,16 @@ This looks not like a valid token.
if tag == "IP2TOR":
# get all active IP2TOR subscriptions (just in case)
ip2torSubs = []
ip2tor_subs = []
if Path(SUBSCRIPTIONS_FILE).is_file():
os.system("sudo chown admin:admin {0}".format(SUBSCRIPTIONS_FILE))
subs = toml.load(SUBSCRIPTIONS_FILE)
for idx, sub in enumerate(subs['subscriptions_ip2tor']):
if sub['active']:
ip2torSubs.append(sub)
ip2tor_subs.append(sub)
# when user has no IP2TOR subs yet
if len(ip2torSubs) == 0:
if len(ip2tor_subs) == 0:
Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
You have no active IP2TOR subscriptions.
Create one first and try again.
@ -378,7 +387,7 @@ Create one first and try again.
# let user select a IP2TOR subscription
choices = []
for idx, sub in enumerate(ip2torSubs):
for idx, sub in enumerate(ip2tor_subs):
choices.append(("{0}".format(idx), "IP2TOR {0} {1}:{2}".format(sub['name'], sub['ip'], sub['port'])))
d = Dialog(dialog="dialog", autowidgetsize=True)
@ -392,8 +401,8 @@ Create one first and try again.
sys.exit(0)
# get the slected IP2TOR bridge
ip2torSelect = ip2torSubs[int(tag)]
ip = ip2torSelect["ip"]
ip2tor_select = ip2tor_subs[int(tag)]
ip = ip2tor_select["ip"]
target = "tor"
elif tag == "DYNDNS":
@ -419,13 +428,13 @@ Create one first and try again.
if len(ip) == 0:
Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
This looks not like a valid IP.
''', title="Unvalid Input")
''', title="Invalid Input")
sys.exit(0)
# create the letsencrypt subscription
try:
os.system("clear")
subscription = subscriptionsNew(ip, dnsservice, domain, token, target)
subscription = subscriptions_new(ip, dnsservice, domain, token, target)
# success dialog
Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
@ -453,19 +462,15 @@ Unknown Error happened - please report to developers:
# CREATE SSH DIALOG
# use for ssh shell menu
###############
def create_ssh_dialog():
menu_make_subscription()
if sys.argv[1] == "create-ssh-dialog":
menuMakeSubscription()
sys.exit()
##########################
# SUBSCRIPTIONS NEW
# call from web interface
##########################
if sys.argv[1] == "subscription-new":
def subscription_new():
# check parameters
try:
if len(sys.argv) <= 5:
@ -484,7 +489,7 @@ if sys.argv[1] == "subscription-new":
# create the subscription
try:
subscription = subscriptionsNew(ip, dnsservice_type, dnsservice_id, dnsservice_token, target)
subscription = subscriptions_new(ip, dnsservice_type, dnsservice_id, dnsservice_token, target)
# output json ordered bridge
print(json.dumps(subscription, indent=2))
@ -493,12 +498,11 @@ if sys.argv[1] == "subscription-new":
except Exception as e:
handleException(e)
#######################
# SUBSCRIPTIONS LIST
#######################
if sys.argv[1] == "subscriptions-list":
def subscriptions_list():
try:
if Path(SUBSCRIPTIONS_FILE).is_file():
@ -513,13 +517,11 @@ if sys.argv[1] == "subscriptions-list":
except Exception as e:
handleException(e)
sys.exit(0)
#######################
# SUBSCRIPTION DETAIL
#######################
if sys.argv[1] == "subscription-detail":
def subscription_detail():
# check parameters
try:
if len(sys.argv) <= 2:
@ -527,22 +529,20 @@ if sys.argv[1] == "subscription-detail":
except Exception as e:
handleException(e)
subscriptionID = sys.argv[2]
subscription_id = sys.argv[2]
try:
sub = getSubscription(subscriptionID)
sub = get_subscription(subscription_id)
print(json.dumps(sub, indent=2))
except Exception as e:
handleException(e)
sys.exit(0)
#######################
# DOMAIN BY IP
# to check if an ip has a domain mapping
#######################
if sys.argv[1] == "domain-by-ip":
def domain_by_ip():
# check parameters
try:
if len(sys.argv) <= 2:
@ -554,19 +554,17 @@ if sys.argv[1] == "domain-by-ip":
ip = sys.argv[2]
try:
domain = getDomainByIP(ip)
domain = get_domain_by_ip(ip)
print("domain='{0}'".format(domain))
except Exception as e:
handleException(e)
sys.exit(0)
#######################
# SUBSCRIPTION CANCEL
#######################
if sys.argv[1] == "subscription-cancel":
def subscription_cancel():
# check parameters
try:
if len(sys.argv) <= 2:
@ -574,13 +572,36 @@ if sys.argv[1] == "subscription-cancel":
except Exception as e:
handleException(e)
subscriptionID = sys.argv[2]
subscription_id = sys.argv[2]
try:
subscriptionsCancel(subscriptionID)
subscriptions_cancel(subscription_id)
except Exception as e:
handleException(e)
sys.exit(0)
# unknown command
print("# unknown command")
def main():
if sys.argv[1] == "create-ssh-dialog":
create_ssh_dialog()
elif sys.argv[1] == "domain-by-ip":
domain_by_ip()
elif sys.argv[1] == "subscriptions-list":
subscriptions_list()
elif sys.argv[1] == "subscription-cancel":
subscription_cancel()
elif sys.argv[1] == "subscription-detail":
subscription_detail()
elif sys.argv[1] == "subscription-new":
subscription_new()
else:
# unknown command
print("# unknown command")
if __name__ == '__main__':
main()

View file

@ -15,10 +15,10 @@ from blitzpy import RaspiBlitzConfig
from dialog import Dialog
# constants for standard services
LND_REST_API = "LND-REST-API"
LND_GRPC_API = "LND-GRPC-API"
LNBITS = "LNBITS"
BTCPAY = "BTCPAY"
SERVICE_LND_REST_API = "LND-REST-API"
SERVICE_LND_GRPC_API = "LND-GRPC-API"
SERVICE_LNBITS = "LNBITS"
SERVICE_BTCPAY = "BTCPAY"
# load config
cfg = RaspiBlitzConfig()
@ -32,35 +32,38 @@ SUBSCRIPTIONS_FILE = "/mnt/hdd/app-data/subscriptions/subscriptions.toml"
# HELPER FUNCTIONS
#######################
# ToDo(frennkie) these are not being used!
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
def parseDateIP2TORSERVER(datestr):
return datetime.strptime(datestr, "%Y-%m-%dT%H:%M:%S.%fZ")
def parse_date_ip2tor(date_str):
return datetime.strptime(date_str, "%Y-%m-%dT%H:%M:%S.%fZ")
def secondsLeft(dateObj):
return round((dateObj - datetime.utcnow()).total_seconds())
def seconds_left(date_obj):
return round((date_obj - datetime.utcnow()).total_seconds())
#######################
# SSH MENU FUNCTIONS
#######################
def mySubscriptions():
def my_subscriptions():
# check if any subscriptions are available
countSubscriptions = 0
count_subscriptions = 0
try:
os.system("sudo chown admin:admin {0}".format(SUBSCRIPTIONS_FILE))
subs = toml.load(SUBSCRIPTIONS_FILE)
if 'subscriptions_ip2tor' in subs:
countSubscriptions += len(subs['subscriptions_ip2tor'])
count_subscriptions += len(subs['subscriptions_ip2tor'])
if 'subscriptions_letsencrypt' in subs:
countSubscriptions += len(subs['subscriptions_letsencrypt'])
count_subscriptions += len(subs['subscriptions_letsencrypt'])
except Exception as e:
pass
if countSubscriptions == 0:
print(f"warning: {e}")
if count_subscriptions == 0:
Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
You have no active or inactive subscriptions.
''', title="Info")
@ -69,36 +72,36 @@ You have no active or inactive subscriptions.
# load subscriptions and make dialog choices out of it
choices = []
lookup = {}
lookupIndex = 0
lookup_index = 0
subs = toml.load(SUBSCRIPTIONS_FILE)
# list ip2tor subscriptions
if 'subscriptions_ip2tor' in subs:
for sub in subs['subscriptions_ip2tor']:
# remember subscription under lookupindex
lookupIndex += 1
lookup[str(lookupIndex)] = sub
lookup_index += 1
lookup[str(lookup_index)] = sub
# add to dialog choices
if sub['active']:
activeState = "active"
active_state = "active"
else:
activeState = "in-active"
active_state = "in-active"
name = "IP2TOR Bridge (P:{1}) for {0}".format(sub['name'], sub['port'])
choices.append(("{0}".format(lookupIndex), "{0} ({1})".format(name.ljust(30), activeState)))
choices.append(("{0}".format(lookup_index), "{0} ({1})".format(name.ljust(30), active_state)))
# list letsencrypt subscriptions
if 'subscriptions_letsencrypt' in subs:
for sub in subs['subscriptions_letsencrypt']:
# remember subscription under lookupindex
lookupIndex += 1
lookup[str(lookupIndex)] = sub
lookup_index += 1
lookup[str(lookup_index)] = sub
# add to dialog choices
if sub['active']:
activeState = "active"
active_state = "active"
else:
activeState = "in-active"
active_state = "in-active"
name = "LETSENCRYPT {0}".format(sub['id'])
choices.append(("{0}".format(lookupIndex), "{0} ({1})".format(name.ljust(30), activeState)))
choices.append(("{0}".format(lookup_index), "{0} ({1})".format(name.ljust(30), active_state)))
# show menu with options
d = Dialog(dialog="dialog", autowidgetsize=True)
@ -111,15 +114,15 @@ You have no active or inactive subscriptions.
if code != d.OK:
return
# get data of selected subscrption
selectedSub = lookup[str(tag)]
# get data of selected subscription
selected_sub = lookup[str(tag)]
# show details of selected
d = Dialog(dialog="dialog", autowidgetsize=True)
d.set_background_title("My Subscriptions")
if selectedSub['type'] == "letsencrypt-v1":
if len(selectedSub['warning']) > 0:
selectedSub['warning'] = "\n{0}".format(selectedSub['warning'])
if selected_sub['type'] == "letsencrypt-v1":
if len(selected_sub['warning']) > 0:
selected_sub['warning'] = "\n{0}".format(selected_sub['warning'])
text = '''
This is a LetsEncrypt subscription using the free DNS service
{dnsservice}
@ -135,17 +138,17 @@ The state of the subscription is: {active} {warning}
The following additional information is available:
{description}
'''.format(dnsservice=selectedSub['dnsservice_type'],
domain=selectedSub['id'],
ip=selectedSub['ip'],
active="ACTIVE" if selectedSub['active'] else "NOT ACTIVE",
warning=selectedSub['warning'],
description=selectedSub['description']
'''.format(dnsservice=selected_sub['dnsservice_type'],
domain=selected_sub['id'],
ip=selected_sub['ip'],
active="ACTIVE" if selected_sub['active'] else "NOT ACTIVE",
warning=selected_sub['warning'],
description=selected_sub['description']
)
elif selectedSub['type'] == "ip2tor-v1":
if len(selectedSub['warning']) > 0:
selectedSub['warning'] = "\n{0}".format(selectedSub['warning'])
elif selected_sub['type'] == "ip2tor-v1":
if len(selected_sub['warning']) > 0:
selected_sub['warning'] = "\n{0}".format(selected_sub['warning'])
text = '''
This is a IP2TOR subscription bought on {initdate} at
{shop}
@ -161,26 +164,26 @@ The state of the subscription is: {active} {warning}
The following additional information is available:
{description}
'''.format(initdate=selectedSub['time_created'],
shop=selectedSub['shop'],
publicaddress="{0}:{1}".format(selectedSub['ip'], selectedSub['port']),
toraddress=selectedSub['tor'],
renewhours=(round(int(selectedSub['duration']) / 3600)),
renewsats=(round(int(selectedSub['price_extension']) / 1000)),
totalsats=(round(int(selectedSub['price_total']) / 1000)),
active="ACTIVE" if selectedSub['active'] else "NOT ACTIVE",
warning=selectedSub['warning'],
description=selectedSub['description'],
service=selectedSub['name']
'''.format(initdate=selected_sub['time_created'],
shop=selected_sub['shop'],
publicaddress="{0}:{1}".format(selected_sub['ip'], selected_sub['port']),
toraddress=selected_sub['tor'],
renewhours=(round(int(selected_sub['duration']) / 3600)),
renewsats=(round(int(selected_sub['price_extension']) / 1000)),
totalsats=(round(int(selected_sub['price_total']) / 1000)),
active="ACTIVE" if selected_sub['active'] else "NOT ACTIVE",
warning=selected_sub['warning'],
description=selected_sub['description'],
service=selected_sub['name']
)
else:
text = "no text?! FIXME"
if selectedSub['active']:
extraLable = "CANCEL SUBSCRIPTION"
if selected_sub['active']:
extra_label = "CANCEL SUBSCRIPTION"
else:
extraLable = "DELETE SUBSCRIPTION"
code = d.msgbox(text, title="Subscription Detail", ok_label="Back", extra_button=True, extra_label=extraLable,
extra_label = "DELETE SUBSCRIPTION"
code = d.msgbox(text, title="Subscription Detail", ok_label="Back", extra_button=True, extra_label=extra_label,
width=75, height=30)
# user wants to delete this subscription
@ -188,15 +191,15 @@ The following additional information is available:
# api calls when canceling
if code == "extra":
os.system("clear")
if selectedSub['type'] == "letsencrypt-v1":
if selected_sub['type'] == "letsencrypt-v1":
cmd = "python /home/admin/config.scripts/blitz.subscriptions.letsencrypt.py subscription-cancel {0}".format(
selectedSub['id'])
selected_sub['id'])
print("# running: {0}".format(cmd))
os.system(cmd)
time.sleep(2)
elif selectedSub['type'] == "ip2tor-v1":
elif selected_sub['type'] == "ip2tor-v1":
cmd = "python /home/admin/config.scripts/blitz.subscriptions.ip2tor.py subscription-cancel {0}".format(
selectedSub['id'])
selected_sub['id'])
print("# running: {0}".format(cmd))
os.system(cmd)
time.sleep(2)
@ -205,41 +208,42 @@ The following additional information is available:
time.sleep(3)
# loop until no more subscriptions or user chooses CANCEL on subscription list
mySubscriptions()
my_subscriptions()
#######################
# SSH MENU
#######################
def main():
#######################
# SSH MENU
#######################
choices = list()
choices.append(("LIST", "My Subscriptions"))
choices.append(("NEW1", "+ IP2TOR Bridge (paid)"))
choices.append(("NEW2", "+ LetsEncrypt HTTPS Domain (free)"))
choices = list()
choices.append(("LIST", "My Subscriptions"))
choices.append(("NEW1", "+ IP2TOR Bridge (paid)"))
choices.append(("NEW2", "+ LetsEncrypt HTTPS Domain (free)"))
d = Dialog(dialog="dialog", autowidgetsize=True)
d.set_background_title("RaspiBlitz Subscriptions")
code, tag = d.menu(
d = Dialog(dialog="dialog", autowidgetsize=True)
d.set_background_title("RaspiBlitz Subscriptions")
code, tag = d.menu(
"\nCheck existing subscriptions or create new:",
choices=choices, width=50, height=10, title="Subscription Management")
# if user chosses CANCEL
if code != d.OK:
# if user chosses CANCEL
if code != d.OK:
sys.exit(0)
#######################
# MANAGE SUBSCRIPTIONS
#######################
#######################
# MANAGE SUBSCRIPTIONS
#######################
if tag == "LIST":
mySubscriptions()
if tag == "LIST":
my_subscriptions()
sys.exit(0)
###############################
# NEW LETSENCRYPT HTTPS DOMAIN
###############################
###############################
# NEW LETSENCRYPT HTTPS DOMAIN
###############################
if tag == "NEW2":
if tag == "NEW2":
# run creating a new IP2TOR subscription
os.system("clear")
cmd = "python /home/admin/config.scripts/blitz.subscriptions.letsencrypt.py create-ssh-dialog"
@ -247,19 +251,18 @@ if tag == "NEW2":
os.system(cmd)
sys.exit(0)
###############################
# NEW IP2TOR BRIDGE
###############################
###############################
# NEW IP2TOR BRIDGE
###############################
if tag == "NEW1":
if tag == "NEW1":
# check if Blitz is running behind TOR
cfg.reload()
if not cfg.run_behind_tor.value:
Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
The IP2TOR service just makes sense if you run
your RaspiBlitz behind TOR.
The IP2TOR service just makes sense if you run
your RaspiBlitz behind TOR.
''', title="Info")
sys.exit(1)
@ -278,31 +281,31 @@ your RaspiBlitz behind TOR.
for sub in subs['subscriptions_ip2tor']:
if not sub['active']:
continue
if sub['active'] and sub['name'] == LND_REST_API:
if sub['active'] and sub['name'] == SERVICE_LND_REST_API:
lnd_rest_api = True
if sub['active'] and sub['name'] == LND_GRPC_API:
if sub['active'] and sub['name'] == SERVICE_LND_GRPC_API:
lnd_grpc_api = True
if sub['active'] and sub['name'] == LNBITS:
if sub['active'] and sub['name'] == SERVICE_LNBITS:
lnbits = True
if sub['active'] and sub['name'] == BTCPAY:
if sub['active'] and sub['name'] == SERVICE_BTCPAY:
btcpay = True
except Exception as e:
print(e)
# check if BTCPayserver is installed
btcPayServer = False
statusData = subprocess.run(['/home/admin/config.scripts/bonus.btcpayserver.sh', 'status'],
# check if BTCPayServer is installed
btc_pay_server = False
status_data = subprocess.run(['/home/admin/config.scripts/bonus.btcpayserver.sh', 'status'],
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
if statusData.find("installed=1") > -1:
btcPayServer = True
if status_data.find("installed=1") > -1:
btc_pay_server = True
# ask user for which RaspiBlitz service the bridge should be used
choices = list()
choices.append(("REST", "LND REST API {0}".format("--> ALREADY BRIDGED" if lnd_rest_api else "")))
choices.append(("GRPC", "LND gRPC API {0}".format("--> ALREADY BRIDGED" if lnd_grpc_api else "")))
if cfg.lnbits:
choices.append(("LNBITS", "LNbits Webinterface {0}".format("--> ALREADY BRIDGED" if lnd_grpc_api else "")))
if btcPayServer:
choices.append(("LNBITS", "LNbits Webinterface {0}".format("--> ALREADY BRIDGED" if lnbits else "")))
if btc_pay_server:
choices.append(("BTCPAY", "BTCPay Server Webinterface {0}".format("--> ALREADY BRIDGED" if btcpay else "")))
choices.append(("SELF", "Create a custom IP2TOR Bridge"))
@ -316,35 +319,35 @@ your RaspiBlitz behind TOR.
if code != d.OK:
sys.exit(0)
servicename = None
torAddress = None
torPort = None
service_name = None
tor_address = None
tor_port = None
if tag == "REST":
# get TOR address for REST
servicename = LND_REST_API
torAddress = subprocess.run(['sudo', 'cat', '/mnt/hdd/tor/lndrest8080/hostname'],
service_name = SERVICE_LND_REST_API
tor_address = subprocess.run(['sudo', 'cat', '/mnt/hdd/tor/lndrest8080/hostname'],
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
torPort = 8080
tor_port = 8080
if tag == "GRPC":
# get TOR address for GRPC
servicename = LND_GRPC_API
torAddress = subprocess.run(['sudo', 'cat', '/mnt/hdd/tor/lndrpc10009/hostname'],
service_name = SERVICE_LND_GRPC_API
tor_address = subprocess.run(['sudo', 'cat', '/mnt/hdd/tor/lndrpc10009/hostname'],
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
torPort = 10009
tor_port = 10009
if tag == "LNBITS":
# get TOR address for LNBits
servicename = LNBITS
torAddress = subprocess.run(['sudo', 'cat', '/mnt/hdd/tor/lnbits/hostname'],
service_name = SERVICE_LNBITS
tor_address = subprocess.run(['sudo', 'cat', '/mnt/hdd/tor/lnbits/hostname'],
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
torPort = 443
tor_port = 443
if tag == "BTCPAY":
# get TOR address for BTCPAY
servicename = BTCPAY
torAddress = subprocess.run(['sudo', 'cat', '/mnt/hdd/tor/btcpay/hostname'],
service_name = SERVICE_BTCPAY
tor_address = subprocess.run(['sudo', 'cat', '/mnt/hdd/tor/btcpay/hostname'],
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
torPort = 443
tor_port = 443
if tag == "SELF":
servicename = "CUSTOM"
service_name = "CUSTOM"
try:
# get custom TOR address
code, text = d.inputbox(
@ -361,7 +364,7 @@ your RaspiBlitz behind TOR.
print("Not a TOR Onion Address")
time.sleep(3)
sys.exit(0)
torAddress = text
tor_address = text
# get custom TOR port
code, text = d.inputbox(
"Enter TOR Port Number:",
@ -373,7 +376,7 @@ your RaspiBlitz behind TOR.
sys.exit(0)
if len(text) == 0:
sys.exit(0)
torPort = int(text)
tor_port = int(text)
except Exception as e:
print(e)
time.sleep(3)
@ -382,7 +385,11 @@ your RaspiBlitz behind TOR.
# run creating a new IP2TOR subscription
os.system("clear")
cmd = "python /home/admin/config.scripts/blitz.subscriptions.ip2tor.py create-ssh-dialog {0} {1} {2}".format(
servicename, torAddress, torPort)
service_name, tor_address, tor_port)
print("# running: {0}".format(cmd))
os.system(cmd)
sys.exit(0)
if __name__ == '__main__':
main()

View file

@ -128,6 +128,9 @@ elif [ "$1" = "1" ] || [ "$1" = "on" ]; then
sudo systemctl enable nginx
sudo systemctl start nginx
# create nginx app-data dir
sudo mkdir /mnt/hdd/app-data/nginx/ 2>/dev/null
# general nginx settings
if ! grep -Eq '^\s*server_names_hash_bucket_size.*$' /etc/nginx/nginx.conf; then
# ToDo(frennkie) verify this
@ -135,10 +138,22 @@ elif [ "$1" = "1" ] || [ "$1" = "on" ]; then
fi
if [ ! -f /etc/ssl/certs/dhparam.pem ]; then
#can take 5-10+ minutes on a Raspberry Pi 3
# check if there is a user generated dhparam.pem on the HDD to use
userFileExists=$(sudo ls /mnt/hdd/app-data/nginx/dhparam.pem 2>/dev/null | grep -c dhparam.pem)
if [ ${userFileExists} -eq 0 ]; then
# generate dhparam.pem - can take +10 minutes on a Raspberry Pi
echo "Generating a complete new dhparam.pem"
echo "Running \"sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048\" next."
echo "This can take 5-10 minutes on a Raspberry Pi 3 - please be patient!"
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
sudo cp /etc/ssl/certs/dhparam.pem /mnt/hdd/app-data/nginx/dhparam.pem
else
# just copy the already user generated dhparam.pem into nginx
echo "Copying the user generetad /mnt/hdd/app-data/nginx/dhparam.pem"
sudo cp /mnt/hdd/app-data/nginx/dhparam.pem /etc/ssl/certs/dhparam.pem
fi
fi
sudo cp /home/admin/assets/nginx/snippets/* /etc/nginx/snippets/
@ -178,8 +193,7 @@ elif [ "$1" = "1" ] || [ "$1" = "on" ]; then
sudo apt-get install -y python3-jinja2
sudo -H python3 -m pip install j2cli
# create nginx app-data dir and use LND cert by default
sudo mkdir /mnt/hdd/app-data/nginx/ 2>/dev/null
# use LND cert by default
sudo ln -sf /mnt/hdd/lnd/tls.cert /mnt/hdd/app-data/nginx/tls.cert
sudo ln -sf /mnt/hdd/lnd/tls.key /mnt/hdd/app-data/nginx/tls.key
sudo ln -sf /mnt/hdd/lnd/tls.cert /mnt/hdd/app-data/nginx/tor_tls.cert

View file

@ -229,7 +229,7 @@ EOF
# Hidden Service for BTC-RPC-explorer if Tor is active
source /mnt/hdd/raspiblitz.conf
if [ "${runBehindTor}" = "on" ]; then
echo "# Creating Tor Hidden Service"
# make sure to keep in sync with internet.tor.sh script
/home/admin/config.scripts/internet.hiddenservice.sh btc-rpc-explorer 80 3022 443 3023
fi
exit 0
@ -261,6 +261,7 @@ if [ "$1" = "0" ] || [ "$1" = "off" ]; then
# Hidden Service if Tor is active
if [ "${runBehindTor}" = "on" ]; then
# make sure to keep in sync with internet.tor.sh script
/home/admin/config.scripts/internet.hiddenservice.sh off btc-rpc-explorer
fi

View file

@ -14,8 +14,12 @@ source /mnt/hdd/raspiblitz.conf
source /home/admin/raspiblitz.info
if [ "$1" = "status" ]; then
if [ "${BTCPayServer}" = "on" ]; then
echo "installed=1"
echo "switchedon=1"
isInstalled=$(sudo ls /etc/systemd/system/btcpayserver.service 2>/dev/null | grep -c 'btcpayserver.service')
echo "installed=${isInstalled}"
localIP=$(ip addr | grep 'state UP' -A2 | egrep -v 'docker0' | grep 'eth0\|wlan0' | tail -n1 | awk '{print $2}' | cut -f1 -d'/')
echo "localIP='${localIP}'"
@ -61,6 +65,7 @@ if [ "$1" = "status" ]; then
fi
else
echo "switchedon=0"
echo "installed=0"
fi
exit 0
@ -73,6 +78,17 @@ if [ "$1" = "menu" ]; then
echo "# collecting status info ... (please wait)"
source <(sudo /home/admin/config.scripts/bonus.btcpayserver.sh status)
if [ ${switchedon} -eq 0 ]; then
whiptail --title " BTCPay Server " --msgbox "BTCPay Server is not activated." 7 36
exit 0
fi
if [ ${installed} -eq 0 ]; then
whiptail --title " BTCPay Server " --msgbox "BTCPay Server needs to be re-installed.\nPress OK to start process." 8 45
/home/admin/config.scripts/bonus.btcpayserver.sh on
exit 0
fi
text="Local Webrowser: https://${localIP}:${httpsPort}"
if [ ${#publicDomain} -gt 0 ]; then
@ -162,7 +178,10 @@ BTC.lightning=type=lnd-rest;server=https://127.0.0.1:8080/;macaroonfilepath=/hom
s="BTC.lightning=type=lnd-rest\;server=https\://127.0.0.1:8080/\;macaroonfilepath=/home/btcpay/admin.macaroon\;"
sudo -u btcpay sed -i "s|^${s}certthumbprint=.*|${s}certthumbprint=$FINGERPRINT|g" /home/btcpay/.btcpayserver/Main/settings.config
fi
if [ "${state}" == "ready" ]; then
sudo systemctl restart btcpayserver
fi
exit 0
fi
@ -197,8 +216,7 @@ if [ "$1" = "1" ] || [ "$1" = "on" ]; then
# Hidden Service for BTCPay if Tor is active
if [ "${runBehindTor}" = "on" ]; then
# correct old Hidden Service with port
sudo sed -i "s/^HiddenServicePort 80 127.0.0.1:23000/HiddenServicePort 80 127.0.0.1:23002/g" /etc/tor/torrc
# make sure to keep in sync with internet.tor.sh script
/home/admin/config.scripts/internet.hiddenservice.sh btcpay 80 23002 443 23003
fi
@ -322,7 +340,6 @@ if [ "$1" = "1" ] || [ "$1" = "on" ]; then
# from the build.sh with path
sudo -u btcpay /home/btcpay/dotnet/dotnet build -c Release NBXplorer/NBXplorer.csproj
# create nbxplorer service
echo "
[Unit]
@ -350,26 +367,27 @@ WantedBy=multi-user.target
sudo systemctl daemon-reload
# start to create settings.config
sudo systemctl enable nbxplorer
sudo systemctl start nbxplorer
#sudo systemctl start nbxplorer
echo "Checking for nbxplorer config"
while [ ! -f "/home/btcpay/.nbxplorer/Main/settings.config" ]
do
echo "Waiting for nbxplorer to start - CTRL+C to abort"
sleep 10
hasFailed=$(sudo systemctl status nbxplorer | grep -c "Active: failed")
if [ ${hasFailed} -eq 1 ]; then
echo "seems like starting nbxplorer service has failed - see: systemctl status nbxplorer"
echo "maybe report here: https://github.com/rootzoll/raspiblitz/issues/214"
fi
done
#echo "Checking for nbxplorer config"
#while [ ! -f "/home/btcpay/.nbxplorer/Main/settings.config" ]
# do
# echo "Waiting for nbxplorer to start - CTRL+C to abort"
# sleep 10
# hasFailed=$(sudo systemctl status nbxplorer | grep -c "Active: failed")
# if [ ${hasFailed} -eq 1 ]; then
# echo "seems like starting nbxplorer service has failed - see: systemctl status nbxplorer"
# echo "maybe report here: https://github.com/rootzoll/raspiblitz/issues/214"
# fi
#done
echo ""
echo "***"
echo "getting RPC credentials from the bitcoin.conf"
RPC_USER=$(sudo cat /mnt/hdd/bitcoin/bitcoin.conf | grep rpcuser | cut -c 9-)
PASSWORD_B=$(sudo cat /mnt/hdd/bitcoin/bitcoin.conf | grep rpcpassword | cut -c 13-)
sudo mv /home/btcpay/.nbxplorer/Main/settings.config /home/btcpay/.nbxplorer/Main/settings.config.backup
#sudo mv /home/btcpay/.nbxplorer/Main/settings.config /home/btcpay/.nbxplorer/Main/settings.config.backup
sudo -u btcpay mkdir -p /home/btcpay/.nbxplorer/Main
touch /home/admin/settings.config
sudo chmod 600 /home/admin/settings.config || exit 1
cat >> /home/admin/settings.config <<EOF
@ -379,7 +397,14 @@ EOF
sudo mv /home/admin/settings.config /home/btcpay/.nbxplorer/Main/settings.config
sudo chown btcpay:btcpay /home/btcpay/.nbxplorer/Main/settings.config
sudo systemctl restart nbxplorer
#sudo systemctl restart nbxplorer
if [ "${state}" == "ready" ]; then
echo "Starting nbxplorer"
sudo systemctl start nbxplorer
else
echo "Because the system is not 'ready' the service 'nbxplorer' will not be started at this point .. its enabled and will start on next reboot"
fi
# BTCPayServer
echo ""
@ -420,30 +445,41 @@ WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable btcpayserver
sudo systemctl start btcpayserver
echo "Checking for btcpayserver config"
while [ ! -f "/home/btcpay/.btcpayserver/Main/settings.config" ]
do
echo "Waiting for btcpayserver to start - CTRL+C to abort"
sleep 10
hasFailed=$(sudo systemctl status btcpayserver | grep -c "Active: failed")
if [ ${hasFailed} -eq 1 ]; then
echo "seems like starting btcpayserver service has failed - see: systemctl status btcpayserver"
echo "maybe report here: https://github.com/rootzoll/raspiblitz/issues/214"
if [ "${state}" == "ready" ]; then
echo "Starting btcpayserver"
sudo systemctl start btcpayserver
else
echo "Because the system is not 'ready' the service 'btcpayserver' will not be started at this point .. its enabled and will start on next reboot"
fi
done
#echo "Checking for btcpayserver config"
#while [ ! -f "/home/btcpay/.btcpayserver/Main/settings.config" ]
# do
# echo "Waiting for btcpayserver to start - CTRL+C to abort"
# sleep 10
# hasFailed=$(sudo systemctl status btcpayserver | grep -c "Active: failed")
# if [ ${hasFailed} -eq 1 ]; then
# echo "seems like starting btcpayserver service has failed - see: systemctl status btcpayserver"
# echo "maybe report here: https://github.com/rootzoll/raspiblitz/issues/214"
# fi
#done
sudo -u btcpay mkdir -p /home/btcpay/.btcpayserver/Main/
/home/admin/config.scripts/bonus.btcpayserver.sh write-tls-macaroon
else
echo "BTCPay Server is already installed."
if [ "${state}" == "ready" ]; then
# start service
echo "start service"
sudo systemctl start nbxplorer 2>/dev/null
sudo systemctl start btcpayserver 2>/dev/null
fi
fi
# setting value in raspi blitz config
sudo sed -i "s/^BTCPayServer=.*/BTCPayServer=on/g" /mnt/hdd/raspiblitz.conf
exit 0

View file

@ -239,10 +239,8 @@ EOF
# Hidden Service for SERVICE if Tor is active
source /mnt/hdd/raspiblitz.conf
if [ "${runBehindTor}" = "on" ]; then
echo "# --> correct old Hidden Service with port"
sudo sed -i "s/^HiddenServicePort 25441 127.0.0.1:25441/HiddenServicePort 80 127.0.0.1:25441/g" /etc/tor/torrc
sudo sed -i "s/^HiddenServicePort 25441 127.0.0.1:80/HiddenServicePort 443 127.0.0.1:25441/g" /etc/tor/torrc
# port 25441 is HTTPS with self-signed cert
# make sure to keep in sync with internet.tor.sh script
# port 25441 is HTTPS with self-signed cert - specte only makes sense to be served over HTTPS
/home/admin/config.scripts/internet.hiddenservice.sh cryptoadvance-specter 443 25441
fi
exit 0

View file

@ -453,6 +453,7 @@ WantedBy=multi-user.target
# Hidden Service for electrs if Tor active
if [ "${runBehindTor}" = "on" ]; then
# make sure to keep in sync with internet.tor.sh script
/home/admin/config.scripts/internet.hiddenservice.sh electrs 50002 50002 50001 50001
fi

View file

@ -105,11 +105,6 @@ function acme_install() {
function refresh_certs_with_nginx() {
if [ ! -d "${ACME_CERT_HOME}" ]; then
echo "# no cert directory to link: ${ACME_CERT_HOME}"
return
fi
# FIRST: SET ALL TO DEFAULT SELF SIGNED
echo "# default IP certs"
@ -126,6 +121,11 @@ function refresh_certs_with_nginx() {
# SECOND: SET LETSENCRPYT CERTS FOR SUBSCRIPTIONS
if [ "${letsencrypt}" != "on" ]; then
echo "# lets encrypt is off - so no certs replacements"
return
fi
certsDirectories=$(sudo ls ${ACME_CERT_HOME})
directoryArray=(`echo "${certsDirectories}" | tr ' ' ' '`)
for i in "${directoryArray[@]}"; do

View file

@ -184,7 +184,13 @@ if [ "$1" = "1" ] || [ "$1" = "on" ]; then
cd /home/lnbits
sudo -u lnbits git clone https://github.com/lnbits/lnbits.git
cd /home/lnbits/lnbits
if [ "$2" == "master" ]; then
echo "# checking out master branch"
sudo -u lnbits git checkout
else
echo "# checking out tag 'raspiblitz'"
sudo -u lnbits git checkout tags/raspiblitz
fi
# prepare .env file
echo "# preparing env file"
@ -246,7 +252,14 @@ WantedBy=multi-user.target
EOF
sudo systemctl enable lnbits
echo "# OK - service needs starting: sudo systemctl start lnbits"
source /home/admin/raspiblitz.info
if [ "${state}" == "ready" ]; then
echo "# OK - lnbits service is enabled, system is on ready so starting lnbits service"
sudo systemctl start lnbits
else
echo "# OK - lnbits service is enabled, but needs reboot or manual starting: sudo systemctl start lnbits"
fi
else
echo "LNbits already installed."
@ -274,6 +287,7 @@ EOF
# Hidden Service if Tor is active
source /mnt/hdd/raspiblitz.conf
if [ "${runBehindTor}" = "on" ]; then
# make sure to keep in sync with internet.tor.sh script
/home/admin/config.scripts/internet.hiddenservice.sh lnbits 80 5002 443 5003
fi
exit 0

View file

@ -200,8 +200,7 @@ EOF
# Hidden Service for RTL if Tor is active
if [ "${runBehindTor}" = "on" ]; then
echo "# Creating Tor Hidden Service"
sudo sed -i "s/^HiddenServicePort 80 127.0.0.1:3000/HiddenServicePort 80 127.0.0.1:3002/g" /etc/tor/torrc
# make sure to keep in sync with internet.tor.sh script
/home/admin/config.scripts/internet.hiddenservice.sh RTL 80 3002 443 3003
fi
exit 0

View file

@ -229,8 +229,7 @@ EOF
# Hidden Service for thunderhub if Tor is active
if [ "${runBehindTor}" = "on" ]; then
# correct old Hidden Service with port
sudo sed -i "s/^HiddenServicePort 80 127.0.0.1:3001/HiddenServicePort 80 127.0.0.1:3012/g" /etc/tor/torrc
# make sure to keep in sync with internet.tor.sh script
/home/admin/config.scripts/internet.hiddenservice.sh thunderhub 80 3012 443 3013
fi
fi

View file

@ -15,17 +15,24 @@ source /mnt/hdd/raspiblitz.conf
# delete a hidden service
if [ "$1" == "off" ]; then
service="$2"
if [ ${#service} -eq 0 ]; then
echo "ERROR: service name is missing"
exit 1
fi
# remove service paragraph
sudo sed -i "/# Hidden Service for ${service}/,/^\s*$/{d}" /etc/tor/torrc
# remove double lines
awk 'NF > 0 {blank=0} NF == 0 {blank++} blank < 2' /etc/tor/torrc > .tmp && sudo mv .tmp /etc/tor/torrc
echo "# OK service is removed - restarting TOR ..."
sudo chmod 644 /etc/tor/torrc
sudo systemctl restart tor
sleep 10
echo "# Done"
exit 1
exit 0
fi
service="$1"
@ -59,20 +66,18 @@ if [ ${#toPort2} -gt 0 ]; then
fi
if [ "${runBehindTor}" = "on" ]; then
#check if the service is already present
isHiddenService=$(sudo cat /etc/tor/torrc 2>/dev/null | grep -c $service)
if [ ${isHiddenService} -eq 0 ]; then
#check if the port is already forwarded
alreadyThere=$(sudo cat /etc/tor/torrc 2>/dev/null | grep -c "\b127.0.0.1:$fromPort\b")
if [ ${alreadyThere} -gt 0 ]; then
echo "The port $fromPort is already forwarded. Check /etc/tor/torrc for the details."
exit 1
fi
# delete any old entry for that servive
sudo sed -i "/# Hidden Service for ${service}/,/^\s*$/{d}" /etc/tor/torrc
# make new entry for that service
echo "
# Hidden Service for $service
HiddenServiceDir /mnt/hdd/tor/$service
HiddenServiceVersion 3
HiddenServicePort $toPort 127.0.0.1:$fromPort" | sudo tee -a /etc/tor/torrc
# remove double lines
sudo awk 'NF > 0 {blank=0} NF == 0 {blank++} blank < 2' /etc/tor/torrc > /mnt/hdd/temp/tmp && sudo mv /mnt/hdd/temp/tmp /etc/tor/torrc
# check and insert second port pair
if [ ${#toPort2} -gt 0 ]; then
@ -83,14 +88,14 @@ HiddenServicePort $toPort 127.0.0.1:$fromPort" | sudo tee -a /etc/tor/torrc
echo "HiddenServicePort $toPort2 127.0.0.1:$fromPort2" | sudo tee -a /etc/tor/torrc
fi
fi
# restart tor
echo ""
echo "Restarting Tor to activate the Hidden Service..."
sudo chmod 644 /etc/tor/torrc
sudo systemctl restart tor
sleep 10
else
echo "The Hidden Service for $service is already installed."
fi
# show the Hidden Service address
TOR_ADDRESS=$(sudo cat /mnt/hdd/tor/$service/hostname)
if [ -z "$TOR_ADDRESS" ]; then
@ -106,13 +111,10 @@ HiddenServicePort $toPort 127.0.0.1:$fromPort" | sudo tee -a /etc/tor/torrc
echo "The Tor Hidden Service address for $service is:"
echo "$TOR_ADDRESS"
echo "use with the port: $toPort"
echo ""
if [ ${#toPort2} -gt 0 ]; then
alreadyThere=$(sudo cat /etc/tor/torrc 2>/dev/null | grep -c "\b127.0.0.1:$fromPort2\b")
if [ ${alreadyThere} -eq 0 ]; then
wasAdded=$(sudo cat /etc/tor/torrc 2>/dev/null | grep -c "\b127.0.0.1:$fromPort2\b")
if [ ${wasAdded} -gt 0 ]; then
echo "or the port: $toPort2"
else
echo "The port $fromPort2 is forwarded for another Hidden Service. Check the /etc/tor/torrc for the details."
fi
fi
else

View file

@ -365,16 +365,23 @@ EOF
/home/admin/config.scripts/internet.hiddenservice.sh btc-rpc-explorer 80 3002
fi
if [ "${rtlWebinterface}" = "on" ]; then
/home/admin/config.scripts/internet.hiddenservice.sh RTL 80 3000
/home/admin/config.scripts/internet.hiddenservice.sh RTL 80 3002 443 3003
fi
if [ "${BTCPayServer}" = "on" ]; then
/home/admin/config.scripts/internet.hiddenservice.sh btcpay 80 23000
/home/admin/config.scripts/internet.hiddenservice.sh btcpay 80 23002 443 23003
fi
if [ "${ElectRS}" = "on" ]; then
/home/admin/config.scripts/internet.hiddenservice.sh electrs 50002 50002 50001 50001
fi
if [ "${LNBits}" = "on" ]; then
/home/admin/config.scripts/internet.hiddenservice.sh lnbits 80 5000
/home/admin/config.scripts/internet.hiddenservice.sh lnbits 80 5002 443 5003
fi
if [ "${thunderhub}" = "on" ]; then
/home/admin/config.scripts/internet.hiddenservice.sh thunderhub 80 3012 443 3013
fi
if [ "${specter}" = "on" ]; then
# specter makes only sense to be served over https
/home/admin/config.scripts/internet.hiddenservice.sh cryptoadvance-specter 443 25441
fi
echo "OK - TOR is now ON"