#!/bin/bash -i # # Purpose : CoreDesktop installer # Print the logo print_logo() { cat << "EOF" ██ █ ██ ██ ██████ █████ ██ █████ █████ ████ ██ █████ ██ ██ ██ ██ ███ ███████ ██ ██ ██ ██ ██ ████████ ██ ██ ███████ █████ ██████ ██ ██ ██████ ██ ████████ ██ █ ███████ ██ ██ ██ ██████ ███████ ██████ ██ ██████ ██████ ██████ ███████ EOF } # Clear screen and show logo clear print_logo cd # Exit on any error set -e # 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 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 echo "Installing git..." sudo pacman -S git --noconfirm else echo "git is installed." 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 else git clone https://gitea.federated.computer/Federated_Computer/coredesktop.git ~/.local/share/coredesktop fi cd ~/.local/share/coredesktop # Source utility functions (provides install_packages and other helpers) source utils.sh # Install the refresh, update, sibling, version and configure scripts to the user's bin mkdir -p ~/.local/bin install_script ~/.local/share/coredesktop/refresh ~/.local/bin/refresh install_script ~/.local/share/coredesktop/update ~/.local/bin/update install_script ~/.local/share/coredesktop/sibling ~/.local/bin/sibling install_script ~/.local/share/coredesktop/version ~/.local/bin/version install_script ~/.local/share/coredesktop/configure ~/.local/bin/configure # Source the package list (defines SYSTEM_UTILS, DEV_TOOLS, DESKTOP, etc. arrays) if [ ! -f "packages.conf" ]; then echo "Error: packages.conf not found!" exit 1 fi source packages.conf echo "Starting full system setup..." # Bring the system fully up to date before installing anything new echo "Updating system..." sudo pacman -Sy --needed --noconfirm archlinux-keyring sudo pacman -Su --noconfirm cd ~/ # Install yay AUR helper if not present — required for AUR packages installed later if ! command -v yay &> /dev/null; then echo "Installing yay AUR helper..." sudo pacman -S --needed git base-devel --noconfirm if [[ -d "yay" ]]; then echo "yay directory already exists, removing it..." rm -rf yay fi echo "Cloning yay repository..." git clone https://aur.archlinux.org/yay.git cd yay echo "Building yay..." makepkg -si --noconfirm cd .. rm -rf yay else echo "yay is already installed." fi # Install packages grouped by category as defined in packages.conf echo "Installing system utilities..." install_packages "${SYSTEM_UTILS[@]}" echo "Installing development tools..." install_packages "${DEV_TOOLS[@]}" echo "Installing system maintenance tools..." install_packages "${MAINTENANCE[@]}" echo "Installing desktop environment..." install_packages "${DESKTOP[@]}" echo "Installing media packages..." install_packages "${MEDIA[@]}" echo "Installing fonts..." install_packages "${FONTS[@]}" echo "Installing pipx applications..." install_pipx_apps "${PIPX[@]}" # Enable all systemd services listed in SERVICES array, then register the SSH # Avahi service so the machine is discoverable over mDNS echo "Configuring services..." enable_services "${SERVICES[@]}" sudo cp /usr/share/doc/avahi/ssh.service /etc/avahi/services/ cd ~/.local/share/coredesktop # Install GNOME shell extensions via the dedicated script echo "Installing GNOME extensions..." . gnome/gnome-extensions.sh # Install Flatpak apps — some programs run better sandboxed as Flatpaks echo "Installing flatpaks..." . install-flatpaks.sh # Install TPM (Tmux Plugin Manager) and configured plugins echo "Installing tmux plug-in manager..." . install-tpm.sh # Install Mise version manager, then use it to set up Ruby and Rails echo "Installing Mise, Ruby, Rails..." cd ~/.local/share/coredesktop . install-mise-ruby-rails.sh # Install Kickstart Neovim config as the default Neovim configuration echo "Installing Kickstart Neovim..." . install-kickstart-nvim.sh # Install Claude Code and configure desktop notification hooks echo "Installing Claude Code..." bash claude.sh # Run AI agents (opencode, hermes) in a sandbox, and turn on Claude Code's own echo "Setting up sandboxed AI agents..." bash ~/.local/share/coredesktop/sandbox/setup.sh # Configure Bitwarden SSH agent echo "Configuring Bitwarden SSH agent..." . bitwarden.sh # Add the current user to the docker group and start the Docker daemon # Group membership takes effect at next login (newgrp would start an interactive shell) sudo usermod -aG docker $USER sudo systemctl enable docker.service sudo systemctl start docker.service # Enable and start Tailscale daemon if ! systemctl is-enabled tailscaled &> /dev/null; then sudo systemctl enable tailscaled fi if ! systemctl is-active tailscaled &> /dev/null; then sudo systemctl start tailscaled fi # SSH keepalives, login lockout, shutdown timeout, OOM protection, boot, SSH PATH echo "Applying system defaults..." bash ~/.local/share/coredesktop/system/defaults.sh # Block incoming connections except SSH, mDNS, LocalSend and Tailscale echo "Configuring the firewall..." bash ~/.local/share/coredesktop/system/firewall.sh # Snapshot / before each update (btrfs only) echo "Configuring Snapper..." bash ~/.local/share/coredesktop/system/snapper.sh echo "Installing GPU drivers..." bash ~/.local/share/coredesktop/system/vulkan.sh bash ~/.local/share/coredesktop/system/nvidia.sh # Prompt, zoxide, fzf key bindings, aliases and functions echo "Configuring the shell..." bash ~/.local/share/coredesktop/shell/setup.sh # Notify in GNOME when a new version of CoreDesktop is available echo "Configuring update notifications..." bash ~/.local/share/coredesktop/system/update-notify.sh # Apply GNOME dconf settings only if the settings file has changed since last run bash ~/.local/share/coredesktop/gnome/apply-gnome-settings.sh # Fix mDNS configuration if systemd-resolved is managing DNS on this system if systemctl is-enabled systemd-resolved.service &> /dev/null; then echo "systemd-resolved is enabled, applying mDNS fix..." bash ~/.local/share/coredesktop/fixmdns.sh fi # Run one-time migrations not yet recorded on this machine. On a fresh install # they repeat setup done above, which is safe because each one is idempotent. echo "Running migrations..." run_migrations CONFIGURE_HINT="configure connects to your Federated Computer Core, sets up backups and signs you in to the AI agents." # 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