test core for configure
This commit is contained in:
@@ -218,7 +218,7 @@ configure
|
||||
|
||||
It covers:
|
||||
|
||||
- **Your Federated Computer Core.** Give it your Superpanel's address (e.g. https://superpanel.example.com), your Core email, name and password, and it adds Superpanel to your applications, adds your Nextcloud (calendar, contacts and files) and email to GNOME's Online Accounts, and mounts your Nextcloud files at /mnt/example.com ("example.com" in the Files sidebar), and points Element at your Core's Matrix server. For Nextcloud and the files it creates a Nextcloud app password, which you can revoke in Nextcloud under Settings > Security. You can add more Cores: run `configure core` again and choose "Add a Core". Each gets its own Superpanel, Nextcloud, email and files; Element, Tailscale and backups use your main Core (the first one, unless you choose another). "Remove a Core" takes it off this computer and revokes its app password, and leaves everything on the Core itself as it is. If you change your Core password (e.g. in Superpanel), run `configure core` and choose "Your Core password changed": email keeps your Core password, so it saves the new one there, and it signs in to Nextcloud with it, which turns the app passwords for Nextcloud, files and backups back on (Nextcloud turns them off when your password changes), then checks each of them.
|
||||
- **Your Federated Computer Core.** Give it your Superpanel's address (e.g. https://superpanel.example.com), your Core email, name and password, and it adds Superpanel to your applications, adds your Nextcloud (calendar, contacts and files) and email to GNOME's Online Accounts, and mounts your Nextcloud files at /mnt/example.com ("example.com" in the Files sidebar), and points Element at your Core's Matrix server. For Nextcloud and the files it creates a Nextcloud app password, which you can revoke in Nextcloud under Settings > Security. You can add more Cores: run `configure core` again and choose "Add a Core". Each gets its own Superpanel, Nextcloud, email and files; Element, Tailscale and backups use your main Core (the first one, unless you choose another). "Remove a Core" takes it off this computer and revokes its app password, and leaves everything on the Core itself as it is. If you change your Core password (e.g. in Superpanel), run `configure core` and choose "Your Core password changed": email keeps your Core password, so it saves the new one there, and it signs in to Nextcloud with it, which turns the app passwords for Nextcloud, files and backups back on (Nextcloud turns them off when your password changes), then checks each of them. To check that a Core still works from this computer, run `configure core` and choose "Test a Core": it signs in to Superpanel, Nextcloud, email, your files, Element's Matrix server and backups the way this computer does, says which work, and offers to fix those that don't (asking for your Core password if a fix needs it, e.g. to make a new app password for one that was revoked), then tests again.
|
||||
- **Your Core's Tailscale network.** Joins this computer to it through headscale.example.com, so you can reach your other machines on it. Set up your Core first. You sign in through a link it shows you; if this computer is on another Tailscale network, it moves it to your Core's. To leave your Core's network, run `configure tailscale` again.
|
||||
- **Daily backups of your home folder** to your Nextcloud files, in a .backup-{machine name} folder, with restic. Set up your Core first. The backup is encrypted with a passphrase that `configure` shows you once: save it somewhere other than this computer, such as Bitwarden. It keeps 7 daily, 4 weekly and 6 monthly backups, and leaves out caches, things that can be reinstalled, and WinBoat's Windows VM (~/winboat). To leave out more, list paths in ~/.config/coredesktop/backup-exclude, one per line. restic reaches Nextcloud directly through rclone with its own Nextcloud app password, so the backup doesn't depend on the /mnt mount. See "Restoring from a backup" below. To turn backups off, run `configure backup` again; it also offers to delete the backups from your Nextcloud files (they go to Nextcloud's trash bin).
|
||||
- Signing in to Claude Code, opencode and Hermes Agent and choosing their model providers.
|
||||
|
||||
+237
-23
@@ -218,13 +218,24 @@ EOF
|
||||
echo "Added $CORE_EMAIL to Online Accounts."
|
||||
}
|
||||
|
||||
# Save APP_PASSWORD for davfs2 to mount your files with. davfs2 only reads
|
||||
# this file if no one else can.
|
||||
save_files_secret() {
|
||||
local secret
|
||||
mkdir -p -m 700 "$HOME/.davfs2"
|
||||
touch "$HOME/.davfs2/secrets"
|
||||
chmod 600 "$HOME/.davfs2/secrets"
|
||||
secret="${APP_PASSWORD//\\/\\\\}"
|
||||
secret="${secret//\"/\\\"}"
|
||||
sed -i "\\#^$MOUNT #d" "$HOME/.davfs2/secrets"
|
||||
printf '%s %s "%s"\n' "$MOUNT" "$CORE_USER" "$secret" >> "$HOME/.davfs2/secrets"
|
||||
}
|
||||
|
||||
# Mount your Nextcloud files at /mnt/<domain> with davfs2. You can mount it
|
||||
# without sudo once it's in /etc/fstab with "user" and you're in Arch's davfs2
|
||||
# group (network). It's mounted now and each time you log in.
|
||||
setup_files() {
|
||||
[ -n "$APP_PASSWORD" ] || { echo "This needs your Core password, and Nextcloud didn't accept it."; return 1; }
|
||||
local secret
|
||||
|
||||
sudo install -d -o "$USER" -g "$(id -gn)" "$MOUNT" || return 1
|
||||
if ! grep -qs " $MOUNT davfs " /etc/fstab; then
|
||||
echo "$WEBDAV $MOUNT davfs rw,user,noauto,uid=$USER,_netdev 0 0" | sudo tee -a /etc/fstab > /dev/null || return 1
|
||||
@@ -234,15 +245,7 @@ setup_files() {
|
||||
if ! id -nG "$USER" | grep -qw network; then
|
||||
sudo usermod -aG network "$USER" || return 1
|
||||
fi
|
||||
|
||||
# davfs2 only reads this file if no one else can
|
||||
mkdir -p -m 700 "$HOME/.davfs2"
|
||||
touch "$HOME/.davfs2/secrets"
|
||||
chmod 600 "$HOME/.davfs2/secrets"
|
||||
secret="${APP_PASSWORD//\\/\\\\}"
|
||||
secret="${secret//\"/\\\"}"
|
||||
sed -i "\\#^$MOUNT #d" "$HOME/.davfs2/secrets"
|
||||
printf '%s %s "%s"\n' "$MOUNT" "$CORE_USER" "$secret" >> "$HOME/.davfs2/secrets"
|
||||
save_files_secret || return 1
|
||||
|
||||
mkdir -p "$HOME/.config/autostart"
|
||||
cat > "$HOME/.config/autostart/core-$CORE_DOMAIN-files.desktop" << EOF
|
||||
@@ -300,6 +303,25 @@ step() {
|
||||
"setup_$name" || { echo -e "\e[31m$title was not set up.\e[0m"; STATUS=1; }
|
||||
}
|
||||
|
||||
# Ask for your Core password until Nextcloud takes it, and with a name ($1),
|
||||
# create an app password by that name (APP_PASSWORD). PASSWORD is left empty
|
||||
# if Nextcloud says it's wrong three times, and kept, unchecked, if Nextcloud
|
||||
# can't be reached.
|
||||
ask_password() {
|
||||
local tries
|
||||
for tries in 1 2 3; do
|
||||
read -rsp "Your Core password: " PASSWORD
|
||||
echo
|
||||
if [ -n "$1" ]; then nextcloud_app_password "$1"; else nextcloud_sign_in; fi
|
||||
case $? in
|
||||
0) return 0 ;;
|
||||
2) echo "Nextcloud says that password is wrong."; PASSWORD="" ;;
|
||||
*) echo "Couldn't reach Nextcloud at $NEXTCLOUD; trying the password for email anyway."; return 1 ;;
|
||||
esac
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# Set up the Core loaded with load_core, or a new one
|
||||
setup_core() {
|
||||
local url
|
||||
@@ -324,17 +346,7 @@ setup_core() {
|
||||
|
||||
# Nextcloud, email and files need your Core password; Nextcloud checks it
|
||||
if ! nextcloud_done || ! email_done || ! files_done; then
|
||||
local tries
|
||||
for tries in 1 2 3; do
|
||||
read -rsp "Your Core password: " PASSWORD
|
||||
echo
|
||||
nextcloud_app_password "CoreDesktop on $HOSTNAME"
|
||||
case $? in
|
||||
0) break ;;
|
||||
2) echo "Nextcloud says that password is wrong."; PASSWORD="" ;;
|
||||
*) echo "Couldn't reach Nextcloud at $NEXTCLOUD; trying the password for email anyway."; break ;;
|
||||
esac
|
||||
done
|
||||
ask_password "CoreDesktop on $HOSTNAME"
|
||||
fi
|
||||
|
||||
echo
|
||||
@@ -401,7 +413,7 @@ change_password() {
|
||||
echo " Nextcloud in Online Accounts: working"
|
||||
else
|
||||
echo -e " \e[31mNextcloud in Online Accounts: can't sign in.\e[0m"
|
||||
echo " Remove it in Settings > Online Accounts, then run: configure core"
|
||||
echo " To fix it: configure core, then choose t) Test a Core"
|
||||
STATUS=1
|
||||
fi
|
||||
fi
|
||||
@@ -513,6 +525,204 @@ remove_core() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Testing a Core checks each part this computer set up for it against the
|
||||
# Core itself, then offers to fix what doesn't work. A test that fails adds a
|
||||
# fix, if there is one, to FIXES (with its title in FIX_TITLES).
|
||||
|
||||
passed() {
|
||||
echo -e " $1: \e[32mworking\e[0m"
|
||||
}
|
||||
|
||||
# failed <title> <problem> [fix] [more]
|
||||
failed() {
|
||||
echo -e " \e[31m$1: $2\e[0m"
|
||||
[ -n "$4" ] && echo " $4"
|
||||
PROBLEMS=$((PROBLEMS + 1))
|
||||
[ -n "$3" ] && FIXES+=("$3") FIX_TITLES+=("$1")
|
||||
}
|
||||
|
||||
# Test an Online Accounts account: <title> <provider> <identity> <setup> <fix>
|
||||
test_account() {
|
||||
local error
|
||||
if ! "$GOA_ACCOUNT" exists "$2" "$3" 2> /dev/null; then
|
||||
failed "$1" "not set up" "$4"
|
||||
elif error="$("$GOA_ACCOUNT" check "$2" "$3" 2>&1)"; then
|
||||
passed "$1"
|
||||
else
|
||||
failed "$1" "can't sign in" "$5" "$error"
|
||||
fi
|
||||
}
|
||||
|
||||
test_files() {
|
||||
local title="Nextcloud files at $MOUNT"
|
||||
files_done || { failed "$title" "not set up" setup_files; return; }
|
||||
nextcloud_sign_in "$(files_app_password)"
|
||||
case $? in
|
||||
0) if mountpoint -q "$MOUNT" && timeout 15 ls "$MOUNT" &> /dev/null; then
|
||||
passed "$title"
|
||||
else
|
||||
failed "$title" "not mounted" remount_files
|
||||
fi ;;
|
||||
2) failed "$title" "Nextcloud doesn't accept its app password" fix_files \
|
||||
"It may have been revoked in Nextcloud under Settings > Security." ;;
|
||||
*) failed "$title" "couldn't check its app password" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
test_element() {
|
||||
local title="Element with your Core's Matrix server"
|
||||
if ! element_done; then
|
||||
failed "$title" "Element uses another server" setup_element
|
||||
elif curl -sf -o /dev/null --max-time 15 "$MATRIX/_matrix/client/versions"; then
|
||||
passed "$title"
|
||||
else
|
||||
failed "$title" "can't reach $MATRIX"
|
||||
fi
|
||||
}
|
||||
|
||||
test_backups() {
|
||||
local webdav
|
||||
webdav="$(source "$BACKUP_CONF" && echo "$BACKUP_WEBDAV")"
|
||||
nextcloud_sign_in "$(secret-tool lookup coredesktop backup item nextcloud url "$webdav" 2> /dev/null)"
|
||||
case $? in
|
||||
0) passed "Backups" ;;
|
||||
2) failed "Backups" "Nextcloud doesn't accept their app password" fix_backups ;;
|
||||
*) failed "Backups" "couldn't check their app password" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Test the Core loaded with load_core. Fails if Nextcloud can't be reached,
|
||||
# as then nothing else can be tested.
|
||||
test_core() {
|
||||
local status
|
||||
FIXES=() FIX_TITLES=() PROBLEMS=0
|
||||
status="$(curl -sf --max-time 15 "$NEXTCLOUD/status.php")"
|
||||
if [ -z "$status" ]; then
|
||||
echo -e " \e[31mCouldn't reach Nextcloud at $NEXTCLOUD.\e[0m"
|
||||
echo " Check this computer's internet connection, or whether your Core is down."
|
||||
return 1
|
||||
fi
|
||||
if jq -e '.maintenance' <<< "$status" > /dev/null 2>&1; then
|
||||
echo " Nextcloud is being updated (maintenance mode). Test again when it's done."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! superpanel_done; then
|
||||
failed "Superpanel in your applications" "not set up" setup_superpanel
|
||||
elif curl -s -o /dev/null --max-time 15 "https://superpanel.$CORE_DOMAIN/"; then
|
||||
passed "Superpanel"
|
||||
else
|
||||
failed "Superpanel" "can't reach https://superpanel.$CORE_DOMAIN"
|
||||
fi
|
||||
test_account "Nextcloud in Online Accounts" owncloud "$CORE_USER@nextcloud.$CORE_DOMAIN" \
|
||||
setup_nextcloud fix_nextcloud
|
||||
test_account "Email in Online Accounts" imap_smtp "$CORE_EMAIL" setup_email fix_email
|
||||
test_files
|
||||
[ "$CORE_DOMAIN" = "$MAIN_DOMAIN" ] && element_installed && test_element
|
||||
backup_on "$CORE_DOMAIN" && test_backups
|
||||
return 0
|
||||
}
|
||||
|
||||
# Online Accounts gets a new app password
|
||||
fix_nextcloud() {
|
||||
[ -n "$APP_PASSWORD" ] || { echo "This needs your Core password, and Nextcloud didn't accept it."; return 1; }
|
||||
jq -n --arg password "$APP_PASSWORD" '{password: $password}' \
|
||||
| "$GOA_ACCOUNT" update owncloud "$CORE_USER@nextcloud.$CORE_DOMAIN" || return 1
|
||||
echo "Nextcloud in Online Accounts has a new app password."
|
||||
}
|
||||
|
||||
# Email gets your Core password. If the mail server still says no, its
|
||||
# settings may have changed, so add it again with the server's settings now.
|
||||
fix_email() {
|
||||
[ -n "$PASSWORD" ] || { echo "This needs your Core password."; return 1; }
|
||||
jq -n --arg password "$PASSWORD" '{"imap-password": $password, "smtp-password": $password}' \
|
||||
| "$GOA_ACCOUNT" update imap_smtp "$CORE_EMAIL" 2> /dev/null
|
||||
case $? in
|
||||
0) echo "Email has your Core password." ;;
|
||||
3) echo "The mail server still says no; adding your email again with its current settings."
|
||||
"$GOA_ACCOUNT" remove imap_smtp "$CORE_EMAIL" && setup_email ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Unmount if it's stuck, then mount
|
||||
remount_files() {
|
||||
if mountpoint -q "$MOUNT"; then
|
||||
umount "$MOUNT" 2> /dev/null || sudo umount "$MOUNT" || return 1
|
||||
fi
|
||||
mount "$MOUNT" 2> /dev/null || sudo -u "$USER" mount "$MOUNT" || return 1
|
||||
echo "Your Nextcloud files are at $MOUNT."
|
||||
}
|
||||
|
||||
# davfs2 gets a new app password
|
||||
fix_files() {
|
||||
[ -n "$APP_PASSWORD" ] || { echo "This needs your Core password, and Nextcloud didn't accept it."; return 1; }
|
||||
save_files_secret && remount_files
|
||||
}
|
||||
|
||||
# Backups get their own new app password, as configure backup gives them
|
||||
fix_backups() {
|
||||
local APP_PASSWORD webdav
|
||||
[ -n "$PASSWORD" ] || { echo "This needs your Core password."; return 1; }
|
||||
webdav="$(source "$BACKUP_CONF" && echo "$BACKUP_WEBDAV")"
|
||||
nextcloud_app_password "CoreDesktop backup on $HOSTNAME" || return 1
|
||||
printf '%s' "$APP_PASSWORD" | secret-tool store --label "CoreDesktop backup nextcloud ($webdav)" \
|
||||
coredesktop backup item nextcloud url "$webdav" || return 1
|
||||
echo "Backups have a new app password."
|
||||
}
|
||||
|
||||
# Run the fixes test_core found, asking for your Core password once if they
|
||||
# need it
|
||||
fix_core() {
|
||||
local fix i needs=""
|
||||
for fix in "${FIXES[@]}"; do
|
||||
case "$fix" in
|
||||
setup_nextcloud|fix_nextcloud|setup_files|fix_files) needs=app ;;
|
||||
setup_email|fix_email|fix_backups) needs="${needs:-password}" ;;
|
||||
esac
|
||||
done
|
||||
case "$needs" in
|
||||
app) ask_password "CoreDesktop on $HOSTNAME" ;;
|
||||
password) ask_password ;;
|
||||
esac
|
||||
|
||||
STATUS=0
|
||||
for i in "${!FIXES[@]}"; do
|
||||
echo
|
||||
echo "${FIX_TITLES[$i]}:"
|
||||
"${FIXES[$i]}" || { echo -e "\e[31m${FIX_TITLES[$i]} was not fixed.\e[0m"; STATUS=1; }
|
||||
done
|
||||
unset PASSWORD APP_PASSWORD
|
||||
return $STATUS
|
||||
}
|
||||
|
||||
check_core() {
|
||||
load_core "$1"
|
||||
echo "Testing $CORE_DOMAIN..."
|
||||
test_core || return 1
|
||||
if [ $PROBLEMS -eq 0 ]; then
|
||||
echo "Everything works."
|
||||
return 0
|
||||
fi
|
||||
echo
|
||||
if [ ${#FIXES[@]} -eq 0 ]; then
|
||||
echo "This computer can't fix that; it's on the Core's side, or the network's."
|
||||
return 1
|
||||
fi
|
||||
confirm_yes "Fix what doesn't work?" || return 1
|
||||
fix_core
|
||||
|
||||
echo
|
||||
echo "Testing $CORE_DOMAIN again..."
|
||||
test_core || return 1
|
||||
if [ $PROBLEMS -eq 0 ]; then
|
||||
echo "Everything works now."
|
||||
else
|
||||
echo "Some of it still doesn't work."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
run_configure() {
|
||||
local choice i state
|
||||
mapfile -t DOMAINS < <(core_domains)
|
||||
@@ -536,6 +746,7 @@ run_configure() {
|
||||
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 " t) Test a Core, and fix what doesn't work"
|
||||
echo " p) Your Core password changed"
|
||||
echo " r) Remove a Core"
|
||||
echo " q) Leave it as it is"
|
||||
@@ -552,6 +763,9 @@ run_configure() {
|
||||
p|P)
|
||||
pick_core "Which Core's password changed?" || { echo "Choose a number from the list."; return 1; }
|
||||
change_password "$PICKED" ;;
|
||||
t|T)
|
||||
pick_core "Which Core should be tested?" || { echo "Choose a number from the list."; return 1; }
|
||||
check_core "$PICKED" ;;
|
||||
r|R)
|
||||
pick_core "Which Core should be removed?" || { echo "Choose a number from the list."; return 1; }
|
||||
remove_core "$PICKED" ;;
|
||||
|
||||
Reference in New Issue
Block a user