#!/usr/bin/env bash # Paquetes comunes a GNOME y KDE. Lo sourcea cada /setup.sh. # AUR-first: lo que está en repos oficiales va por pacman, el resto por paru. # --- Repos oficiales (pacman) --------------------------------------------- # Sincronizado con la instalación real de la máquina maestra. Si un paquete no # está presente aquí, se elimina del instalador. PACMAN_COMMON=( # base / shell / CLI moderno zsh starship fzf ripgrep bat eza btop zoxide fd tldr fastfetch 7zip vim usbutils # dev toolchain (Podman en vez de Docker + capa de compat) git base-devel podman podman-docker buildah nodejs npm python python-pip rustup github-cli # sync de dotfiles (repo arch-configs) -- en repos oficiales desde 2.x chezmoi # apps de escritorio que SÍ están en extra bitwarden dbeaver gimp syncthing remmina freerdp apostrophe guvcview kvirc vlc vlc-plugin-ffmpeg # diccionarios (corrector ortográfico en apps GTK/Qt) hunspell-en_us hunspell-es_es # fuentes / iconos compartidos ttf-jetbrains-mono-nerd ttf-firacode-nerd noto-fonts noto-fonts-emoji papirus-icon-theme # red / utilidades base networkmanager flatpak openssh networkmanager-openvpn openvpn tailscale wpa_supplicant # audio (PipeWire reemplaza a PulseAudio) pipewire pipewire-alsa pipewire-jack pipewire-pulse wireplumber libpulse gst-plugin-pipewire gst-plugins-good gst-plugins-bad gst-libav # bluetooth: stack + daemon comunes. La UI va por DE: GNOME la trae vía # gnome-control-center; KDE la instala explícito en kde/setup.sh. bluez bluez-utils # hardware: mismo par de máquinas físicas (ver PROJECT_CONTEXT.md) amd-ucode sof-firmware btrfs-progs zram-generator cpupower power-profiles-daemon ibus wl-clipboard wmctrl smartmontools # gvfs backend para montar móviles Android por MTP (Dolphin/Nautilus) gvfs-mtp # kernels: último + LTS como fallback ante actualizaciones rotas linux linux-lts linux-lts-headers linux-firmware # rollback de actualizaciones atómicas sobre btrfs. inotify-tools es # dependencia OPCIONAL de grub-btrfs (pacman --needed no la instala sola) # pero grub-btrfsd la necesita para arrancar -- sin ella el daemon muere # con exit code 1 y el menú de GRUB nunca ve los snapshots (visto en real # en Vampire-HM80: paquetes instalados pero grub-btrfsd en 'failed'). snapper snap-pac grub-btrfs inotify-tools # bootloader (antes hardcodeado en cada /setup.sh, install_bootloader() # también los instala explícito -- duplicado inofensivo con --needed, pero # ahora viven aquí para que pkgsync pueda declararlos/protegerlos) grub efibootmgr # drivers gráficos open-source (antes hardcodeados en cada /setup.sh; # mismo hardware físico en ambas máquinas, ver PROJECT_CONTEXT.md) mesa vulkan-icd-loader vulkan-radeon vulkan-intel intel-media-driver # --- pkgsync: nuevos detectados (revisa y reorganiza a mano) --- base podman-compose sudo ) # --- Flatpak --------------------------------------------------------------- # Aplicaciones que en la máquina maestra están instaladas como Flatpak. # Antes algunas de estas vivían en AUR (p.ej. heroic-games-launcher-bin, # karere); ahora se gestionan desde Flathub. FLATPAK_COMMON=( com.heroicgameslauncher.hgl io.github.tobagin.karere org.gnome.gitlab.cheywood.Buffer ) # --- AUR (paru) ------------------------------------------------------------ # helpwire: es un .deb; no hay paquete AUR estable -> se convierte con debtap # (lo gestiona aparte la función install_helpwire de setup.sh). # claude-code: NO va por AUR (se desincroniza del release real); se instala # con el instalador nativo oficial, función install_claude_code() más abajo. AUR_COMMON=( zen-browser-bin visual-studio-code-bin vscodium-bin betterbird-bin onlyoffice-bin spotify ungoogled-chromium-bin ventoy-bin woeusb-ng bibata-cursor-theme-bin googledot-cursor-theme pamac-all yay # herramientas adicionales presentes en la máquina maestra autofirma debtap gotify-desktop openlogi stably-orca-bin # --- pkgsync: nuevos detectados (revisa y reorganiza a mano) --- codexbar-cli metapac paru ) # --- helpers usados por los setup.sh -------------------------------------- install_pacman() { pacman -S --needed --noconfirm "$@"; } # paru se construye como usuario normal (makepkg no corre como root). # RUSTUP_HOME/CARGO_HOME explícitos: bajo el fakeroot de makepkg, HOME pasa a # /root y rustup intenta crear /root/.rustup (permission denied, uid real != root). # rustup respeta RUSTUP_HOME antes que HOME, así que apuntarlo al home del usuario # arregla los paquetes Rust (p.ej. karere). as_user() { sudo -u "$INSTALL_USER" bash -lc \ "export RUSTUP_HOME=\$HOME/.rustup CARGO_HOME=\$HOME/.cargo; $*" } bootstrap_paru() { command -v paru &>/dev/null && return 0 install_pacman git base-devel # rustup sin toolchain por defecto no expone cargo y rompe el build de paru as_user 'rustup default stable' # paru (fuente, no paru-bin): el binario de paru-bin enlaza contra una # libalpm.so concreta y rompe si la del sistema nuevo difiere; compilar de # fuente enlaza contra la libalpm instalada. as_user 'cd /tmp && rm -rf paru && \ git clone https://aur.archlinux.org/paru.git && \ cd paru && makepkg -si --noconfirm' } install_aur() { # Uno a uno: que un PKGBUILD roto (p.ej. karere) no se lleve por delante el # resto del lote ni el chezmoi init posterior. Avisa de los que fallen. local p failed=() for p in "$@"; do as_user "paru -S --needed --noconfirm $p" || failed+=("$p") done ((${#failed[@]})) && echo "!! AUR falló (revisa a mano): ${failed[*]}" >&2 return 0 } # archinstall 4.3 instala el paquete grub pero NO ejecuta grub-install con # nuestro esquema (/boot ext4 separado + ESP): el sistema queda sin bootloader. # Lo hacemos aquí (root, dentro del chroot). Idempotente. install_bootloader() { install_pacman grub efibootmgr grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=GRUB --recheck grub-mkconfig -o /boot/grub/grub.cfg } # HelpWire no tiene AUR: descargar .deb, convertir con debtap, instalar. install_helpwire() { local url="https://www.helpwire.app/downloads/operator/linux/helpwire-operator.deb" install_aur debtap as_user "sudo debtap -u || true" # debtap nombra el paquete por el campo Package del .deb ('helpwire', no # 'helpwire-operator'): convertir en un dir limpio e instalar el único .zst, # sin depender del nombre exacto. as_user "d=\$(mktemp -d) && cd \"\$d\" && curl -fsSL -o hw.deb '$url' && \ yes '' | sudo debtap -Q hw.deb && \ sudo pacman -U --noconfirm \"\$d\"/*.pkg.tar.zst && rm -rf \"\$d\"" # debtap deja el .desktop y el icono dentro de /opt y su scriptlet (roto) no # los registra, así que HelpWire no sale en el menú: lo hacemos a mano. local hw=/opt/HelpWire/Operator/desktop install -Dm644 "$hw/helpwire-operator.desktop" /usr/share/applications/helpwire-operator.desktop install -Dm644 "$hw/helpwire-operator_128.png" /usr/share/icons/hicolor/128x128/apps/helpwire-operator.png } # Claude Code: instalador nativo oficial (no AUR, se autoactualiza). Instala # en ~/.local/share/claude con symlink en ~/.local/bin/claude; no necesita # root ni flags especiales para correr sin interacción. install_claude_code() { as_user "curl -fsSL https://claude.ai/install.sh | bash" } # Instala aplicaciones desde Flathub. Se usa para apps que en la máquina # maestra están como Flatpak, aunque antes estuvieran en AUR. install_flatpaks() { echo ">> Instalando Flatpaks comunes..." if ! command -v flatpak &>/dev/null; then echo "!! flatpak no está disponible; omitiendo Flatpaks." >&2 return 0 fi flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo local app failed=() for app in "$@"; do flatpak install -y --noninteractive flathub "$app" || failed+=("$app") done ((${#failed[@]})) && echo "!! Flatpak falló (revisa a mano): ${failed[*]}" >&2 return 0 } # pkgsync: sincroniza qué paquetes hay instalados (pacman+AUR+flatpak) entre # las dos máquinas, igual que chezmoi sincroniza los dotfiles. Instala metapac # (motor de diff/aplicación), despliega pkgsync.sh y sus dos servicios de # usuario, y deja el group file de metapac listo. Ver pkgsync/ en este repo. install_pkgsync() { echo ">> Instalando pkgsync (metapac + servicios de sincronización de paquetes)..." install_aur metapac as_user "mkdir -p ~/.local/bin ~/.config/systemd/user ~/.config/metapac/groups" as_user "cp '$REPO_DIR/pkgsync/pkgsync.sh' ~/.local/bin/pkgsync.sh && chmod +x ~/.local/bin/pkgsync.sh" as_user "cp '$REPO_DIR/pkgsync/systemd/'*.service ~/.config/systemd/user/" as_user "~/.local/bin/pkgsync.sh bootstrap" as_user "systemctl --user enable pkgsync-push.service pkgsync-pull.service" # ya lo activa el run_once de chezmoi, pero por si este DE se instala algún # día sin chezmoi: idempotente, no hace nada si ya está activo. loginctl enable-linger "$INSTALL_USER" 2>/dev/null || true } # Configura snapper + snap-pac + grub-btrfs para rollback de actualizaciones. # snap-pac crea snapshots automaticos antes/después de cada 'pacman -Syu'. # grub-btrfs añade las entradas de snapshots al menú de GRUB. configure_btrfs_rollback() { echo ">> Configurando rollback btrfs (snapper + snap-pac + grub-btrfs)..." # Asegurar que / es btrfs; si no, no hacemos nada. if ! findmnt -nro FSTYPE / | grep -q btrfs; then echo "!! Advertencia: / no es btrfs; omitiendo configuración de snapper." >&2 return 0 fi # Crear configuración de snapper para / si no existe. if [[ ! -f /etc/snapper/configs/root ]]; then snapper -c root create-config / fi # Solo queremos snapshots automáticos de pacman (snap-pac), no por tiempo. # Esto evita que se acumulen snapshots innecesarios y se coma espacio. # ALLOW_GROUPS=wheel: snapper tiene su propia lista de permitidos aparte de # los permisos de fichero de /.snapshots -- sin esto, "snapper -c root # list" da "Sin permisos" para cualquiera que no sea root, aunque el chmod # de abajo esté bien (visto en real en Vampire-HM80). snapper -c root set-config \ TIMELINE_CREATE=no \ TIMELINE_LIMIT_HOURLY=0 \ TIMELINE_LIMIT_DAILY=0 \ TIMELINE_LIMIT_WEEKLY=0 \ TIMELINE_LIMIT_MONTHLY=0 \ TIMELINE_LIMIT_YEARLY=0 \ NUMBER_LIMIT=10 \ NUMBER_LIMIT_IMPORTANT=10 \ ALLOW_GROUPS=wheel # Permisos del directorio de snapshots en sí (necesario además de # ALLOW_GROUPS de arriba, snapper comprueba las dos cosas). chmod 750 /.snapshots chown :wheel /.snapshots 2>/dev/null || true # Habilitar el daemon que regenera el menú de GRUB cuando cambian los snapshots. systemctl enable grub-btrfsd # Regenerar menú de GRUB con las entradas de snapshots. grub-mkconfig -o /boot/grub/grub.cfg }