From 27115f8245b11411d88f94ccdc1955348e1829e3 Mon Sep 17 00:00:00 2001 From: David Young Date: Sat, 31 Oct 2026 07:23:08 -0600 Subject: [PATCH] trim down install, tighten sshd --- .gitea/workflows/shellcheck.yml | 22 +++++++++++ .shellcheckrc | 10 +++++ README.md | 67 ++++++++++++++++++++++++++------ bitwarden.sh | 5 ++- configure | 2 +- configure.d/20-backup.sh | 2 +- install-flatpaks.sh | 3 +- install.sh | 6 ++- migrations/1793452584.sh | 18 +++++++++ migrations/1793452585.sh | 17 ++++++++ migrations/1793452586.sh | 32 +++++++++++++++ packages.conf | 8 +--- system/sshd.sh | 33 ++++++++++++++++ update | 2 +- updates.d/20-aur.sh | 10 ++--- updates.d/80-gnome-extensions.sh | 2 +- updates.d/95-cleanup.sh | 18 ++++++--- utils.sh | 2 +- 18 files changed, 220 insertions(+), 39 deletions(-) create mode 100644 .gitea/workflows/shellcheck.yml create mode 100644 .shellcheckrc create mode 100644 migrations/1793452584.sh create mode 100644 migrations/1793452585.sh create mode 100644 migrations/1793452586.sh create mode 100644 system/sshd.sh diff --git a/.gitea/workflows/shellcheck.yml b/.gitea/workflows/shellcheck.yml new file mode 100644 index 0000000..c537e55 --- /dev/null +++ b/.gitea/workflows/shellcheck.yml @@ -0,0 +1,22 @@ +# Check every bash script with shellcheck (settings in .shellcheckrc) +name: shellcheck + +on: [push, pull_request] + +jobs: + shellcheck: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install shellcheck + run: | + SUDO=$(command -v sudo || true) + $SUDO apt-get update -q + $SUDO apt-get install -y -q shellcheck + - name: Run shellcheck + run: | + git ls-files -z | while IFS= read -r -d '' f; do + [ -L "$f" ] && continue + case "$f" in *.sh|*.conf) echo "$f"; continue ;; esac + head -n 1 "$f" | grep -q '^#!.*bash' && echo "$f" + done | xargs -d '\n' shellcheck -S warning diff --git a/.shellcheckrc b/.shellcheckrc new file mode 100644 index 0000000..b9cbf16 --- /dev/null +++ b/.shellcheckrc @@ -0,0 +1,10 @@ +# Settings for shellcheck, run on every push by .gitea/workflows/shellcheck.yml +shell=bash +# Scripts source files by paths built at run time, like $HOME/.local/share/coredesktop/utils.sh +disable=SC1090,SC1091 +# configure.d items set TITLE and DESCRIPTION for configure, which sources them +disable=SC2034 +# Messages that print ~ for the user to read +disable=SC2088 +# mkdir -p -m 700 on a directory whose parents already exist +disable=SC2174 diff --git a/README.md b/README.md index f0b6530..30e6b72 100644 --- a/README.md +++ b/README.md @@ -12,19 +12,26 @@ Additionally, CoreDesktop includes a lot of useful software mostly for work at F These scripts are based on the initial work of [Typecraft](https://www.youtube.com/@typecraft_dev). +## Requirements + +- A 64-bit PC (x86_64) that can run Arch Linux, with an internet connection. +- At least 100 GB for / (the root partition). CoreDesktop installs a lot of software, about 50 GB, and `update` needs at least 10 GB free. +- A fresh Arch Linux install with GNOME (see below). CoreDesktop changes system settings, so it's best not to run it on a machine you've already set up the way you like (see "What CoreDesktop changes on your system"). +- A Federated Computer Core is optional. Without one, everything works except what `configure core` sets up: your Core's apps, files, calendars and email, its Tailscale network, and backups. + ## Installing Arch 1) Download the ISO for Arch from [this link](https://archlinux.org/download/). You may need to scroll down to find the download links. 2) Write the ISO file to a USB stick. 3) Boot from the Arch ISO USB stick. When the ISO has booted, type `archinstall` to get to the simple installer. -(Note: if you're on a laptop and/or don't have a wired internet connection, you'll need to set up the wifi card, etc. Here's [the great article](https://wiki.archlinux.org/title/Network_configuration/Wireless) how to do this. But it really boils down to five steps: at the prompt type "iwctl"; then "device list"; then "station wlan0 scan" where "wlan0" is your wifi device; then "station wlan0 get-networks"; then "station wlan0 connect SSID" where you replace "SSID" with the name of your network.) +(Note: if you're on a laptop and/or don't have a wired internet connection, set up Wi-Fi first. See "A Note About Networking in Arch" below.) 4) You will go through the different options. Mostly choose the defaults. -5) Video cards: IF YOU HAVE AN NVIDIA GPU, CHOOSE THE PROPRIETARY NVIDIA OPTION. Choose the AMD option for AMD cards. Just works better. We've found Arch is very good maintaining compatability with Nvidia and AMD options. -6) When asked what type of system your want, the correct choice is "desktop" and the correct desktop environment is "Gnome". +5) Video cards: IF YOU HAVE AN NVIDIA GPU, CHOOSE THE PROPRIETARY NVIDIA OPTION. Choose the AMD option for AMD cards. Just works better. We've found Arch is very good at maintaining compatibility with Nvidia and AMD options. +6) When asked what type of system you want, the correct choice is "desktop" and the correct desktop environment is "Gnome". 7) For sound, "pipewire" is strongly recommended for the sound system choice during install. This is known to work really well with Jitsi, Element, and the other Federated Core SaaS applications, if you're using those. This may no longer be required in the newest installations of Arch Linux. -8) Reboot the system and log in. You should have a working Arch system at this point but without the Coredesktop configurations. +8) Reboot the system and log in. You should have a working Arch system at this point but without the CoreDesktop configurations. You will likely screw up the installation of Arch the first or second time. Don't despair. Keep trying! The logic of the install will ultimately become clear and, frankly, efficient for you. And, besides, you get to know the base Arch install better and better over time. @@ -32,11 +39,11 @@ You will likely screw up the installation of Arch the first or second time. Don' You'll need a connection to the internet to successfully install Arch. -If you have a wired connection, then your network should "just work" and you can use that to configure your Arch network installation. But if you do not have a wired connection and you have a wifi chip installed in your computer, before installing Arch you'll want to set up the wifi network. You can do that using the too `iwctl`. +If you have a wired connection, then your network should "just work" and you can use that to configure your Arch network installation. But if you do not have a wired connection and you have a wifi chip installed in your computer, before installing Arch you'll want to set up the wifi network. You can do that using the tool `iwctl`. Here's [the great article](https://wiki.archlinux.org/title/Network_configuration/Wireless) on how to do this. Type `iwctl` and that will put you into the utility `iwd`. -To list the wireless adapters type: `device list`. If your wireless device is "wlan0" (for example) you next type: `station wlan0 scan` to put the wireless chip into scan mode then `station wlan0 get-networks` to find the wireless networks available. The join your wireless network with the command `station wlan0 connect SSID` where SSID is the wireless network name. You can test your network with a ping to some server, etc. +To list the wireless adapters type: `device list`. If your wireless device is "wlan0" (for example) you next type: `station wlan0 scan` to put the wireless chip into scan mode then `station wlan0 get-networks` to find the wireless networks available. Then join your wireless network with the command `station wlan0 connect SSID` where SSID is the wireless network name. You can test your network with a ping to some server, etc. When you have the wireless network working (check by doing "ping google.com"), then you can proceed to install Arch. @@ -69,7 +76,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 neovim, tmux, Go, Rust, Docker, Tailscale, Element, LibreOffice, 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. If you'd like other tools, open an issue or send a pull request. Federated Computer's own packages, such as Federated Calendar, come from the `[federated]` repository on Federated Computer's Gitea. CoreDesktop adds it to /etc/pacman.conf and trusts its signing key (fingerprint `6AB7C080D87C74BEE3925A026329376994F18B4E`), so they install and update like any other pacman package. Federated Calendar is installed alongside GNOME Calendar and can invite people to events on your Core's Nextcloud calendars. @@ -81,7 +88,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 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. +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), 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. @@ -97,11 +104,11 @@ Lots of development tools including herdr, neovim, tmux, go, hugo, python, rust, The printing service (cups) is turned on. This may need more work to "just work" with other "coredesktop" machines. -mDNS is installed and enabled so the your can find and SSH to your machine on your LAN using {machinename}.local. +mDNS is installed and enabled so you can find and SSH to your machine on your LAN using {machinename}.local. ### Firewall -The ufw firewall is on. It blocks incoming connections except SSH (22), mDNS (5353/udp), LocalSend (53317) and anything arriving over Tailscale. ufw-docker is installed too, because ports published by Docker containers otherwise get around ufw. To let a container's port through, use `sudo ufw-docker allow {container} {port}`. To open a port for something else, e.g. a dev server you want to reach from another machine, use `sudo ufw allow {port}/tcp`. `sudo ufw status` shows the current rules. +The ufw firewall is on. It blocks incoming connections except SSH (22, keys only: see System defaults), mDNS (5353/udp), LocalSend (53317) and anything arriving over Tailscale. ufw-docker is installed too, because ports published by Docker containers otherwise get around ufw. To let a container's port through, use `sudo ufw-docker allow {container} {port}`. To open a port for something else, e.g. a dev server you want to reach from another machine, use `sudo ufw allow {port}/tcp`. `sudo ufw status` shows the current rules. ### Shell @@ -140,6 +147,25 @@ The installer adds the Vulkan driver for Intel and AMD GPUs. If there's an NVIDI - If memory runs out, systemd-oomd closes the app causing it instead of the whole desktop freezing. - Boot no longer waits for the network. - Commands run over SSH (`ssh {machine} {command}`) can find tools in ~/.local/bin and mise. +- You log in to this machine over SSH with a key, not a password, so nobody on the same network can try to guess your password. Put your public key in ~/.ssh/authorized_keys on this machine (`ssh-copy-id` does this from the other machine). To allow passwords again, delete /etc/ssh/sshd_config.d/10-coredesktop-keys-only.conf and run `sudo systemctl reload sshd`. Machines installed earlier, where someone has logged in over SSH with a password, keep accepting passwords until you run `bash ~/.local/share/coredesktop/system/sshd.sh`. +- ssh uses Bitwarden's SSH agent while Bitwarden is running it (turn it on in Bitwarden's settings), and GNOME's otherwise. A terminal opened before Bitwarden started uses GNOME's; open a new one. + +### What CoreDesktop changes on your system + +Besides installing software, CoreDesktop changes these settings. They're listed so you know what you're running, and so you can undo them (see "Uninstalling"). + +- **/etc/pacman.conf**: adds the `[federated]` repository and trusts its signing key (see Pacman above). +- **SSH**: sshd is on, with key login only (/etc/ssh/sshd_config.d/10-coredesktop-keys-only.conf). The SSH client keepalives are in /etc/ssh/ssh_config.d/20-coredesktop-keepalive.conf. +- **Firewall**: ufw is on, with the rules under Firewall above, and ufw-docker's rules in /etc/ufw/after.rules. +- **Login lockout**: deny and unlock_time in /etc/security/faillock.conf. +- **systemd**: a 10-second stop timeout (/etc/systemd/system.conf.d/ and /etc/systemd/user.conf.d/10-coredesktop-timeout.conf), systemd-oomd for apps (/etc/systemd/user/app.slice.d/10-coredesktop-oomd.conf), and NetworkManager-wait-online is masked. +- **/etc/security/pam_env.conf**: a PATH line, so SSH commands find ~/.local/bin and mise. +- **mDNS**: Avahi is on, nss-mdns is added to /etc/nsswitch.conf, and SSH is advertised in /etc/avahi/services/ssh.service. +- **Services turned on**: Avahi, Bluetooth, CUPS (printing), fwupd, GDM, NetworkManager, sshd, Docker, Tailscale, ufw and systemd-oomd. Your user is added to the docker group. +- **Snapper** (btrfs only): a config for / in /etc/snapper/configs/root. +- **NVIDIA** (only if it installs the driver): /etc/mkinitcpio.conf.d/nvidia.conf and NVIDIA's suspend services. +- **Your home folder**: lines in ~/.bashrc (CoreDesktop's shell setup, ~/.local/bin on PATH, the Bitwarden SSH agent), the commands in ~/.local/bin (update, refresh, sibling, version, configure, audit), GNOME extensions and their settings, Claude Code's ~/.claude/settings.json if you had none, and a user timer that checks for updates. +- **configure** adds more, only for what you set up: your Nextcloud files mount in /etc/fstab, GNOME Online Accounts, passwords in your GNOME keyring, and the backup timer. ## Keep your System Up-to-date @@ -158,7 +184,7 @@ The script pulls the latest CoreDesktop, then runs each step in ~/.local/share/c - 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. Packages CoreDesktop installs are never removed this way. To stop another package you use directly from being removed, run `sudo pacman -D --asexplicit ` +- lists packages that were installed only because something else needed them, and are no longer needed by anything, and asks before removing them. Packages CoreDesktop installs are never on this list. To keep one you use directly off the list, run `sudo pacman -D --asexplicit ` If a step fails, the other steps still run, and the failed ones are listed at the end. @@ -279,10 +305,29 @@ You can stop a service from there, which also keeps it from starting at boot, or 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. +## Uninstalling + +CoreDesktop doesn't have an uninstaller, but you can undo it by hand. If you set up a Core, do this first, while `configure` is still installed, so your app passwords are revoked: `configure backup` (turn backups off), `configure tailscale` (leave the network), then `configure core` and "Remove a Core" for each Core. + +Then remove CoreDesktop's own files: + +``` +systemctl --user disable --now coredesktop-update-check.timer coredesktop-backup.timer +rm -f ~/.config/systemd/user/coredesktop-* +rm -f ~/.local/bin/{update,refresh,sibling,version,configure,audit} +rm -rf ~/.local/share/coredesktop ~/.local/share/siblings ~/.local/state/coredesktop ~/.config/coredesktop +``` + +Delete the CoreDesktop lines from ~/.bashrc, and undo the system settings you don't want from "What CoreDesktop changes on your system". The software stays installed: remove what you don't want with `sudo pacman -Rns ` and `flatpak uninstall `. + ## Contributing This whole "project" is licensed under the MIT License. Want to help make CoreDesktop better? Awesome! We welcome any and all help. Just contribute a PR and we're off to a better CoreDesktop. +Found a bug or have an idea? [Open an issue](https://gitea.federated.computer/Federated_Computer/coredesktop/issues). + +Every push is checked with [shellcheck](https://www.shellcheck.net) (settings in .shellcheckrc). Run `shellcheck` on the scripts you change before sending a PR. + Changes to install.sh only reach new installs. If existing machines need the change too, also add a migration: a script named `migrations/$(date +%s).sh` that `update` runs once on each machine. It may also run on fresh installs, so make it safe to repeat. ## Bonus diff --git a/bitwarden.sh b/bitwarden.sh index 3775584..7434fe5 100644 --- a/bitwarden.sh +++ b/bitwarden.sh @@ -1,6 +1,9 @@ #!/bin/bash -LINE='export SSH_AUTH_SOCK="$HOME/.bitwarden-ssh-agent.sock"' +# Use Bitwarden's SSH agent only while Bitwarden is running it, so ssh and +# ssh-add keep working with GNOME's agent for anyone who doesn't. A shell opened +# before Bitwarden starts uses GNOME's agent; open a new one afterwards. +LINE='if [ -S "$HOME/.bitwarden-ssh-agent.sock" ]; then export SSH_AUTH_SOCK="$HOME/.bitwarden-ssh-agent.sock"; fi' if grep -qF "$LINE" ~/.bashrc; then echo "Bitwarden SSH agent already configured in .bashrc" diff --git a/configure b/configure index 11b2e06..adb3b24 100755 --- a/configure +++ b/configure @@ -96,7 +96,7 @@ load_items() { show_items() { local i mark for i in "${!ITEMS[@]}"; do - if [ "${STATES[$i]}" = done ]; then + if [ "${STATES[$i]}" = "done" ]; then mark="\e[32mdone\e[0m " else mark="\e[33mto do\e[0m" diff --git a/configure.d/20-backup.sh b/configure.d/20-backup.sh index 01716d3..4bbc5f4 100644 --- a/configure.d/20-backup.sh +++ b/configure.d/20-backup.sh @@ -161,7 +161,7 @@ run_configure() { echo "There's already a backup in $BACKUP_DIR in your Nextcloud files." read -rsp "Its passphrase: " pass echo - RESTIC_PASSWORD_COMMAND= RESTIC_PASSWORD="$pass" restic cat config > /dev/null \ + RESTIC_PASSWORD_COMMAND='' RESTIC_PASSWORD="$pass" restic cat config > /dev/null \ || { echo "restic couldn't open it with that passphrase."; return 1; } save_secret passphrase "$WEBDAV/$BACKUP_DIR" "$pass" || return 1 fi diff --git a/install-flatpaks.sh b/install-flatpaks.sh index 1876a46..7a196d1 100755 --- a/install-flatpaks.sh +++ b/install-flatpaks.sh @@ -20,7 +20,6 @@ FLATPAKS=( "com.discordapp.Discord" "com.spotify.Client" "md.obsidian.Obsidian" - "org.qbittorrent.qBittorrent" "org.inkscape.Inkscape" "us.zoom.Zoom" "org.audacityteam.Audacity" @@ -50,7 +49,7 @@ FLATPAKS=( ) for pak in "${FLATPAKS[@]}"; do - if ! flatpak list | grep -i "$pak" &> /dev/null; then + if ! flatpak info "$pak" &> /dev/null; then echo "Installing Flatpak: $pak" sudo flatpak install --system --noninteractive "$pak" else diff --git a/install.sh b/install.sh index 5f2850d..e67c4f1 100755 --- a/install.sh +++ b/install.sh @@ -43,7 +43,7 @@ fi # Update or clone the CoreDesktop repo echo "Getting the latest version of CoreDesktop..." if [ -d "$HOME/.local/share/coredesktop/.git" ]; then - git -C ~/.local/share/coredesktop pull + git -C ~/.local/share/coredesktop pull --ff-only else git clone https://gitea.federated.computer/Federated_Computer/coredesktop.git ~/.local/share/coredesktop fi @@ -189,6 +189,10 @@ fi echo "Applying system defaults..." bash ~/.local/share/coredesktop/system/defaults.sh +# SSH logins with keys only, not passwords +echo "Configuring the SSH server..." +bash ~/.local/share/coredesktop/system/sshd.sh + # Block incoming connections except SSH, mDNS, LocalSend and Tailscale echo "Configuring the firewall..." bash ~/.local/share/coredesktop/system/firewall.sh diff --git a/migrations/1793452584.sh b/migrations/1793452584.sh new file mode 100644 index 0000000..8c35b08 --- /dev/null +++ b/migrations/1793452584.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# The SSH server now accepts keys only (system/sshd.sh). A machine someone has +# logged in to over SSH with a password is left as it is, so nobody loses a +# way in; it's told how to switch instead. +SSHD_CONF=/etc/ssh/sshd_config.d/10-coredesktop-keys-only.conf + +[ -f "$SSHD_CONF" ] && exit 0 + +if sudo journalctl -q --no-pager -u sshd.service \ + | grep -qE 'Accepted (password|keyboard-interactive)'; then + echo "Someone has logged in to this machine over SSH with a password, so SSH still accepts passwords." + echo "To allow keys only, add your public key to ~/.ssh/authorized_keys, then run:" + echo " bash ~/.local/share/coredesktop/system/sshd.sh" + exit 0 +fi + +bash "$HOME/.local/share/coredesktop/system/sshd.sh" diff --git a/migrations/1793452585.sh b/migrations/1793452585.sh new file mode 100644 index 0000000..3cfae12 --- /dev/null +++ b/migrations/1793452585.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# ~/.bashrc pointed SSH_AUTH_SOCK at Bitwarden's SSH agent even when Bitwarden +# wasn't running it, which broke ssh and ssh-add for everyone else. Swap that +# line, where it was, for bitwarden.sh's, which only does so while it is. +OLD='export SSH_AUTH_SOCK="$HOME/.bitwarden-ssh-agent.sock"' +NEW='if [ -S "$HOME/.bitwarden-ssh-agent.sock" ]; then export SSH_AUTH_SOCK="$HOME/.bitwarden-ssh-agent.sock"; fi' + +[ -f ~/.bashrc ] || exit 0 +grep -qxF "$OLD" ~/.bashrc || exit 0 + +tmp="$(mktemp ~/.bashrc.XXXXXX)" || exit 1 +awk -v old="$OLD" -v new="$NEW" '$0 == old { print new; next } { print }' ~/.bashrc > "$tmp" \ + && cat "$tmp" > ~/.bashrc +status=$? +rm -f "$tmp" +exit $status diff --git a/migrations/1793452586.sh b/migrations/1793452586.sh new file mode 100644 index 0000000..f2da40f --- /dev/null +++ b/migrations/1793452586.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +# CoreDesktop no longer installs Sonarr, qBittorrent, or the tools it had two +# of: borg (restic does backups), lsd (eza), screen (tmux) and asdf-vm (mise). +# Remove them once. Install one again yourself and update leaves it alone. +# Their data stays: Sonarr's in /var/lib/sonarr, qBittorrent's in ~/.var/app. +DROPPED=(sonarr-bin borg lsd screen asdf-vm) + +if systemctl is-enabled -q sonarr.service 2> /dev/null || systemctl is-active -q sonarr.service 2> /dev/null; then + echo "Stopping Sonarr..." + sudo systemctl disable --now sonarr.service || exit 1 +fi + +for pkg in "${DROPPED[@]}"; do + # The exact name: pacman -Q also matches a package that only provides it + [ "$(pacman -Qq "$pkg" 2> /dev/null)" = "$pkg" ] || continue + + # Something else still needs it: leave it to go with that, as an orphan + if [ "$(LC_ALL=C pacman -Qi "$pkg" | awk -F' *: *' '/^Required By/ { print $2 }')" != "None" ]; then + sudo pacman -D --asdeps "$pkg" > /dev/null || exit 1 + continue + fi + + echo "Removing $pkg..." + sudo pacman -Rns --noconfirm "$pkg" || exit 1 +done + +if flatpak info --system org.qbittorrent.qBittorrent &> /dev/null; then + echo "Removing qBittorrent..." + sudo flatpak uninstall --system --noninteractive org.qbittorrent.qBittorrent || exit 1 +fi +exit 0 diff --git a/packages.conf b/packages.conf index 2872d9b..db4b1a7 100644 --- a/packages.conf +++ b/packages.conf @@ -5,7 +5,6 @@ SYSTEM_UTILS=( bluez bluez-utils bubblewrap - borg btop cadaver cups @@ -30,7 +29,6 @@ SYSTEM_UTILS=( lazygit libnotify libyaml - lsd lsof man mc @@ -45,7 +43,6 @@ SYSTEM_UTILS=( rclone restic ripgrep - screen sniffnet socat stow @@ -67,7 +64,6 @@ SYSTEM_UTILS=( # Development tools DEV_TOOLS=( - asdf-vm base-devel bat bun @@ -79,7 +75,6 @@ DEV_TOOLS=( docker-compose ghostty git - gnome-video-effects go # The source-built herdr pins an exact zig version that Arch rarely ships herdr-bin @@ -130,7 +125,6 @@ DESKTOP=( helium-browser-bin kitty libreoffice-fresh - sonarr-bin voxtype-bin winboat-bin ) @@ -139,6 +133,7 @@ DESKTOP=( MEDIA=( flameshot gimp + gnome-video-effects imagemagick mpv sox @@ -173,5 +168,4 @@ SERVICES=( # next boot: starting gdm or NetworkManager in the middle of an install would # interrupt it. START_SERVICES=( - sonarr.service ) diff --git a/system/sshd.sh b/system/sshd.sh new file mode 100644 index 0000000..2a26dde --- /dev/null +++ b/system/sshd.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# +# Purpose : Let the SSH server accept keys only, not passwords. sshd is on and +# port 22 is open on the LAN, so with passwords anyone on the same +# network (a café's Wi-Fi, say) could try to guess yours. +# +# To log in to this machine over SSH, add your public key to +# ~/.ssh/authorized_keys on it, e.g. with ssh-copy-id from the other machine +# before running this. To allow passwords again, delete the file this writes +# and run: sudo systemctl reload sshd + +set -e + +CONF=/etc/ssh/sshd_config.d/10-coredesktop-keys-only.conf + +# Arch's sshd_config includes sshd_config.d first, and sshd keeps the first +# value it reads, so this wins over the defaults further down +echo "Allowing SSH logins with keys only..." +sudo install -d -m 755 /etc/ssh/sshd_config.d +sudo tee "$CONF" > /dev/null << 'EOF' +# CoreDesktop: log in over SSH with a key, not a password. +# Delete this file and run "sudo systemctl reload sshd" to allow passwords. +PasswordAuthentication no +KbdInteractiveAuthentication no +PermitRootLogin no +EOF + +# Check the config before reloading, so a mistake can't stop sshd. Reloading +# leaves SSH sessions that are already open as they are. +sudo sshd -t +if systemctl is-active -q sshd.service; then + sudo systemctl reload sshd.service +fi diff --git a/update b/update index b31e3a5..d59f971 100755 --- a/update +++ b/update @@ -34,7 +34,7 @@ print_logo COREDESKTOP="$HOME/.local/share/coredesktop" echo "Updating CoreDesktop..." -if [[ -z "$UPDATE_REEXECED" ]] && ! git -C "$COREDESKTOP" pull; then +if [[ -z "$UPDATE_REEXECED" ]] && ! git -C "$COREDESKTOP" pull --ff-only; then echo "WARNING: could not pull the latest CoreDesktop; running the update hooks already on disk." export UPDATE_PULL_FAILED=1 fi diff --git a/updates.d/20-aur.sh b/updates.d/20-aur.sh index ce2dcfa..2181d5b 100644 --- a/updates.d/20-aur.sh +++ b/updates.d/20-aur.sh @@ -10,14 +10,12 @@ YAY_FLAGS="--noconfirm --answerdiff=None --answeredit=None --answerclean=None" if ! yay --version &>/dev/null; then echo "yay is broken (likely a libalpm bump). Rebuilding yay..." sudo pacman -R --noconfirm yay - cd /tmp + cd /tmp || exit 1 rm -rf yay - git clone https://aur.archlinux.org/yay.git - cd yay + git clone https://aur.archlinux.org/yay.git && cd yay || exit 1 makepkg -si --noconfirm - cd .. - rm -rf yay - cd + cd .. && rm -rf yay + cd || exit 1 fi yay -Sua $YAY_FLAGS diff --git a/updates.d/80-gnome-extensions.sh b/updates.d/80-gnome-extensions.sh index b270fe3..df5042b 100755 --- a/updates.d/80-gnome-extensions.sh +++ b/updates.d/80-gnome-extensions.sh @@ -50,7 +50,7 @@ reinstall_incompatible_extensions() { rm -rf "$backup" else echo "Reinstall of $uuid failed; restoring the previous version." - rm -rf "$ext_root/$uuid" + rm -rf "${ext_root:?}/$uuid" mv "$backup/$uuid" "$ext_root/$uuid" rmdir "$backup" fi diff --git a/updates.d/95-cleanup.sh b/updates.d/95-cleanup.sh index b809608..281f4cf 100755 --- a/updates.d/95-cleanup.sh +++ b/updates.d/95-cleanup.sh @@ -10,13 +10,19 @@ if command -v paccache &>/dev/null; then sudo paccache -ruk0 fi -# Remove packages that were installed as dependencies and are no longer needed -# (packages something lists as an optional dependency are kept). To keep one -# you use directly: sudo pacman -D --asexplicit +# Offer to remove packages that were installed as dependencies and are no +# longer needed (packages something lists as an optional dependency are kept). +# Ask first: one may be something you use directly. Without a terminal to ask +# on, keep them. To keep one for good: sudo pacman -D --asexplicit mapfile -t ORPHANS < <(pacman -Qtdq 2>/dev/null) if (( ${#ORPHANS[@]} > 0 )); then - echo "Removing packages no longer needed by anything:" + echo "These packages were installed for something else, and nothing needs them any more:" printf ' %s\n' "${ORPHANS[@]}" - sudo pacman -Rns --noconfirm "${ORPHANS[@]}" || exit 1 - echo "To get one of these back, reinstall it with: sudo pacman -S " + if { : < /dev/tty; } 2> /dev/null && read -rp "Remove them? [y/N] " answer < /dev/tty \ + && [[ "$answer" == [yY]* ]]; then + sudo pacman -Rns --noconfirm "${ORPHANS[@]}" || exit 1 + echo "To get one of these back, reinstall it with: sudo pacman -S " + else + echo "Kept them. To keep one for good, so you're not asked again: sudo pacman -D --asexplicit " + fi fi diff --git a/utils.sh b/utils.sh index ce42c8e..d7f7961 100755 --- a/utils.sh +++ b/utils.sh @@ -101,7 +101,7 @@ remove_flatpaks() { local to_remove=() for pak in "${flatpaks[@]}"; do - if flatpak list --system | grep -qi "$pak"; then + if flatpak info --system "$pak" &> /dev/null; then to_remove+=("$pak") fi done