openssh-server
 # firewalling
 nftables
+# so every server can store borg backups
+borgbackup
 # for playing nicely with ssh sessions via the foot terminal
 foot-terminfo
 
 . lib/get_passphrase
 . lib/path_tmp_timestamped
 . lib/print_usage
+. lib/retry_until
 cd - > /dev/null
 
 USAGE_DESCRIPTION='Wrapper around certain borgbackup usages.\n\nAvailable commands:'
 USAGE_INDICES='backup_keys claim help info init keys orgpull orgpush'
 
 _run_borg_with_passphrase() {
-    while true; do
+    _FIRST_RUN=1
+    _PREPARE='
         if [ -z "${BORG_PASSPHRASE}" ]; then
-            printf 'Passphrase:'
+            printf "Passphrase:"
             export BORG_PASSPHRASE="$(get_passphrase)"
-            echo ''
+            echo ""
         fi
-        set +e
-        _OUTPUT="$(borg $@)"
-        _RESULT=$?
-        set -e
-        if [ "${_RESULT}" = "0" ]; then
-            break
-        elif [ "${_RESULT}" != "52" ]; then
-            error_exit "unexpected borg error, code ${_RESULT}."
-        fi
-        export BORG_PASSPHRASE=
-    done
+    '
+    _TO_TEST='"$(borg '"$@"')"'
+    _ON_FAIL='echo "unexpected borg error, code ${_RESULT}."'
+    _ON_LOOP_END='export BORG_PASSPHRASE='
+    retry_until 52 "${_PREPARE}" "${_TO_TEST}" "${_ON_FAIL}" "${_ON_LOOP_END}"
 }
 
 _id_from_file() { head -1 "$1" | cut -d' ' -f2; }
 
 . lib/constants_user  # USERNAME
 . lib/constants_borg  # NAME_BORGAPP
 . lib/mount_secrets  # mount_secrets, copy_and_unmount_secrets
+. lib/retry_until
 
 PATH_REPOS="${HOME}/repos"
 REPOS_SITE_DOMAIN=plomlompom.com
 echo "\nSetting up ~/.ssh"
 cp -a "${PATH_SECRETS_SSH}" "${PATH_USER_SSH}"
 eval $(ssh-agent)
-while true; do
-    echo ''
-    stty -echo
-    set +e
-    ssh-add -q
-    RESULT=$?
-    set -e
-    stty echo
-    if [ "${RESULT}" = 0 ]; then
-        break
-    elif [ "${RESULT}" != 1 ]; then
-        echo "Aborting due to ssh-add error."
-    fi
-done
+stty -echo
+trap 'stty echo' EXIT INT TERM
+retry_until 1 'echo ""' 'ssh-add -q' 'echo "Aborting due to ssh-add error"'
+stty echo
+trap '' EXIT INT TERM
 
 echo "\n\nSetting up ~/repos"
 REPOS_SITE_LOGIN="${USERNAME}@${REPOS_SITE_DOMAIN}"
     "${NAME_BORGAPP}" claim "${_FILENAME}"
 done
 cd -
-while true; do
-    set +e
-    "${NAME_BORGAPP}" orgpull
-    RESULT=$?
-    set -e
-    if [ "${RESULT}" = "0" ]; then
-        break
-    elif [ "${RESULT}" != "2" ]; then
-        abort "Aborting due to unexpected ${NAME_BORGAPP} error."
-    fi
-done
+retry_until 2 '' "${NAME_BORGAPP} orgpull" "echo 'Aborting due to unexpected ${NAME_BORGAPP} error.'"
+echo "${_OUTPUT}"
 
 . lib/expect_min_n_args
 . lib/get_passphrase
 . lib/path_tmp_timestamped
+. lib/retry_until
 
 mount_secrets() {
     expect_min_n_args 1 "(device name, e.g. 'sda')" "$@"
     while [ ! -e "${PATH_DEV}" ]; do
         sleep 0.1
     done
-    while true; do
-        printf 'Passphrase: '
-        PASSPHRASE=$(get_passphrase)
-        echo ''
-        set +e
-        echo "${PASSPHRASE}" | pmount "${PATH_DEV}" 2> "${PATH_PMOUNT_ERR}"
-        RESULT=$?
-        set -e
-        if [ "${RESULT}" = "0" ]; then
-            break
-        elif [ "${RESULT}" != "100" ]; then
-        PMOUNT_ERR="$(cat ${PATH_PMOUNT_ERR})"
-        rm "${PATH_PMOUNT_ERR}"
-            abort "Aborting due to pmount error: ${PMOUNT_ERR}"
-        fi
-    done
+    _PREPARE='printf "Passphrase: "; PASSPHRASE=$(get_passphrase); echo ""'
+    _TO_TEST='echo "${PASSPHRASE}" | pmount "${PATH_DEV}" 2>&1'
+    _ON_FAIL='echo "Aborting due to pmount error:'
+    retry_until 100 ${_PREPARE}" "${_TO_TEST}" "${_ON_FAIL}"
+    echo "${_OUTPUT}"
 }
 
 copy_and_unmount_secrets() {
 
--- /dev/null
+retry_until() {
+    _CODE_FOR_CONTINUE="$1"
+    _ON_LOOP_START="$2"
+    _TO_TEST="$3"
+    _ON_FAIL="$4"
+    _ON_LOOP_END="$5"
+    while true; do
+        eval "${_ON_LOOP_START}"
+        set +e
+        _OUTPUT="$(eval ${_TO_TEST}
+        _RESULT=$?
+        set -e
+        if [ "${_RESULT}" = '0' ]; then
+            break
+        elif [ "${RESULT}" != "${_CODE_FOR_CONTINUE} ]; then
+            eval "${_ON_FAIL}"
+            abort
+        fi
+        eval "${_ON_LOOP_END}"
+    done
+}