From 44c67c980fef7046d36f5d997770f7904f39b775 Mon Sep 17 00:00:00 2001 From: David Young Date: Tue, 27 Oct 2026 06:30:58 -0600 Subject: [PATCH] various improvements and fixes --- README.md | 22 ++++++++------ install-flatpaks.sh | 1 - install.sh | 50 ++++++++++++++++++------------- migrations/1793103962.sh | 8 +++++ remove-packages.conf | 1 + sandbox/config/base.json | 2 ++ skills/sibling-project-updates.md | 1 - updates.d/10-pacman.sh | 12 ++++---- updates.d/60-pipx.sh | 22 +++++++++----- utils.sh | 9 ++++++ 10 files changed, 83 insertions(+), 45 deletions(-) create mode 100644 migrations/1793103962.sh diff --git a/README.md b/README.md index 29bcb12..38f1fd1 100644 --- a/README.md +++ b/README.md @@ -49,11 +49,15 @@ When Arch and Gnome have been successfully installed, you log in to the system t 2) Open a terminal, then enter the following command (you copied it from Gitea in step #1): ``` -wget -qO- https://gitea.federated.computer/david/coredesktop/raw/branch/main/install.sh | bash +wget -qO- https://gitea.federated.computer/Federated_Computer/coredesktop/raw/branch/main/install.sh | bash ``` -3) You'll have to enter your password a couple times and click to install a gnome extension. Be patient. When the installation finishes, reboot (command: 'sudo reboot now') so that Element can find the encryption keychain. +3) Enter your password when asked, once at the start. Be patient: it takes a while. -4) If something fails, just run the script again. The typical fails are not entering the password in time, or failing to click on a Gnome extension dialog. Just re-run the script and it will get through everything. You'll know you're done when the script asks you to reboot your machine. +4) At the end, it offers to run `configure`, which connects to your Federated Computer Core, sets up backups and signs you in to the AI agents (see "Configure" below). If the install brought in a newer kernel, it asks you to reboot first; run `configure` after the reboot. + +5) If something fails, just run the command again. It skips what's already done. + +6) Reboot (`sudo reboot now`) when you're done, so that Element can find the encryption keychain, among other things. ## Notes about what is installed @@ -65,7 +69,7 @@ The scripts install lots of useful software. There are (4) main ways software is ### Pacman -Pacman installs software from the "packages.conf" file. It installs software such as nice versions of neovim, tmux, VS Codium (VS Code without the M$ surveillance), Go, etc. Tell me if you want other tools or submit a pull request. +Pacman installs software from the "packages.conf" file. It installs software such as neovim, tmux, Go, Rust, Docker, Tailscale, Element, LibreOffice, etc. Tell me if you want other tools or submit a pull request. ### AUR @@ -75,7 +79,7 @@ Yay is installed as is the way AUR packages are installed and maintained. Exampl The file "install-flatpaks.sh" file for Flatpaks. -Flatpaks installed: Chrome, Chromium, Firefox, Brave, Zen, Vivaldi, Warehouse (manage Flatpaks), Embellish (manage fonts), Revolt (Discord clone), Impression (burn ISOs to usb sticks), Logseq (note taking), Apostrophe (markdown writer), Signal (messaging), Thunderbird (email), Trayscale (tailnet), VS Code (IDE), Telegram (messaging), LibbreOffice, Extension Manager (for Gnome extensions), Nextcloud client, Kdenlive (video editing), OBS (video recording), Discord (messaging), Spotify (music), VLC (video watching), Obsidian (note taking), qBittorent, Bitwarden desktop, Inkscape (postscript editor), Zoom, Audacity (audio editing), Remmina (remote desktop), Postman, Alpaca (work with AI), DBeaver (database client), Jellyfin Media (client), Zen (interesting browser project), Localsend (send stuff to other devices easily), Boxes (virtual machines) and much else. +Flatpaks installed include: Chrome, Chromium, Firefox, Brave, Zen, Vivaldi (browsers), Signal, Telegram, Discord, Revolt, FluffyChat (messaging), Thunderbird and Evolution (email), VS Code and VSCodium (VS Code without the Microsoft telemetry), Obsidian and Logseq (notes), Apostrophe (markdown writer), Kdenlive (video editing), OBS (video recording), Audacity (audio editing), Inkscape (vector graphics), Scribus (page layout), Spotify, Jellyfin (media client), Zoom, Remmina and RustDesk (remote desktop), Postman, DBeaver and Beekeeper Studio (database clients), Alpaca and LM Studio (local AI), LocalSend (send files to other devices), Boxes (virtual machines), Impression (write ISOs to USB sticks), Trayscale (Tailscale), Warehouse (manage Flatpaks), Extension Manager (GNOME extensions), qBittorrent, RetroArch and more. See [install-flatpaks.sh](install-flatpaks.sh) for the full list. If you want to install more software from Flathub, simple visit https://flathub.org. @@ -149,10 +153,10 @@ The script pulls the latest CoreDesktop, then runs each step in ~/.local/share/c - stops if there's less than 10 GiB free on / (run `UPDATE_FORCE=1 update` to skip the check) - snapshots / first, if Snapper is set up (see Snapshots above) -- updates the Arch keyring, then Arch and GNOME, then AUR packages, Flatpaks, Ruby, GNOME extensions and firmware +- updates the Arch keyring, then Arch and GNOME, then AUR packages, Flatpaks, Ruby, the pipx apps CoreDesktop installs, GNOME extensions and firmware - warns you not to reboot if the initramfs failed to rebuild - runs any one-time migrations, the way existing machines pick up new CoreDesktop setup -- removes packages that were installed only because something else needed them, and are no longer needed by anything. It lists what it removed. To stop a package you use directly from being removed, run `sudo pacman -D --asexplicit ` +- removes packages that were installed only because something else needed them, and are no longer needed by anything. It lists what it removed. Packages CoreDesktop installs are never removed this way. To stop another package you use directly from being removed, run `sudo pacman -D --asexplicit ` If a step fails, the other steps still run, and the failed ones are listed at the end. @@ -243,7 +247,7 @@ restic snapshots CoreDesktop installs the AI coding agents opencode, Hermes Agent and Claude Code, and runs them in a sandbox. In the sandbox, an agent: - can change files only in the directory you start it from (plus its own settings and a few package caches), so start it from a project directory -- can't read your SSH keys, password stores, browser profiles, cloud and Git credentials, or the other agents' logins +- can't read your SSH keys, password stores, browser profiles, Flatpak apps' data (browsers, Signal, Telegram and the rest), your Nextcloud password, cloud and Git credentials, or the other agents' logins - can reach only AI providers and common developer sites: GitHub, Gitea, npm, PyPI, crates.io, RubyGems, the Go module proxy and archlinux.org Typing `opencode`, `hermes` or `hermes-agent` runs it in the sandbox. To run one without it, type `unsandboxed opencode`. Hermes' gateway, the background service that lets you talk to Hermes through Matrix and other messaging apps, runs in the sandbox too, and can reach the Matrix server in Hermes' settings. For other messaging services, add their domains as shown below. Claude Code uses its own built-in sandbox for every command it runs (see `/sandbox` inside Claude). @@ -263,7 +267,7 @@ The sandbox is Anthropic's [sandbox runtime](https://github.com/anthropics/sandb ## mDNS Networking -If you want to use mDNS networking on your LAN (the ability to log in to other local machines using the format "machine.local"), then you should replace /etc/nsswitch.conf with the one in this repository and add /etc/mdns.allow. These two files are formatted to avoid any conflicts with systemd-resolved that may cause nss-mdns not to work. See: https://wiki.archlinux.org/title/Avahi#Hostname_resolution (section 4.2) for more information. +mDNS lets you reach other machines on your LAN as "machine.local", e.g. `ssh machine.local`. When systemd-resolved is enabled, the installer sets it up with [fixmdns.sh](fixmdns.sh): it turns on Avahi and adds nss-mdns to /etc/nsswitch.conf ahead of systemd-resolved, so the two don't conflict. On a machine without systemd-resolved, run `bash ~/.local/share/coredesktop/fixmdns.sh` yourself. See the [Arch wiki](https://wiki.archlinux.org/title/Avahi#Hostname_resolution) for more. ## Contributing diff --git a/install-flatpaks.sh b/install-flatpaks.sh index 7150a48..1876a46 100755 --- a/install-flatpaks.sh +++ b/install-flatpaks.sh @@ -40,7 +40,6 @@ FLATPAKS=( "com.github.xournalpp.xournalpp" "org.libretro.RetroArch" "io.github.anil_e.Codd" - "org.gnome.DejaDup" "com.rustdesk.RustDesk" "io.github.tanaybhomia.Whisp" "org.pipewire.Helvum" diff --git a/install.sh b/install.sh index 5a188d3..deb6420 100755 --- a/install.sh +++ b/install.sh @@ -24,13 +24,13 @@ cd # Exit on any error set -e -# Ask for sudo password upfront so subsequent sudo calls don't prompt mid-install +# Ask for the password once, then keep sudo's cached credentials fresh until +# the install exits, so long builds don't stop for a password again. Unlike a +# passwordless sudoers entry, nothing is left behind if the install is killed. sudo -v - -# Grant passwordless sudo for the duration of the install, revoke on exit -echo "$USER ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/99-hampack-install > /dev/null -sudo chmod 440 /etc/sudoers.d/99-hampack-install -trap "sudo rm -f /etc/sudoers.d/99-hampack-install" EXIT +while kill -0 $$ 2> /dev/null; do sudo -n -v; sleep 60; done 2> /dev/null & +SUDO_KEEPALIVE_PID=$! +trap 'kill "$SUDO_KEEPALIVE_PID" 2> /dev/null' EXIT # Ensure git is available before attempting to clone anything if ! command -v git &> /dev/null; then @@ -45,7 +45,7 @@ echo "Getting the latest version of CoreDesktop..." if [ -d "$HOME/.local/share/coredesktop/.git" ]; then git -C ~/.local/share/coredesktop pull else - git clone https://gitea.federated.computer/david/coredesktop.git ~/.local/share/coredesktop + git clone https://gitea.federated.computer/Federated_Computer/coredesktop.git ~/.local/share/coredesktop fi cd ~/.local/share/coredesktop @@ -155,11 +155,6 @@ bash claude.sh echo "Setting up sandboxed AI agents..." bash ~/.local/share/coredesktop/sandbox/setup.sh -# Install Migrate Backup System -curl -L -o migrate https://github.com/CyphrRiot/Migrate/raw/main/bin/migrate -chmod +x migrate -mv migrate ~/.local/bin/ - # Configure Bitwarden SSH agent echo "Configuring Bitwarden SSH agent..." . bitwarden.sh @@ -216,12 +211,27 @@ fi echo "Running migrations..." run_migrations -# Check whether the running kernel matches the installed modules — if not, a -# newer kernel was installed during this run and a reboot is required -if ! ls /usr/lib/modules/$(uname -r) > /dev/null 2>&1; then - echo "A newer kernel has been installed. Please reboot when convenient." -else - echo "Kernel is up to date, no reboot needed. You may want to consider a reboot if other significant software was updated or installed." -fi +CONFIGURE_HINT="configure connects to your Federated Computer Core, sets up backups and signs you in to the AI agents." -echo "To connect to your Federated Computer Core and sign in to the AI agents, run: configure" +# If the running kernel's modules are gone, a newer kernel was installed during +# this run. configure waits for the reboot: until then, modules it needs, such +# as Tailscale's tun and davfs2's fuse, can't be loaded. +if [ ! -d "/usr/lib/modules/$(uname -r)" ]; then + echo "A newer kernel has been installed. Reboot, then run: configure" + echo "$CONFIGURE_HINT" + exit 0 +fi +echo "Kernel is up to date, no reboot needed. You may want to consider a reboot if other significant software was updated or installed." + +# Offer configure only if something is still to do, as refresh runs this too. +# This script is usually piped into bash, so ask on the terminal, not stdin. +if ~/.local/bin/configure --list | grep -q '^to do'; then + echo + echo "$CONFIGURE_HINT" + if { : < /dev/tty; } 2> /dev/null && read -rp "Run configure now? [Y/n] " answer < /dev/tty \ + && [[ "$answer" != [nN]* ]]; then + ~/.local/bin/configure < /dev/tty || true + else + echo "To do it later, run: configure" + fi +fi diff --git a/migrations/1793103962.sh b/migrations/1793103962.sh new file mode 100644 index 0000000..9584344 --- /dev/null +++ b/migrations/1793103962.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# The installer used to allow sudo without a password while it ran, through a +# file it removed on exit. An install that was killed left it behind. +sudo rm -f /etc/sudoers.d/99-hampack-install || exit 1 + +# Migrate is no longer installed or updated; backups are `configure backup` +rm -f "$HOME/.local/bin/migrate" diff --git a/remove-packages.conf b/remove-packages.conf index fdf7858..c9ba896 100644 --- a/remove-packages.conf +++ b/remove-packages.conf @@ -17,4 +17,5 @@ REMOVE_FLATPAKS=( org.videolan.VLC org.libreoffice.LibreOffice com.bitwarden.desktop + org.gnome.DejaDup ) diff --git a/sandbox/config/base.json b/sandbox/config/base.json index 53f33e9..468208b 100644 --- a/sandbox/config/base.json +++ b/sandbox/config/base.json @@ -61,6 +61,8 @@ "~/.config/google-chrome", "~/.config/BraveSoftware", "~/.config/net.imput.helium", + "~/.var/app", + "~/.davfs2", "~/.claude", "~/.claude.json", "~/.hermes", diff --git a/skills/sibling-project-updates.md b/skills/sibling-project-updates.md index 38d1b19..7970e68 100644 --- a/skills/sibling-project-updates.md +++ b/skills/sibling-project-updates.md @@ -71,7 +71,6 @@ Existing coredesktop hooks use a numeric prefix to control execution order: | `46-neovim.sh` | Neovim plugins | | `50-bitwarden.sh` | Bitwarden SSH agent | | `60-pipx.sh` | pipx packages | -| `65-migrate.sh` | Migrate backup tool | | `70-claude.sh` | Claude Code setup | | `71-siblings.sh` | Projects installed with `sibling` | | `80-gnome-extensions.sh` | GNOME extensions | diff --git a/updates.d/10-pacman.sh b/updates.d/10-pacman.sh index 2a2a73f..ad87e09 100644 --- a/updates.d/10-pacman.sh +++ b/updates.d/10-pacman.sh @@ -30,11 +30,11 @@ if initramfs_build_failed; then fi echo "Checking for new packages..." -install_packages "${SYSTEM_UTILS[@]}" -install_packages "${DEV_TOOLS[@]}" -install_packages "${MAINTENANCE[@]}" -install_packages "${DESKTOP[@]}" -install_packages "${MEDIA[@]}" -install_packages "${FONTS[@]}" +install_packages "${SYSTEM_UTILS[@]}" || STATUS=1 +install_packages "${DEV_TOOLS[@]}" || STATUS=1 +install_packages "${MAINTENANCE[@]}" || STATUS=1 +install_packages "${DESKTOP[@]}" || STATUS=1 +install_packages "${MEDIA[@]}" || STATUS=1 +install_packages "${FONTS[@]}" || STATUS=1 exit $STATUS diff --git a/updates.d/60-pipx.sh b/updates.d/60-pipx.sh index 0ba9fe2..1a7a468 100644 --- a/updates.d/60-pipx.sh +++ b/updates.d/60-pipx.sh @@ -11,20 +11,26 @@ echo "Checking for new pipx applications..." install_pipx_apps "${PIPX[@]}" || STATUS=1 # pipx venvs are tied to the Python they were built with, so a Python upgrade -# breaks them in a way `pipx upgrade-all` can't repair. Rebuild them when the -# Python version changes, or when an upgrade fails. +# breaks them in a way `pipx upgrade` can't repair. Rebuild them all when the +# Python version changes; otherwise upgrade the apps CoreDesktop installs (gext +# comes from ensure_gext), rebuilding one if its upgrade fails. Apps you +# installed yourself are left to you, so one of them can't fail the update. STAMP="$HOME/.local/state/coredesktop/pipx-python-version" CURRENT_PYTHON="$(python3 -c 'import sys; print("%d.%d" % sys.version_info[:2])')" if [ "$(cat "$STAMP" 2>/dev/null)" != "$CURRENT_PYTHON" ]; then echo "Python changed to $CURRENT_PYTHON, reinstalling pipx applications..." - pipx reinstall-all + pipx reinstall-all && mkdir -p "$(dirname "$STAMP")" && echo "$CURRENT_PYTHON" > "$STAMP" || STATUS=1 else echo "Updating pipx applications..." - if ! pipx upgrade-all; then - echo "pipx upgrade-all failed, reinstalling pipx applications..." - pipx reinstall-all - fi -fi && mkdir -p "$(dirname "$STAMP")" && echo "$CURRENT_PYTHON" > "$STAMP" || STATUS=1 + installed="$(pipx list --short 2> /dev/null | cut -d' ' -f1)" + for app in "${PIPX[@]}" gnome-extensions-cli; do + grep -qx "$app" <<< "$installed" || continue + if ! pipx upgrade "$app"; then + echo "Upgrading $app failed, reinstalling it..." + pipx reinstall "$app" || STATUS=1 + fi + done +fi exit $STATUS diff --git a/utils.sh b/utils.sh index a834a66..ac9115d 100755 --- a/utils.sh +++ b/utils.sh @@ -15,12 +15,21 @@ install_packages() { local packages=("$@") local to_install=() + local as_deps=() + for pkg in "${packages[@]}"; do if ! is_installed "$pkg" && ! is_group_installed "$pkg"; then to_install+=("$pkg") fi done + # A package first installed as another one's dependency becomes an orphan + # when that one is removed, and updates.d/95-cleanup.sh removes orphans + mapfile -t as_deps < <(pacman -Qdq "${packages[@]}" 2> /dev/null) + if [ ${#as_deps[@]} -ne 0 ]; then + sudo pacman -D --asexplicit "${as_deps[@]}" > /dev/null + fi + if [ ${#to_install[@]} -ne 0 ]; then echo "Installing: ${to_install[*]}" yay -S --noconfirm --answerdiff=None --answeredit=None --answerclean=None "${to_install[@]}"