improvements to configure

This commit is contained in:
2026-10-29 06:36:51 -06:00
parent 1bd73df94f
commit 7209f7424c
7 changed files with 348 additions and 22 deletions
+196 -9
View File
@@ -3,11 +3,30 @@
TITLE="Federated Computer Core"
DESCRIPTION="Superpanel, Nextcloud, email, files and Element"
# What you entered last time, so running this again only does what's missing
# Each Core is in cores/<domain>.conf, with what you entered last time, so
# running this again only does what's missing. core.conf is a copy of the main
# Core's: Element, Tailscale and Backup use that one.
CORE_CONF="$HOME/.config/coredesktop/core.conf"
CORES_DIR="$HOME/.config/coredesktop/cores"
TAILSCALE_CONF="$HOME/.config/coredesktop/tailscale.conf"
BACKUP_CONF="$HOME/.config/coredesktop/backup.conf"
GOA_ACCOUNT="$COREDESKTOP/configure.d/lib/goa-account"
source "$COREDESKTOP/configure.d/lib/nextcloud.sh"
[ -f "$CORE_CONF" ] && source "$CORE_CONF"
MAIN_DOMAIN="$CORE_DOMAIN"
core_domains() {
local file
for file in "$CORES_DIR"/*.conf; do
[ -f "$file" ] && basename "$file" .conf
done
}
load_core() {
CORE_DOMAIN="" CORE_EMAIL="" CORE_NAME=""
[ -n "$1" ] && source "$CORES_DIR/$1.conf"
core_names
}
# CORE_DOMAIN, CORE_EMAIL and CORE_NAME come from core.conf; the rest follow
core_names() {
@@ -48,19 +67,37 @@ element_done() {
"$ELEMENT_CONFIG" &> /dev/null
}
is_configured() {
[ -n "$CORE_DOMAIN" ] || return 1
core_names
superpanel_done && nextcloud_done && email_done && files_done && element_done
# Element only follows the main Core
core_done() {
superpanel_done && nextcloud_done && email_done && files_done \
&& { [ "$CORE_DOMAIN" != "$MAIN_DOMAIN" ] || element_done; }
}
# Done when every Core is
is_configured() {
local domain domains
domains="$(core_domains)"
[ -n "$domains" ] || return 1
for domain in $domains; do
(load_core "$domain" && core_done) || return 1
done
}
# The first Core you set up is the main one
save_conf() {
mkdir -p "$(dirname "$CORE_CONF")"
mkdir -p "$CORES_DIR"
{
printf 'CORE_DOMAIN=%q\n' "$CORE_DOMAIN"
printf 'CORE_EMAIL=%q\n' "$CORE_EMAIL"
printf 'CORE_NAME=%q\n' "$CORE_NAME"
} > "$CORE_CONF"
} > "$CORES_DIR/$CORE_DOMAIN.conf"
if [ -z "$MAIN_DOMAIN" ] || [ "$MAIN_DOMAIN" = "$CORE_DOMAIN" ]; then
make_main "$CORE_DOMAIN"
fi
}
make_main() {
cp "$CORES_DIR/$1.conf" "$CORE_CONF" && MAIN_DOMAIN="$1"
}
desktop_entry() {
@@ -263,7 +300,8 @@ step() {
"setup_$name" || { echo -e "\e[31m$title was not set up.\e[0m"; STATUS=1; }
}
run_configure() {
# Set up the Core loaded with load_core, or a new one
setup_core() {
local url
STATUS=0
@@ -304,7 +342,156 @@ run_configure() {
step nextcloud "Nextcloud in Online Accounts"
step email "Email in Online Accounts"
step files "Nextcloud files at $MOUNT"
element_installed && step element "Element with your Core's Matrix server"
[ "$CORE_DOMAIN" = "$MAIN_DOMAIN" ] && element_installed \
&& step element "Element with your Core's Matrix server"
unset PASSWORD APP_PASSWORD
return $STATUS
}
# Tailscale and Backup point at one Core, which can't be removed while they do
tailscale_on() {
[ "$(source "$TAILSCALE_CONF" 2> /dev/null && echo "$TAILSCALE_DOMAIN")" = "$1" ] \
&& tailscale status --json 2> /dev/null | jq -e '.BackendState == "Running"' > /dev/null
}
backup_on() {
[[ "$(source "$BACKUP_CONF" 2> /dev/null && echo "$BACKUP_WEBDAV")" == "https://nextcloud.$1/"* ]] \
&& systemctl --user is-enabled -q coredesktop-backup.timer 2> /dev/null
}
# Choose one of DOMAINS, other than $2 if given; sets PICKED
pick_core() {
local choices=() domain choice i
for domain in "${DOMAINS[@]}"; do
[ "$domain" != "$2" ] && choices+=("$domain")
done
if [ ${#choices[@]} -eq 1 ]; then
PICKED="${choices[0]}"
return 0
fi
for i in "${!choices[@]}"; do
printf ' %d) %s\n' $((i + 1)) "${choices[$i]}"
done
read -rp "$1 " choice
[[ "$choice" =~ ^[0-9]+$ ]] && (( choice >= 1 && choice <= ${#choices[@]} )) || return 1
PICKED="${choices[$((choice - 1))]}"
}
# Point Element at the main Core, and say what else follows it
main_changed() {
load_core "$MAIN_DOMAIN"
echo "$MAIN_DOMAIN is now your main Core."
if element_installed && ! element_done && confirm_yes "Point Element at $MATRIX?"; then
setup_element
fi
[ -f "$TAILSCALE_CONF" ] && echo "To move this computer to its Tailscale network: configure tailscale"
[ -f "$BACKUP_CONF" ] && echo "To back up to it instead: configure backup"
return 0
}
# The app password this computer uses for the Core, from davfs2's secrets
files_app_password() {
grep -s "^$MOUNT " "$HOME/.davfs2/secrets" \
| python3 -I -c 'import shlex, sys; print(shlex.split(sys.stdin.read())[2])' 2> /dev/null
}
# Undo what setup_core did. Nothing on the Core itself changes.
remove_core() {
local domain="$1" new_main="" app_password mount_re
if tailscale_on "$domain"; then
echo "This computer is on $domain's Tailscale network. Leave it first: configure tailscale"
return 1
fi
if backup_on "$domain"; then
echo "Your backups go to $domain. Turn them off first: configure backup"
return 1
fi
if [ "$domain" = "$MAIN_DOMAIN" ] && [ ${#DOMAINS[@]} -gt 1 ]; then
echo "$domain is your main Core. Which Core should be the main one instead?"
pick_core "Choose:" "$domain" || { echo "Choose a number from the list."; return 1; }
new_main="$PICKED"
fi
echo "This removes $domain's Superpanel, Nextcloud, email and files from this computer."
echo "Your files, email and everything else stay on the Core."
confirm "Remove $domain?" || return 0
load_core "$domain"
app_password="$(files_app_password)"
[ -n "$app_password" ] && nextcloud_revoke_app_password "$app_password"
mountpoint -q "$MOUNT" && { umount "$MOUNT" 2> /dev/null || sudo umount "$MOUNT"; }
mount_re="${MOUNT//./\\.}"
if grep -qs " $MOUNT davfs " /etc/fstab; then
sudo sed -i "\\# $mount_re davfs #d" /etc/fstab && sudo systemctl daemon-reload
fi
[ -d "$MOUNT" ] && sudo rmdir "$MOUNT" 2> /dev/null
sed -i "\\#^$mount_re #d" "$HOME/.davfs2/secrets" 2> /dev/null
sed -i "\\#^file://$mount_re #d" "$HOME/.config/gtk-3.0/bookmarks" 2> /dev/null
rm -f "$HOME/.config/autostart/core-$CORE_DOMAIN-files.desktop"
"$GOA_ACCOUNT" remove owncloud "$CORE_USER@nextcloud.$CORE_DOMAIN"
"$GOA_ACCOUNT" remove imap_smtp "$CORE_EMAIL"
rm -f "$SUPERPANEL_DESKTOP" "$HOME/.local/share/icons/core-$CORE_DOMAIN-superpanel.png"
# Element keeps its default server, unless that was this Core
if [ "$domain" = "$MAIN_DOMAIN" ] && [ -z "$new_main" ] && [ -f "$ELEMENT_CONFIG" ] \
&& jq -e --arg name "matrix.$domain" '.default_server_config["m.homeserver"].server_name == $name' \
"$ELEMENT_CONFIG" &> /dev/null; then
jq 'del(.default_server_config)' "$ELEMENT_CONFIG" > "$ELEMENT_CONFIG.tmp" \
&& mv -f "$ELEMENT_CONFIG.tmp" "$ELEMENT_CONFIG"
fi
rm -f "$CORES_DIR/$domain.conf"
echo "Removed $domain from this computer."
if [ -n "$new_main" ]; then
make_main "$new_main" && main_changed
elif [ "$domain" = "$MAIN_DOMAIN" ]; then
rm -f "$CORE_CONF"
fi
}
run_configure() {
local choice i state
mapfile -t DOMAINS < <(core_domains)
if [ ${#DOMAINS[@]} -eq 0 ]; then
load_core ""
setup_core
return
fi
echo "Your Cores:"
for i in "${!DOMAINS[@]}"; do
if (load_core "${DOMAINS[$i]}" && core_done); then
state="\e[32mdone\e[0m "
else
state="\e[33mto do\e[0m"
fi
printf " %d) $state %s%s\n" $((i + 1)) "${DOMAINS[$i]}" \
"$([ "${DOMAINS[$i]}" = "$MAIN_DOMAIN" ] && echo " (main)")"
done
echo
echo " Choose a number to finish or change its setup, or:"
echo " a) Add a Core"
[ ${#DOMAINS[@]} -gt 1 ] && echo " m) Make another Core the main one"
echo " r) Remove a Core"
echo " q) Leave it as it is"
echo
read -rp "Choose: " choice
case "$choice" in
a|A)
load_core ""
setup_core ;;
m|M)
[ ${#DOMAINS[@]} -gt 1 ] || return 0
pick_core "Which should be the main one?" "$MAIN_DOMAIN" || { echo "Choose a number from the list."; return 1; }
make_main "$PICKED" && main_changed ;;
r|R)
pick_core "Which Core should be removed?" || { echo "Choose a number from the list."; return 1; }
remove_core "$PICKED" ;;
*)
if [[ "$choice" =~ ^[0-9]+$ ]] && (( choice >= 1 && choice <= ${#DOMAINS[@]} )); then
load_core "${DOMAINS[$((choice - 1))]}"
setup_core
fi ;;
esac
}