diff --git a/armbian/base/build.conf b/armbian/base/build.conf index edbe22e4..a8536ddb 100644 --- a/armbian/base/build.conf +++ b/armbian/base/build.conf @@ -60,3 +60,7 @@ # Make root filesystem read-only and overlay it with a temporary filesystem. # All changes are lost on reboot, guaranteeing a safe state. #BASE_OVERLAYROOT="true" + +# Start Maintenance Menu if authorized maintenance token +# is found on USB flasdrive on boot +#BASE_MAINTENANCEMENU="false" diff --git a/armbian/base/config/dialog/.dialogrc b/armbian/base/config/dialog/.dialogrc new file mode 100644 index 00000000..e96ee261 --- /dev/null +++ b/armbian/base/config/dialog/.dialogrc @@ -0,0 +1,144 @@ +# +# Run-time configuration file for dialog +# +# Automatically generated by "dialog --create-rc " +# +# +# Types of values: +# +# Number - +# String - "string" +# Boolean - +# Attribute - (foreground,background,highlight?) + +# Set aspect-ration. +aspect = 0 + +# Set separator (for multiple widgets output). +separate_widget = "" + +# Set tab-length (for textbox tab-conversion). +tab_len = 0 + +# Make tab-traversal for checklist, etc., include the list. +visit_items = OFF + +# Shadow dialog boxes? This also turns on color. +use_shadow = OFF + +# Turn color support ON or OFF +use_colors = ON + +# Screen color +screen_color = (BLUE,BLACK,ON) + +# Shadow color +shadow_color = (BLACK,BLACK,ON) + +# Dialog box color +dialog_color = (BLACK,WHITE,OFF) + +# Dialog box title color +title_color = (BLUE,WHITE,ON) + +# Dialog box border color +border_color = (WHITE,WHITE,ON) + +# Active button color +button_active_color = (WHITE,BLUE,ON) + +# Inactive button color +button_inactive_color = dialog_color + +# Active button key color +button_key_active_color = button_active_color + +# Inactive button key color +button_key_inactive_color = (RED,WHITE,OFF) + +# Active button label color +button_label_active_color = (YELLOW,BLUE,ON) + +# Inactive button label color +button_label_inactive_color = (BLACK,WHITE,ON) + +# Input box color +inputbox_color = dialog_color + +# Input box border color +inputbox_border_color = dialog_color + +# Search box color +searchbox_color = dialog_color + +# Search box title color +searchbox_title_color = title_color + +# Search box border color +searchbox_border_color = border_color + +# File position indicator color +position_indicator_color = title_color + +# Menu box color +menubox_color = dialog_color + +# Menu box border color +menubox_border_color = border_color + +# Item color +item_color = dialog_color + +# Selected item color +item_selected_color = button_active_color + +# Tag color +tag_color = title_color + +# Selected tag color +tag_selected_color = button_label_active_color + +# Tag key color +tag_key_color = button_key_inactive_color + +# Selected tag key color +tag_key_selected_color = (RED,BLUE,ON) + +# Check box color +check_color = dialog_color + +# Selected check box color +check_selected_color = button_active_color + +# Up arrow color +uarrow_color = (GREEN,WHITE,ON) + +# Down arrow color +darrow_color = uarrow_color + +# Item help-text color +itemhelp_color = (WHITE,BLACK,OFF) + +# Active form text color +form_active_text_color = button_active_color + +# Form text color +form_text_color = (WHITE,CYAN,ON) + +# Readonly form item color +form_item_readonly_color = (CYAN,WHITE,ON) + +# Dialog box gauge color +gauge_color = title_color + +# Dialog box border2 color +border2_color = dialog_color + +# Input box border2 color +inputbox_border2_color = dialog_color + +# Search box border2 color +searchbox_border2_color = dialog_color + +# Menu box border2 color +menubox_border2_color = dialog_color diff --git a/armbian/base/config/signatures/maintenance-token-hashes b/armbian/base/config/signatures/maintenance-token-hashes new file mode 100644 index 00000000..7363f1f4 --- /dev/null +++ b/armbian/base/config/signatures/maintenance-token-hashes @@ -0,0 +1 @@ +657861a460401b2ec32183ea5b3b4d12ce80aea8c9be57c245a033dae776adf7 Shift factory token diff --git a/armbian/base/config/templates/bashrc-custom.template b/armbian/base/config/templates/bashrc-custom.template index b66743f6..cb8c0ec5 100644 --- a/armbian/base/config/templates/bashrc-custom.template +++ b/armbian/base/config/templates/bashrc-custom.template @@ -1,7 +1,7 @@ {{ #output: /home/base/.bashrc-custom }} export LS_OPTIONS='--color=auto' -alias l='ls $LS_OPTIONS -l' -alias ll='ls $LS_OPTIONS -la' +alias l='ls $LS_OPTIONS -lh' +alias ll='ls $LS_OPTIONS -lah' # Bitcoin alias bcli='bitcoin-cli -conf=/etc/bitcoin/bitcoin.conf -rpcuser=base -rpcpassword={{ bitcoind:rpcpassword }}' diff --git a/armbian/base/customize-armbian-rockpro64.sh b/armbian/base/customize-armbian-rockpro64.sh index 825bfb11..fb8d4144 100755 --- a/armbian/base/customize-armbian-rockpro64.sh +++ b/armbian/base/customize-armbian-rockpro64.sh @@ -81,6 +81,7 @@ CONFIGURATION: AUTOSETUP SSD: ${BASE_AUTOSETUP_SSD} BITCOIN SERVICES ENABLED: ${BASE_ENABLE_BITCOIN_SERVICES} + MAINTENANCE MENU: ${BASE_MAINTENANCEMENU} ================================================================================ BUILD OPTIONS: @@ -179,6 +180,7 @@ BASE_DASHBOARD_HDMI_ENABLED="false" BASE_HDMI_BUILD="false" BASE_MINIMAL="true" BASE_OVERLAYROOT="true" +BASE_MAINTENANCEMENU="false" # TODO(Stadicus): set "true" by default after further review # Overwrite defaults if BASE_PRODUCTION_IMAGE set to "false" if [[ ${BASE_PRODUCTION_IMAGE} == "false" ]]; then @@ -291,11 +293,11 @@ apt-get -y --fix-broken install ## remove unnecessary packages (only when building image, not ondevice) if [[ "${BASE_BUILDMODE}" != "ondevice" ]] && [[ "${BASE_MINIMAL}" == "true" ]]; then pkgToRemove="git libllvmkk build-essential libtool autotools-dev automake pkg-config gcc gcc-6 libgcc-6-dev - alsa-utils* autoconf* bc* bison* bridge-utils* btrfs-tools* bwm-ng* cmake* command-not-found* console-setup* - console-setup-linux* crda* dconf-gsettings-backend* dconf-service* debconf-utils* device-tree-compiler* dialog* dirmngr* + alsa-utils* autoconf* bc* bison* bridge-utils* btrfs-tools* bwm-ng* cmake* command-not-found* + crda* dconf-gsettings-backend* dconf-service* debconf-utils* device-tree-compiler* dirmngr* dnsutils* dosfstools* ethtool* evtest* f2fs-tools* f3* fancontrol* figlet* fio* flex* fping* glib-networking* glib-networking-services* gnome-icon-theme* gnupg2* gsettings-desktop-schemas* gtk-update-icon-cache* haveged* hdparm* hostapd* html2text* ifenslave* iotop* - iperf3* iputils-arping* iw* kbd* libatk1.0-0* libcroco3* libcups2* libdbus-glib-1-2* libgdk-pixbuf2.0-0* libglade2-0* libnl-3-dev* + iperf3* iputils-arping* iw* libatk1.0-0* libcroco3* libcups2* libdbus-glib-1-2* libgdk-pixbuf2.0-0* libglade2-0* libnl-3-dev* libpango-1.0-0* libpolkit-agent-1-0* libpolkit-backend-1-0* libpolkit-gobject-1-0* libpython-stdlib* libpython2.7-stdlib* libssl-dev* man-db* ncurses-term* psmisc* pv* python-avahi* python-pip* python2.7-minimal screen* shared-mime-info* unattended-upgrades* unicode-data* unzip* vim* wireless-regdb* wireless-tools* wpasupplicant* " @@ -348,6 +350,9 @@ mkdir -p /data_source/ ln -sfn /data_source /data touch /data/.datadir_set_up +# import presync authorization token, will be deleted after presync or on initial setup +cp /opt/shift/config/signatures/maintenance-token-hashes /data_source + ## install Redis apt-get install -y --no-install-recommends redis mkdir -p /data/redis/ @@ -446,6 +451,8 @@ ln -sfn /mnt/ssd/system/journal /var/log/journal mkdir -p /etc/mender generateConfig mender.conf.template # --> /etc/mender/mender.conf + + ## configure swap file (disable Armbian zram, configure custom swapfile on ssd) if [[ -f /etc/default/armbian-zram-config ]] || [[ "${BASE_BUILDMODE}" != "ondevice" ]]; then sed -i '/ENABLED=/Ic\ENABLED=false' /etc/default/armbian-zram-config @@ -464,6 +471,13 @@ systemctl enable startup-after-redis.service importFile /etc/systemd/system/update-checks.service systemctl enable update-checks.service +## maintenance menu +importFile /etc/systemd/system/startup-maintenance.service + +if [[ "${BASE_MAINTENANCEMENU}" == "true" ]]; then + systemctl enable startup-maintenance.service +fi + ## disable ssh login messages echo "MOTD_DISABLE='header tips updates armbian-config'" >> /etc/default/armbian-motd diff --git a/armbian/base/rootfs/etc/systemd/system/startup-maintenance.service b/armbian/base/rootfs/etc/systemd/system/startup-maintenance.service new file mode 100644 index 00000000..f7df8686 --- /dev/null +++ b/armbian/base/rootfs/etc/systemd/system/startup-maintenance.service @@ -0,0 +1,14 @@ +[Unit] +Description=BitBoxBase: Maintenance menu +After=getty@tty2.service + +[Service] +Type=oneshot +ExecStart=/opt/shift/scripts/systemd-startup-maintenance.sh +StandardInput=tty +TTYPath=/dev/tty2 +TTYReset=yes +TTYVHangup=yes + +[Install] +WantedBy=default.target diff --git a/armbian/base/scripts/bbb-cmd.sh b/armbian/base/scripts/bbb-cmd.sh index d26d19f4..694c69e9 100755 --- a/armbian/base/scripts/bbb-cmd.sh +++ b/armbian/base/scripts/bbb-cmd.sh @@ -16,8 +16,9 @@ possible commands: flashdrive backup restore - reset + reset mender-update + presync " } @@ -79,6 +80,7 @@ fi MODULE="${1:-}" COMMAND="${2:-}" ARG="${3:-}" +ARG2="${4:-}" MODULE="$(tr '[:lower:]' '[:upper:]' <<< "${MODULE}")" COMMAND="$(tr '[:lower:]' '[:upper:]' <<< "${COMMAND}")" @@ -110,14 +112,14 @@ case "${MODULE}" in ln -sfn /mnt/ssd/data / echo "OK: (DATADIR) symlink /data --> /mnt/ssd/data created in OVERLAYROOTFS" - if [ ! -f /data/.datadir_set_up ]; then - cp -r /data_source/* /data - echo "OK: (DATADIR) /data_source/ copied to /data/" - fi - else - ln -sfn /data_source /data - echo "OK: (DATADIR) symlink /data/ --> /data_source/ created" + mkdir -p /data + echo "OK: (DATADIR) directory /data/ created" + fi + + if [ ! -f /data/.datadir_set_up ]; then + cp -r /data_source/* /data + echo "OK: (DATADIR) /data_source/ copied to /data/" fi fi else @@ -320,18 +322,20 @@ case "${MODULE}" in fi echo "OK: backup created as /mnt/backup/bbb-backup.rdb" - # add Factory Reset token - RESET_TOKEN="$(< /dev/urandom tr -dc A-Za-z0-9 | head -c64)" - RESET_TOKEN_HASH=$(echo -n "${RESET_TOKEN}" | sha256sum | tr -d "[:space:]-") + # add maintenance token + MAINTENANCE_TOKEN="$(< /dev/urandom tr -dc A-Za-z0-9 | head -c64)" + MAINTENANCE_TOKEN_HASH=$(echo -n "${MAINTENANCE_TOKEN}" | sha256sum | tr -d "[:space:]-") - # write reset token to usb drive, no linebreak allowed - printf "%s" "${RESET_TOKEN}" > /mnt/backup/.reset-token + # write maintenance token to usb drive, no linebreak allowed + printf "%s" "${MAINTENANCE_TOKEN}" > /mnt/backup/.maintenance-token # append reset token hash for permission check locally - echo "${RESET_TOKEN_HASH}" >> /data/reset-token-hashes - chmod 600 /data/reset-token-hashes - echo "OK: reset token created on flashdrive" + echo "${MAINTENANCE_TOKEN_HASH}" >> /data/maintenance-token-hashes + chmod 600 /data/maintenance-token-hashes + echo "OK: maintenance token created on flashdrive" + # make sure the Shift factory token is removed on first backup + sed -i '/factory token/d' /data/maintenance-token-hashes ;; # backup c-lightning on-chain keys in 'hsm_secret' into Redis database @@ -504,12 +508,120 @@ case "${MODULE}" in echo "OK: middleware authentication reset, setup wizard can be run again." ;; + CONFIG) + # stop services + if redis-cli save; then + systemctl stop redis.service + fi + + # delete old data + rm -rf /data/bbbmiddleware + rm -rf /data/redis + rm -rf /data/ssh + rm -rf /data/ssl + rm /data/.datadir_set_up + + # re-initialize data dir + /opt/shift/scripts/bbb-cmd.sh setup datadir + + # start services + systemctl start redis.service + + # recreate directories and certificates (like on first boot) + /opt/shift/scripts/systemd-startup-checks.sh + ;; + *) echo "Invalid argument for module ${MODULE}: command ${COMMAND} unknown." errorExit CMD_SCRIPT_INVALID_ARG esac ;; + PRESYNC) + # check and mount external drive + if ! lsblk -o NAME,TYPE -abrnp -e 1,7,31,179,252 | grep part | grep -q "${ARG} " || [ -z "${ARG}" ]; then + echo "ERR: external drive partition not found (specify e.g. '/dev/sda1')" + errorExit PRESYNC_EXTERNAL_DRIVE_NOT_FOUND + fi + + mkdir -p /mnt/ext + if mountpoint /mnt/ext -q; then + umount /mnt/ext + fi + mount "${ARG}" /mnt/ext + + # stop bitcoin services + systemctl stop bitcoind + systemctl stop lightningd + systemctl stop electrs + + case "${COMMAND}" in + # create snapshot of blockchain data + # bbb-cmd.sh presync create /dev/sdb1 + CREATE) + checkMockMode + + if [ ! -d /mnt/ssd/bitcoin/.bitcoin ] || [ ! -d /mnt/ssd/electrs/db/mainnet ]; then + echo "ERR: required directories not found (run with --help for additional details)" >&2 + sleep 5 + errorExit PRESYNC_DIRECTORIES_NOT_FOUND + fi + + # freespace=$(df -k /mnt/ssd | awk '/[0-9]%/{print $(NF-2)}') + # if [[ ${freespace} -lt 400000000 ]]; then + # echo "ERR: not enough disk space, should at least have 400 GB" >&2 + # errorExit PRESYNC_NOT_ENOUGH_DISKSPACE + # fi + + tar cvfW /mnt/ext/bbb-presync-ssd-"$(date '+%Y%m%d-%H%M')".tar \ + -C /mnt/ssd/ \ + bitcoin/.bitcoin/chainstate \ + bitcoin/.bitcoin/blocks \ + bitcoin/.bitcoin/chainstate \ + --exclude='IDENTITY' \ + --exclude='LOG*' \ + --exclude='*.log' \ + electrs/db/mainnet + + echo + echo "OK: Presync archive created." + ls -lh /mnt/ssd/bbb-presync* + ;; + + # restore snapshot of blockchain data + # bbb-cmd.sh presync restore /dev/sdb1 /mnt/ext/bbb-presync-ssd-20191126-2248.tar + RESTORE) + checkMockMode + + echo "${ARG2}" + ls -la "${ARG2}" + + if [[ ! -f ${ARG2} ]]; then + echo "ERR: file ${ARG2} not found" + errorExit PRESYNC_RESTORE_ARCHIVE_NOT_FOUND + fi + + # TODO(Stadicus) + # rm -rf /mnt/ssd/bitcoin/.bitcoin/blocks/* + # rm -rf /mnt/ssd/bitcoin/.bitcoin/chainstate/* + # rm -rf /mnt/ssd/electrs/db/mainnet + + tar xvf "${ARG2}" -C /mnt/ssd + + echo + echo "OK: Presync archive restored." + ;; + + *) + echo "Invalid argument for module ${MODULE}: command ${COMMAND} unknown." + errorExit CMD_SCRIPT_INVALID_ARG + + umount /mnt/ext + + esac + ;; + + *) echo "Invalid argument: module ${MODULE} unknown." errorExit CMD_SCRIPT_INVALID_ARG diff --git a/armbian/base/scripts/create-presync-archive.sh b/armbian/base/scripts/create-presync-archive.sh deleted file mode 100644 index dcdd4c08..00000000 --- a/armbian/base/scripts/create-presync-archive.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/bash -# -# create BitBoxBase presync archive -# -set -eu - -# print usage information for script -usage() { - echo "BitBoxBase: create presync archive -usage: create-presync-archive.sh [--help] - -This script needs to be run on the BitBoxBase and creates an uncompressed archive -with Bitcoin Core blocks/chainstate and Electrs database for presynced devices. - -Requirements: -- Bitcoin Core datadir at /mnt/ssd/bitcoin/.bitcoin -- Electrs database at /mnt/ssd/electrs/db/mainnet - -The presync archive will be created as /mnt/ssd/bbb-presync-ssd-YYYYMMDD-hhmm.tar - -" -} - -if [[ ${#} -ne 0 ]]; then - usage - exit 0 -fi - -if [ ! -d /mnt/ssd/bitcoin/.bitcoin ] || [ ! -d /mnt/ssd/electrs/db/mainnet ]; then - echo "ERR: required directories not found (run with --help for additional details)" >&2 - exit 1 -fi - -if [[ ${UID} -ne 0 ]]; then - echo "ERR: needs to be run as superuser." >&2 - exit 1 -fi - -freespace=$(df -k /mnt/ssd | awk '/[0-9]%/{print $(NF-2)}') -if [[ ${freespace} -lt 400000000 ]]; then - echo "ERR: not enough disk space, should at least have 400 GB" >&2 - exit 1 -fi - -cd /mnt/ssd || exit - -tar cvfW bbb-presync-ssd-"$(date '+%Y%m%d-%H%M')".tar \ - bitcoin/.bitcoin/blocks \ - bitcoin/.bitcoin/chainstate \ - --exclude='IDENTITY' \ - --exclude='LOG*' \ - --exclude='*.log' \ - electrs/db/mainnet - -echo -echo "Archive created:" -echo -ls -lh /mnt/ssd/bbb-presync* -echo diff --git a/armbian/base/scripts/systemd-startup-after-redis.sh b/armbian/base/scripts/systemd-startup-after-redis.sh index 0c3e8047..cec8ab1a 100755 --- a/armbian/base/scripts/systemd-startup-after-redis.sh +++ b/armbian/base/scripts/systemd-startup-after-redis.sh @@ -45,12 +45,12 @@ if FLASHDRIVE="$(/opt/shift/scripts/bbb-cmd.sh flashdrive check)"; then echo "RESET: flashdrive mounted" # are all necessary files for a reset present? - if [[ -f /mnt/backup/.reset-token ]] && [[ -f /data/reset-token-hashes ]]; then - FLASHDRIVE_TOKEN_HASH="$(sha256sum /mnt/backup/.reset-token | cut -f 1 -d " ")" - echo "RESET: reset token present on flashdrive, hashed value: ${FLASHDRIVE_TOKEN_HASH}" + if [[ -f /mnt/backup/.maintenance-token ]] && [[ -f /data/maintenance-token-hashes ]]; then + MAINTENANCE_TOKEN_HASH="$(sha256sum /mnt/backup/.maintenance-token | cut -f 1 -d " ")" + echo "RESET: reset token present on flashdrive, hashed value: ${MAINTENANCE_TOKEN_HASH}" # is hashed reset token present on Base? - if grep -q "${FLASHDRIVE_TOKEN_HASH}" /data/reset-token-hashes; then + if grep -q "${MAINTENANCE_TOKEN_HASH}" /data/maintenance-token-hashes; then echo "RESET: valid reset token found" if [[ -f /mnt/backup/reset-base-auth ]]; then @@ -74,7 +74,7 @@ if FLASHDRIVE="$(/opt/shift/scripts/bbb-cmd.sh flashdrive check)"; then mv /mnt/backup/reset-base-image /mnt/backup/reset-base-image.done fi else - echo "RESET: reset token on flashdrive does not match authorized tokens on the Base" + echo "RESET: maintenance token on flashdrive does not match authorized tokens on the BitBoxBase" fi else echo "RESET: not all files for a reset present, doing nothing." diff --git a/armbian/base/scripts/systemd-startup-checks.sh b/armbian/base/scripts/systemd-startup-checks.sh index 95b67e67..b19ee189 100755 --- a/armbian/base/scripts/systemd-startup-checks.sh +++ b/armbian/base/scripts/systemd-startup-checks.sh @@ -28,12 +28,15 @@ if ! grep -q '/mnt/ssd ' /etc/fstab ; then if lsblk | grep -q 'nvme0n1p1' && [[ $(lsblk -o NAME,SIZE -abrnp | grep nvme0n1p1 | cut -f 2 -d " ") -gt 400000000000 ]]; then exec_overlayroot all-layers "echo '/dev/nvme0n1p1 /mnt/ssd ext4 rw,nosuid,dev,noexec,noatime,nodiratime,auto,nouser,async,nofail 0 2' >> /etc/fstab" - elif lsblk | grep -q 'sda1' && [[ $(lsblk -o NAME,SIZE -abrnp | grep sda1 | cut -f 2 -d " ") -gt 400000000000 ]]; then + # ignore USB drives if NVMe SSD present + elif ! lsblk | grep -q 'nvme0n1' && lsblk | grep -q 'sda1' && [[ $(lsblk -o NAME,SIZE -abrnp | grep sda1 | cut -f 2 -d " ") -gt 400000000000 ]]; then exec_overlayroot all-layers "echo '/dev/sda1 /mnt/ssd ext4 rw,nosuid,dev,noexec,noatime,nodiratime,auto,nouser,async,nofail 0 2' >> /etc/fstab" + elif ! lsblk | grep -q 'nvme0n1' && lsblk | grep -q 'sdb1' && [[ $(lsblk -o NAME,SIZE -abrnp | grep sdb1 | cut -f 2 -d " ") -gt 400000000000 ]]; then + exec_overlayroot all-layers "echo '/dev/sdb1 /mnt/ssd ext4 rw,nosuid,dev,noexec,noatime,nodiratime,auto,nouser,async,nofail 0 2' >> /etc/fstab" + else ## if no valid partition present, is image configured for autosetup of SSD? - if ! mountpoint /mnt/ssd -q && [ -f /opt/shift/config/.autosetup-ssd ]; then # run ssd autosetup, and disable it afterwards on success if /opt/shift/scripts/autosetup-ssd.sh format auto --assume-yes diff --git a/armbian/base/scripts/systemd-startup-maintenance.sh b/armbian/base/scripts/systemd-startup-maintenance.sh new file mode 100755 index 00000000..796d45b2 --- /dev/null +++ b/armbian/base/scripts/systemd-startup-maintenance.sh @@ -0,0 +1,272 @@ +#!/bin/bash + +abort() { + sleep 5 + clear + exit 0 +} +trap 'abort' SIGHUP SIGINT SIGTERM + +if [[ ${UID} -ne 0 ]]; then + echo "ERR: script needs to be run as superuser." + exit 1 +fi + +DIALOGRC='/opt/shift/config/dialog/.dialogrc' +export DIALOGRC + +backtitle="BitBoxBase: Maintenance" +box_h=18 +box_w=60 + +popup_h=14 +popup_w=40 + +# +# check credentials +# ----------------------------------------------------------------------------- + +# exit if no flashdrive found +if ! /opt/shift/scripts/bbb-cmd.sh flashdrive mount &>/dev/null; then + echo "MAINTENANCE: no flashdrive found" + exit +fi +echo "MAINTENANCE: flashdrive mounted to check credentials" + +# exit if no token found +if [[ ! -f /mnt/backup/.maintenance-token ]] || [[ ! -f /data/maintenance-token-hashes ]]; then + echo "MAINTENANCE: flashdrive does not contain a valid maintenance token" + exit +fi +private_token_hash="$(sha256sum /mnt/backup/.maintenance-token | cut -f 1 -d " ")" +echo "MAINTENANCE: found maintenance token (hash (${private_token_hash})" + +# exit if token hash not authorized +if ! grep -q "${private_token_hash}" /data/maintenance-token-hashes; then + echo "MAINTENANCE: maintenance token not authorized" + exit +fi + +echo "MAINTENANCE: valid token found, starting maintenance menu on tty2" + +sleep 5 +chvt 2 + +# +# Submenu: SSD presync +# ----------------------------------------------------------------------------- +submenu_presync() { + while true; do + if ! menuitem=$(dialog --title "SSD presync" --backtitle "${backtitle}" --menu "\nPlease choose maintenance task" ${box_h} ${box_w} 10 \ + 1 "CREATE snapshot on external storage" \ + 2 "IMPORT snapshot to internal ssd" \ + 3>&1 1>&2 2>&3) + then break + fi + + count=0 + unset options + + case $menuitem in + 1) # create snapshot + while read -r partition; do + count=$((count + 1)); + onoff="off" + if [[ count -eq 1 ]]; then + onoff="on" + fi + options[$count]="${partition} ${onoff}" + done <<< "$(lsblk -o NAME,SIZE,TYPE -arnp -e 1,7,31,179,252 | grep part | cut -f 1,2 -d " ")" + + options=(${options[@]}) + cmd=(dialog --title "Create snapshot" --backtitle "${backtitle}" --radiolist "Select target drive:" 22 76 16) + target_drive=$("${cmd[@]}" "${options[@]}" 3>&1 1>&2 2>&3) + + if ! bbb-cmd.sh presync create "${target_drive}"; then + echo + read -rp "An error occurred. Press [Enter] to continue..." + else + dialog --title "Snapshot created" --msgbox "\nPresync snapshot created." ${popup_h} ${popup_w} + fi + ;; + + 2) # import snapshot + # select source drive + while read -r partition; do + count=$((count + 1)); + onoff="off" + if [[ count -eq 1 ]]; then + onoff="on" + fi + options[$count]="${partition} ${onoff}" + done <<< "$(lsblk -o NAME,SIZE,TYPE -arnp -e 1,7,31,179,252 | grep part | cut -f 1,2 -d " ")" + + options=(${options[@]}) + cmd=(dialog --title "Restore snapshot" --backtitle "${backtitle}" --radiolist "Select source drive:" 22 76 16) + source_drive=$("${cmd[@]}" "${options[@]}" 3>&1 1>&2 2>&3) + + # select file + count=0 + unset options + + while read -r partition; do + count=$((count + 1)); + onoff="off" + if [[ count -eq 1 ]]; then + onoff="on" + fi + options[$count]="${partition} ${onoff}" + done <<< "$(stat -c "%n %s" /mnt/ext/bbb-presync*)" + + options=(${options[@]}) + cmd=(dialog --title "Restore snapshot" --backtitle "${backtitle}" --radiolist "Select target drive:" 22 76 16) + source_file=$("${cmd[@]}" "${options[@]}" 3>&1 1>&2 2>&3) + + if ! bbb-cmd.sh presync restore "${source_drive}" "${source_file}"; then + echo + read -rp "An error occurred. Press [Enter] to continue..." + else + dialog --title "Snapshot restored" --msgbox "\nPresync snapshot restored." ${popup_h} ${popup_w} + fi + ;; + *) + break + esac + done +} + +# +# Submenu: Factory reset +# ----------------------------------------------------------------------------- +submenu_reset() { + while true; do + if ! menuitem=$(dialog --title "Factory reset" --backtitle "${backtitle}" --menu "\nPlease choose maintenance task" ${box_h} ${box_w} 10 \ + 1 "AUTHENTICATION reset" \ + 2 "CONFIGURATION reset..." \ + 3 "DISK IMAGE reset..." \ + 3>&1 1>&2 2>&3) + then break + fi + + case $menuitem in + 1) action_confirmation="The AUTHENTICATION credentials will be reset.";; + 2) action_confirmation="The CONFIGURATION will be reset to factory defaults.";; + 3) action_confirmation="The DISK IMAGE on the USB flashdrive will be written to your BitBoxBase.\n\nIt needs to be signed and named 'update.base'.";; + 4) action_confirmation="The SSD including all data (Bitcoin, Lightning, Electrum) will be wiped permanently.";; + esac + + if dialog --title "${backtitle}" --yesno "\n${action_confirmation}\n\nContinue?" 12 50; then + case $menuitem in + 1) # auth + if bbb-cmd.sh reset auth --assume-yes; then + dialog --title "Factory reset" --msgbox "\nOK: Authentication reset.\n\nUse BitBoxApp to set management password again." ${popup_h} ${popup_w} + else + read -rp "An error occurred. Press [Enter] to continue..." + fi + ;; + + 2) # config + if bbb-cmd.sh reset config --assume-yes; then + dialog --title "Configuration reset" --msgbox "\nOK: Configuration reset to factory defaults." ${popup_h} ${popup_w} + while ! bbb-cmd.sh flashdrive check; do + dialog --title "Configuration reset" --msgbox "\nInsert USB flashdrive to store new maintenance token." ${popup_h} ${popup_w} + done + + if bbb-cmd.sh flashdrive mount && bbb-cmd.sh backup sysconfig; then + dialog --title "Configuration reset" --msgbox "\nOK: New maintenance token created on USB flashdrive." ${popup_h} ${popup_w} + else + read -rp "An error occurred. Press [Enter] to continue..." + fi + bbb-cmd.sh flashdrive unmount || true + + else + read -rp "An error occurred. Press [Enter] to continue..." + fi + ;; + + 3) # disk image + if bbb-cmd.sh flashdrive mount && bbb-cmd.sh mender-update install flashdrive; then + dialog --title "Disk Image reset" --msgbox "\nOK: Updated from USB disk image, please reboot." ${popup_h} ${popup_w} + else + read -rp "An error occurred. Press [Enter] to continue..." + fi + bbb-cmd.sh flashdrive unmount || true + ;; + esac + fi + + done +} + +# +# Main menu +# ----------------------------------------------------------------------------- +while true; do + +# Main menu +if ! menuitem=$(dialog --title "Main menu" --backtitle "${backtitle}" --menu "\nPlease choose maintenance task" ${box_h} ${box_w} 10 \ + 1 "SSD presync data..." \ + 2 "Finish factory setup" \ + 3 "Factory reset..." \ + 4 "Shutdown" \ + 3>&1 1>&2 2>&3) + then abort +fi + +case $menuitem in + 1) # presync + submenu_presync + ;; + + 2) # finish factory setup + if dialog --title "${backtitle}" --yesno "\nThis will delete all user data on the SSD, preparing the device for shipping.\n\nIt also deletes the factory setup credentials.\n\nContinue?" 12 50; then + + bbb-systemctl.sh stop + + # first, cleanup ssd data + rm -f /mnt/ssd/bitcoin/.bitcoin/*.log + rm -f /mnt/ssd/bitcoin/.bitcoin/*.dat + rm -f /mnt/ssd/bitcoin/.bitcoin/.cookie* + rm -f /mnt/ssd/bitcoin/.bitcoin/.lock + rm -rf /mnt/ssd/bitcoin/.bitcoin/onion_private_key + rm -rf /mnt/ssd/bitcoin/.bitcoin/testnet3 + rm -rf /mnt/ssd/bitcoin/.lightning* + rm -f /mnt/ssd/electrs/db/mainnet/LOG* + rm -f /mnt/ssd/electrs/db/mainnet/LOCK + rm -rf /mnt/ssd/lost+found + rm -rf /mnt/ssd/system + rm -rf /mnt/ssd/prometheus + + swapoff -a + rm -f /mnt/ssd/swapfile + + systemctl start redis + systemctl start bbbmiddleware + + # remove credentials + if sed -i '/factory token/d' /data/maintenance-token-hashes; then + dialog --title "OK" --msgbox "\nFactory setup credentials deleted." ${popup_h} ${popup_w} + else + dialog --title "ERR" --msgbox "\nError: could not delete factory setup credentials." ${popup_h} ${popup_w} + fi + fi + ;; + + 3) # factory reset + submenu_reset + ;; + + 4) # shutdown + if dialog --title "${backtitle}" --yesno "\n Shut down BitBoxBase?" 8 40; then + shutdown now + fi + ;; +esac + +done + +# ----------------------------------------------------------------------------- + +exit 0 + +clear \ No newline at end of file