diff --git a/FAQ.md b/FAQ.md index 18b99c6af..e12e52984 100644 --- a/FAQ.md +++ b/FAQ.md @@ -5,6 +5,7 @@ - Fix: DropBox StaticChannelBackup - New: Balance of Satoshis [details](https://github.com/alexbosworth/balanceofsatoshis) - New: Faraday [details](https://github.com/lightninglabs/faraday) +- New: Let's Encrypt client [details](FAQ.md#how-to-use-the-lets-encrypt-client) ## Whats new in Version 1.5 of RaspiBlitz? @@ -977,3 +978,63 @@ If you cannot login per SSH into your RaspiBlitz your SSH RaspiBlitz certs might - then try again to SSH login If you see a "REMOTE HOST IDENTIFICATION HAS CHANGED!" warning on login thats what we wanted - the SSH cert of your RaspiBlitz changed - thats good. We just need to remove the old one from our laptop first - on OSX you can use `rm ~/.ssh/known_hosts` (deletes all cached server certs) or remove the line with your RaspiBlitz IP manually from the `~/.ssh/known_hosts` file with a text editor. + +## How to use the Let's Encrypt client + +The [Let's Encrypt](https://letsencrypt.org/) client software [acme.sh](https://github.com/acmesh-official/acme.sh) is +included (since v1.6) and can be used to create TLS certificates that are signed by the Certificate Authority (*Root +CA*) **Let's Encrypt** and which are therefore trusted on all modern platforms. + +In order to successfully get a signed certificate you need to **verify ownership** over a **DNS domain** or a **full +qualified domain name** (**FQDN**). Currently Let's Encrypt **doesn't** issue certificates for IP addresses. The two +most common standards for verification of control are `HTTP-01` and `DNS-01`. + +The **acme.sh** client supports both modes and has a large number of DNS services (more than 50) it can interact with. +More details can be found on the [acme.sh wiki](https://github.com/acmesh-official/acme.sh/wiki). + +### Let's Encrypt - HTTP-01 + +To use `HTTP-01` your RaspiBlitz needs to be accessible directly from the Internet on a **public IP address** on **port +80**. If you don't have a public IPv4/IPv6 IP on either `eth0` or `wlan0` then it might be possible to use **NAT port +forwarding** or an **autossh-tunnel** to fulfill this requirement. + +If everything (this includes creating a `DNS A` or `DNS CNAME` record that points to a static or dynamic IP address) is +set up so that the Let's Encrypt servers can reach your RaspiBlitz on port 80 then the following command will perform +the initial creation of a signed certificate and will also store the configuration data needed to regularly refresh it. +Just run this once and then lean back and forget about it. :-D + +``` +~/.acme.sh/acme.sh --keylength ec-256 --issue -d hostname.example.com -w /var/www/letsencrypt/ +``` + +### Let's Encrypt - DNS-01 + +The `DNS-01` standard **proves ownership** by creating `DNS TXT` records on the domain or subdomain you want to use. +This requires interaction with and access to a dns server but comes with the benefit that `wildcard certificates` +can be issued. + +It is beyond the scope of this FAQ entry to explain all details of this - please refer to the official documentation. +Assuming you are using the [DuckDNS](https://www.duckdns.org/) dynamic DNS service then the following command will +get a certificate (including a wildcard subject alternative name (**SAN**) listing). It will also take care of continuous +renewals. + +``` +export DuckDNS_Token="abcdefgh-0123-56ij-78kl-abcd9012efgh" +~/.acme.sh/acme.sh --issue --keylength ec-256 --dns dns_duckdns -d hostname.duckdns.org -d *.hostname.duckdns.org +``` + +As mentioned more that 50 other services (including self-hosted options like e.g. `nsupdate` or `PowerDNS`) are supported. + +### Let's Encrypt - eMail Address + +The installation process of the `acme.sh` client includes a prompt for an eMail address. The data entered there is +stored in the `accounts.conf` file as `ACCOUNT_EMAIL`. This address is used by Let's Encrypt to notify you about +the expiry of certificates (which is not really needed as renewals are automated) and also about changes to their +**Terms of Service**. For more details please check their [privacy policy](https://letsencrypt.org/privacy/). + +It is currently considered completely fine to leave this field empty and not provide an eMail address. + +### Let's Encrypt - Installation details + +The `acme.sh` script is installed in `/home/admin/.acme.sh/` - the configuration and the certificates are stored on the +external hard disk in `/mnt/hdd/app-data/letsencrypt`. diff --git a/home.admin/00settingsMenuServices.sh b/home.admin/00settingsMenuServices.sh index fb1722fc2..9aa19b60b 100644 --- a/home.admin/00settingsMenuServices.sh +++ b/home.admin/00settingsMenuServices.sh @@ -25,6 +25,7 @@ if [ ${#joinmarket} -eq 0 ]; then joinmarket="off"; fi if [ ${#LNBits} -eq 0 ]; then LNBits="off"; fi if [ ${#faraday} -eq 0 ]; then faraday="off"; fi if [ ${#bos} -eq 0 ]; then bos="off"; fi +if [ ${#letsencrypt} -eq 0 ]; then letsencrypt="off"; fi echo "map dropboxbackup to on/off" DropboxBackup="off"; @@ -37,20 +38,20 @@ if [ "${chain}" = "test" ]; then chainValue="on"; fi echo "map domain to on/off" domainValue="off" dynDomainMenu='DynamicDNS' -if [ ${#dynDomain} -gt 0 ]; then +if [ ${#dynDomain} -gt 0 ]; then domainValue="on" dynDomainMenu="${dynDomain}" fi echo "map lcdrotate to on/off" lcdrotateMenu='off' -if [ ${lcdrotate} -gt 0 ]; then +if [ ${lcdrotate} -gt 0 ]; then lcdrotateMenu='on' fi echo "map touchscreen to on/off" touchscreenMenu='off' -if [ ${touchscreen} -gt 0 ]; then +if [ ${touchscreen} -gt 0 ]; then touchscreenMenu='on' fi @@ -82,6 +83,7 @@ l 'Lightning Loop' ${loop} \ 4 'Run behind TOR' ${runBehindTor} \ 5 'RTL Webinterface' ${rtlWebinterface} \ b 'BTC-RPC-Explorer' ${BTCRPCexplorer} \ +c 'Let`s Encrypt Client' ${letsencrypt} \ s 'Cryptoadvance Specter' ${specter} \ 6 'LND Auto-Unlock' ${autoUnlock} \ 9 'Touchscreen' ${touchscreenMenu} \ @@ -105,6 +107,7 @@ l 'Lightning Loop' ${loop} \ 4 'Run behind TOR' ${runBehindTor} \ 5 'RTL Webinterface' ${rtlWebinterface} \ b 'BTC-RPC-Explorer' ${BTCRPCexplorer} \ +c 'Let`s Encrypt Client' ${letsencrypt} \ s 'Cryptoadvance Specter' ${specter} \ 6 'LND Auto-Unlock' ${autoUnlock} \ 7 'BTC UPnP (AutoNAT)' ${networkUPnP} \ @@ -173,13 +176,13 @@ if [ "${chain}" != "${choice}" ]; then echo "Creating a new LND Wallet for ${network}/${choice}net" echo "****************************************************************************" echo "A) For 'Wallet Password' use your PASSWORD C --> !! minimum 8 characters !!" - echo "B) Answere 'n' because you dont have a 'cipher seed mnemonic' (24 words) yet" + echo "B) Answer 'n' because you don't have a 'cipher seed mnemonic' (24 words) yet" echo "C) For 'passphrase' to encrypt your 'cipher seed' use PASSWORD D (optional)" echo "****************************************************************************" sudo -u bitcoin /usr/local/bin/lncli --chain=${network} --network=${chain}net create 2>error.out error=`sudo cat error.out` if [ ${#error} -eq 0 ]; then - sleep 2 + sleep 2 # WIN tryAgain=0 echo "!!! Make sure to write down the 24 words (cipher seed mnemonic) !!!" @@ -217,10 +220,10 @@ if [ "${chain}" != "${choice}" ]; then sudo mkdir /home/admin/.lnd/data/chain/${network}/${choice}net sudo cp /home/bitcoin/.lnd/data/chain/${network}/${choice}net/admin.macaroon /home/admin/.lnd/data/chain/${network}/${choice}net sudo chown -R admin:admin /home/admin/.lnd/ - + needsReboot=1 fi -else +else echo "Testnet Setting unchanged." fi @@ -232,7 +235,7 @@ if [ "${autoPilot}" != "${choice}" ]; then anychange=1 sudo /home/admin/config.scripts/lnd.autopilot.sh ${choice} needsReboot=1 -else +else echo "Autopilot Setting unchanged." fi @@ -256,7 +259,7 @@ if [ "${loop}" != "${choice}" ]; then dialog --title 'FAIL' --msgbox "${l1}\n${l2}\n${l3}" 7 65 fi fi -else +else echo "Loop Setting unchanged." fi @@ -331,7 +334,7 @@ Please keep in mind that thru your LND node id & your previous IP history with y " 16 76 # make sure AutoNAT & UPnP is off - /home/admin/config.scripts/lnd.autonat.sh off + /home/admin/config.scripts/lnd.autonat.sh off /home/admin/config.scripts/network.upnp.sh off fi @@ -340,7 +343,7 @@ Please keep in mind that thru your LND node id & your previous IP history with y sudo /home/admin/config.scripts/internet.tor.sh ${choice} needsReboot=1 -else +else echo "TOR Setting unchanged." fi @@ -397,6 +400,36 @@ else echo "BTC-RPC-Explorer 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 + # cryptoadvance Specter process choice choice="off"; check=$(echo "${CHOICES}" | grep -c "s") if [ ${check} -eq 1 ]; then choice="on"; fi @@ -433,7 +466,7 @@ if [ "${autoUnlock}" != "${choice}" ]; then l1="AUTO-UNLOCK IS NOW OFF" if [ "${choice}" = "on" ]; then l1="AUTO-UNLOCK IS NOW ACTIVE" - fi + fi l2="-------------------------" l3="mobile/external wallets may need reconnect" l4="possible change in macaroon / TLS cert" @@ -513,7 +546,7 @@ When finished use the new 'ELECTRS' entry in Main Menu for more info.\n extraparameter="deleteindex" fi /home/admin/config.scripts/bonus.electrs.sh off ${extraparameter} - fi + fi else echo "ElectRS Setting unchanged." @@ -566,7 +599,7 @@ if [ "${lndmanage}" != "${choice}" ]; then if [ "${lndmanage}" = "on" ]; then sudo -u admin /home/admin/config.scripts/bonus.lndmanage.sh menu fi -else +else echo "lndmanage setting unchanged." fi @@ -581,7 +614,7 @@ if [ "${faraday}" != "${choice}" ]; then if [ "${faraday}" = "on" ]; then sudo -u admin /home/admin/config.scripts/bonus.faraday.sh menu fi -else +else echo "faraday setting unchanged." fi @@ -597,7 +630,7 @@ if [ "${bos}" != "${choice}" ]; then if [ "${bos}" = "on" ]; then sudo -u admin /home/admin/config.scripts/bonus.faraday.sh menu fi -else +else echo "Balance of Satoshis setting unchanged." fi @@ -612,7 +645,7 @@ if [ "${LNBits}" != "${choice}" ]; then sudo systemctl start lnbits sudo -u admin /home/admin/config.scripts/bonus.lnbits.sh menu fi -else +else echo "LNbits setting unchanged." fi @@ -628,7 +661,7 @@ if [ "${DropboxBackup}" != "${choice}" ]; then source /mnt/hdd/raspiblitz.conf sudo /home/admin/config.scripts/dropbox.upload.sh upload ${dropboxBackupTarget} /home/admin/.lnd/data/chain/${network}/${chain}net/channel.backup fi -else +else echo "Dropbox backup setting unchanged." fi @@ -641,7 +674,7 @@ if [ "${keysend}" != "${choice}" ]; then needsReboot=1 sudo -u admin /home/admin/config.scripts/lnd.keysend.sh ${choice} dialog --msgbox "Accept Keysend is now ${choice} after Reboot." 5 46 -else +else echo "keysend setting unchanged." fi diff --git a/home.admin/config.scripts/bonus.letsencrypt.sh b/home.admin/config.scripts/bonus.letsencrypt.sh new file mode 100755 index 000000000..73d788ec9 --- /dev/null +++ b/home.admin/config.scripts/bonus.letsencrypt.sh @@ -0,0 +1,167 @@ +#!/bin/bash + +# command info +if [ $# -eq 0 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ] || [ "$1" = "-help" ]; then + echo "config script to install or remove the Let's Encrypt Client (ACME.SH)" + echo "bonus.letsencrypt.sh [on|off]" + exit 1 +fi + +source /mnt/hdd/raspiblitz.conf + +ACME_LOAD_BASE_URL="https://codeload.github.com/acmesh-official/acme.sh/tar.gz" +ACME_VERSION="2.8.6" + +ACME_INSTALL_HOME="/home/admin/.acme.sh" +ACME_CONFIG_HOME="/mnt/hdd/app-data/letsencrypt" +ACME_CERT_HOME="${ACME_CONFIG_HOME}/certs" + +ACME_IS_INSTALLED=0 + +################### +# FUNCTIONS +################### +function menu_enter_email() { + HEIGHT=18 + WIDTH=56 + BACKTITLE="Manage TLS certificates" + TITLE="Let's Encrypt - eMail" + INPUTBOX="\n +You can *optionally* enter an eMail address.\n +\n +The address will not be included in the generated certificates.\n +\n +It will be used to e.g. notify you about certificate expiries and changes +to the Terms of Service of Let's Encrypt.\n +\n +Feel free to leave empty." + + ADDRESS=$(dialog --clear \ + --backtitle "${BACKTITLE}" \ + --title "${TITLE}" \ + --inputbox "${INPUTBOX}" ${HEIGHT} ${WIDTH} 2>&1 >/dev/tty) + echo "${ADDRESS}" +} + +function acme_status() { + # check if acme is installed (either directory or cronjob) + cron_count=$(crontab -l | grep "acme.sh" -c) + if [ -f "${ACME_INSTALL_HOME}/acme.sh" ] || [ "${cron_count}" = "1" ]; then + ACME_IS_INSTALLED=1 + else + ACME_IS_INSTALLED=0 + fi +} + +function acme_install() { + email="${1}" + + # ensure socat + if ! command -v socat >/dev/null; then + echo "# installing socat..." + sudo apt-get update >/dev/null 2>&1 + sudo apt-get install -y socat >/dev/null 2>&1 + fi + + if ! [ -d "/mnt/hdd/app-data/letsencrypt" ]; then + sudo mkdir -p "/mnt/hdd/app-data/letsencrypt" + fi + sudo chown admin:admin "/mnt/hdd/app-data/letsencrypt" + + rm -f "/tmp/acme.sh_${ACME_VERSION}.tar.gz" + if ! curl --silent --fail -o "/tmp/acme.sh_${ACME_VERSION}.tar.gz" "${ACME_LOAD_BASE_URL}/${ACME_VERSION}" 2>&1; then + echo "Error ($?): Download failed from: ${ACME_LOAD_BASE_URL}/${ACME_VERSION}" + rm -f "/tmp/acme.sh_${ACME_VERSION}.tar.gz" + exit 1 + fi + + if tar xzf "/tmp/acme.sh_${ACME_VERSION}.tar.gz" -C /tmp/; then + cd "/tmp/acme.sh-${ACME_VERSION}" || exit + + if [ -n "${email}" ]; then + ./acme.sh --install \ + --noprofile \ + --home "${ACME_INSTALL_HOME}" \ + --config-home "${ACME_CONFIG_HOME}" \ + --cert-home "${ACME_CERT_HOME}" \ + --accountemail "${email}" + else + ./acme.sh --install \ + --noprofile \ + --home "${ACME_INSTALL_HOME}" \ + --config-home "${ACME_CONFIG_HOME}" \ + --cert-home "${ACME_CERT_HOME}" + fi + + fi + + rm -f "/tmp/acme.sh_${ACME_VERSION}.tar.gz" + rm -Rf "/tmp/acme.sh_${ACME_VERSION}" + +} + + +################### +# running as admin +################### +adminUserId=$(id -u admin) +if [ "${EUID}" != "${adminUserId}" ]; then + echo "error='please run as admin user'" + exit 1 +fi + + +# add default value to RaspiBlitz config if needed +if ! grep -Eq "^letsencrypt" /mnt/hdd/raspiblitz.conf; then + echo "letsencrypt=off" >> /mnt/hdd/raspiblitz.conf +fi + + +################### +# update status +################### +acme_status + +################### +# ON +################### +if [ "$1" = "1" ] || [ "$1" = "on" ]; then + if [ ${ACME_IS_INSTALLED} -eq 0 ]; then + echo "*** INSTALLING Let's Encrypt Client 'acme.sh' ***" + + # setting value in RaspiBlitz config + sudo sed -i "s/^letsencrypt=.*/letsencrypt=on/g" /mnt/hdd/raspiblitz.conf + + address=$(menu_enter_email) + echo "" + + acme_install "${address}" + echo "" + + else + echo "*** Let's Encrypt Client 'acme.sh' appears to be installed already ***" + fi + +################### +# OFF +################### +elif [ "$1" = "0" ] || [ "$1" = "off" ]; then + if [ ${ACME_IS_INSTALLED} -eq 1 ]; then + echo "*** UNINSTALLING Let's Encrypt Client 'acme.sh' ***" + + # setting value in RaspiBlitz config + sudo sed -i "s/^letsencrypt=.*/letsencrypt=off/g" /mnt/hdd/raspiblitz.conf + + "${ACME_INSTALL_HOME}/acme.sh" --uninstall \ + --home "${ACME_INSTALL_HOME}" \ + --config-home "${ACME_CONFIG_HOME}" \ + --cert-home "${ACME_CERT_HOME}" + + else + echo "*** Let's Encrypt Client 'acme.sh' not installed ***" + fi + +else + echo "# FAIL: parameter not known - run with -h for help" + exit 1 +fi