Compare commits
19
Commits
8575c4ffa3
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c353e7287 | ||
|
|
9ad957f4a0 | ||
|
|
2c288e1aec | ||
|
|
da076af6ad | ||
|
|
9a9f6d9931 | ||
|
|
923da6d375 | ||
|
|
f86e424491 | ||
|
|
a8b4e3f51d | ||
|
|
226b439684 | ||
|
|
68e30e9feb | ||
|
|
5b33bd26f9 | ||
|
|
7a8693de8a | ||
|
|
df9cf52acf | ||
|
|
4f2c3e937b | ||
|
|
56c924d0a6 | ||
|
|
1994f7b030 | ||
|
|
56742247ce | ||
|
|
64bb53eadf | ||
|
|
598e8b52c8 |
Regular → Executable
+53
-31
@@ -74,54 +74,76 @@ install_pacman "${PACMAN_COMMON[@]}" \
|
|||||||
echo ">> Bootloader (GRUB)..."
|
echo ">> Bootloader (GRUB)..."
|
||||||
install_bootloader
|
install_bootloader
|
||||||
|
|
||||||
echo ">> Configurando rollback de actualizaciones (snapper)..."
|
|
||||||
configure_btrfs_rollback
|
|
||||||
|
|
||||||
echo ">> Bootstrapeando paru y paquetes AUR..."
|
echo ">> Bootstrapeando paru y paquetes AUR..."
|
||||||
bootstrap_paru
|
bootstrap_paru
|
||||||
# Solo plasmoides que EXISTEN en AUR. Los de KDE Store/GitHub (gnome-pager, kMenu,
|
# Solo plasmoides que EXISTEN en AUR. Los de KDE Store/GitHub (gnome-pager, kMenu,
|
||||||
# kvitals, windowtitlereborn, claudeusageswitcher, tt.launchpadPlasma) NO están en
|
# kvitals, windowtitlereborn, commandoutput, codexbar) NO están en AUR: viajan
|
||||||
# AUR: viajan como dotfiles vía chezmoi (~/.local/share/plasma/plasmoids), capturados
|
# como dotfiles vía chezmoi (~/.local/share/plasma/plasmoids), capturados con
|
||||||
# con shared/capture-kde.sh. No los añadas aquí.
|
# shared/capture-kde.sh. No los añadas aquí. (claudeusageswitcher y
|
||||||
|
# tt.launchpadPlasma viajaron así hasta que se quitaron por no usarse en
|
||||||
|
# ningún panel real -- auditoría 2026-09-20.)
|
||||||
install_aur "${AUR_COMMON[@]}" \
|
install_aur "${AUR_COMMON[@]}" \
|
||||||
plasma6-applets-panel-colorizer kwin-effects-better-blur-dx kwin-effects-glass-git breeze-enhanced \
|
kwin-effects-glass-git tela-icon-theme \
|
||||||
plasma6-themes-layan-git tela-icon-theme layan-cursor-theme-git \
|
|
||||||
plasma6-applets-appgrid plasma6-wallpapers-smart-video-wallpaper-reborn pamac-tray-plasma-git \
|
plasma6-applets-appgrid plasma6-wallpapers-smart-video-wallpaper-reborn pamac-tray-plasma-git \
|
||||||
yin-yang kwin-decoration-sierra-breeze-enhanced-git
|
yin-yang kwin-decoration-sierra-breeze-enhanced-git
|
||||||
install_helpwire
|
run_optional "install_helpwire" install_helpwire
|
||||||
install_claude_code
|
run_optional "install_claude_code" install_claude_code
|
||||||
|
|
||||||
echo ">> Instalando Flatpaks comunes..."
|
run_optional "install_flatpaks" install_flatpaks "${FLATPAK_COMMON[@]}"
|
||||||
install_flatpaks "${FLATPAK_COMMON[@]}"
|
|
||||||
|
|
||||||
echo ">> Servicios..."
|
enable_services() {
|
||||||
systemctl enable sddm
|
systemctl enable sddm
|
||||||
systemctl enable NetworkManager
|
systemctl enable NetworkManager
|
||||||
systemctl enable bluetooth
|
systemctl enable bluetooth
|
||||||
systemctl enable "syncthing@$INSTALL_USER.service"
|
systemctl enable "syncthing@$INSTALL_USER.service"
|
||||||
systemctl enable tailscaled
|
systemctl enable tailscaled
|
||||||
systemctl enable power-profiles-daemon
|
systemctl enable power-profiles-daemon
|
||||||
systemctl enable cpupower
|
systemctl enable cpupower
|
||||||
|
}
|
||||||
|
run_optional "enable_services" enable_services
|
||||||
|
|
||||||
# Tema: Layan (global theme) + iconos Tela + cursores Bibata-Modern-Classic
|
# Tema: look-and-feel propios Vampire-Light/Vampire-dark (ver PROJECT_CONTEXT.md)
|
||||||
# (bibata-cursor-theme-bin en AUR_COMMON), vía AUR (plasma6-themes-layan-git/
|
# + iconos Tela (tela-icon-theme de arriba) + cursores Bibata-Modern-Classic
|
||||||
# tela-icon-theme/layan-cursor-theme-git de arriba, instalan en /usr/share, sin
|
# (bibata-cursor-theme-bin en AUR_COMMON), vía AUR, instalan en /usr/share, sin
|
||||||
# copiar binarios en dotfiles; layan-cursor-theme-git se deja instalado como
|
# copiar binarios en dotfiles. El resto de la personalización (rc files,
|
||||||
# alternativa aunque el cursor activo sea Bibata). El resto de la
|
# layout de paneles, splash Animated-Abstract-Cube, los propios paquetes
|
||||||
# personalización (rc files, layout de paneles, splash Animated-Abstract-Cube)
|
# look-and-feel Vampire-*) se captura del portátil con shared/capture-kde.sh
|
||||||
# se captura del portátil con shared/capture-kde.sh y se replica vía chezmoi.
|
# y se replica vía chezmoi. Single-monitor como base.
|
||||||
# Single-monitor como base.
|
|
||||||
|
|
||||||
# --- chezmoi: dotfiles personales (repo arch-configs) --------------------------
|
# --- chezmoi: dotfiles personales (repo arch-configs) --------------------------
|
||||||
# chezmoi ya se instaló arriba (PACMAN_COMMON, repos oficiales desde 2.x).
|
# chezmoi ya se instaló arriba (PACMAN_COMMON, repos oficiales desde 2.x).
|
||||||
echo ">> chezmoi init --apply (repo arch-configs)..."
|
echo ">> chezmoi init --apply (repo arch-configs)..."
|
||||||
REMOTE="$GITEA/arch-configs.git"
|
REMOTE="$GITEA/arch-configs.git"
|
||||||
[[ -n "${GITEA_TOKEN:-}" ]] && REMOTE="https://$INSTALL_USER:$GITEA_TOKEN@gitea.josevi.ovh/josevi/arch-configs.git"
|
[[ -n "${GITEA_TOKEN:-}" ]] && REMOTE="https://$INSTALL_USER:$GITEA_TOKEN@gitea.josevi.ovh/josevi/arch-configs.git"
|
||||||
as_user "export GIT_NAME='$GIT_NAME' GIT_EMAIL='$GIT_EMAIL'; \
|
chezmoi_init_apply() {
|
||||||
chezmoi init --apply '$REMOTE'"
|
as_user "export GIT_NAME='$GIT_NAME' GIT_EMAIL='$GIT_EMAIL'; \
|
||||||
|
chezmoi init --apply '$REMOTE'"
|
||||||
|
}
|
||||||
|
run_optional "chezmoi init --apply" chezmoi_init_apply
|
||||||
|
|
||||||
# --- pkgsync: sincronización de paquetes (repo arch-setup) -----------------
|
# --- pkgsync: sincronización de paquetes (repo arch-setup) -----------------
|
||||||
install_pkgsync
|
run_optional "install_pkgsync" install_pkgsync
|
||||||
|
|
||||||
|
# Snapper AL FINAL, no tras install_bootloader: snap-pac crea un snapshot
|
||||||
|
# pre+post por cada transacción de pacman/paru en cuanto existe el config de
|
||||||
|
# snapper, y dentro del chroot no hay systemd corriendo para que el timer de
|
||||||
|
# cleanup limite NUMBER_LIMIT -- ninguna limpieza puede correr hasta el primer
|
||||||
|
# arranque real. Con snapper configurado antes de las ~30 instalaciones AUR
|
||||||
|
# (cada una su propia transacción), se acumulan decenas de snapshots sin poda
|
||||||
|
# posible; en una VM de prueba con disco pequeño esto llenó el disco entero
|
||||||
|
# (visto en real). Configurándolo al final, ya con el sistema instalado, no se
|
||||||
|
# snapshotea la propia instalación -- el primer snapshot legítimo será el de
|
||||||
|
# un 'pacman -Syu' real ya con el sistema arrancado, que es para lo que existe
|
||||||
|
# el rollback.
|
||||||
|
echo ">> Configurando rollback de actualizaciones (snapper)..."
|
||||||
|
run_optional "configure_btrfs_rollback" configure_btrfs_rollback
|
||||||
|
|
||||||
rm -f /etc/sudoers.d/99-setup-nopasswd
|
rm -f /etc/sudoers.d/99-setup-nopasswd
|
||||||
|
|
||||||
|
if ((${#FAILED_STEPS[@]})); then
|
||||||
|
echo
|
||||||
|
echo "⚠️ Instalación completada con avisos. Pasos que fallaron y necesitan revisión manual:"
|
||||||
|
printf ' - %s\n' "${FAILED_STEPS[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
echo ">> Configuración de KDE completada."
|
echo ">> Configuración de KDE completada."
|
||||||
|
|||||||
+89
-7
@@ -23,6 +23,18 @@ METAPAC_CONFIG_DIR="$HOME/.config/metapac"
|
|||||||
METAPAC_GROUP="$METAPAC_CONFIG_DIR/groups/arch-setup.toml"
|
METAPAC_GROUP="$METAPAC_CONFIG_DIR/groups/arch-setup.toml"
|
||||||
OVERRIDES_FILE="$METAPAC_CONFIG_DIR/groups/overrides.local.toml"
|
OVERRIDES_FILE="$METAPAC_CONFIG_DIR/groups/overrides.local.toml"
|
||||||
|
|
||||||
|
# Marca que un push falló. pull la revisa al arrancar (con la sesión gráfica
|
||||||
|
# ya arriba) para avisar aunque el notify-send del propio push, disparado
|
||||||
|
# durante el apagado con la sesión cayéndose, no llegara a mostrarse. Se
|
||||||
|
# borra en el primer push que vuelve a tener éxito.
|
||||||
|
FAIL_MARKER="$HOME/.local/share/pkgsync.failed"
|
||||||
|
|
||||||
|
# Token de Gotify (push.josevi.ovh, mismo servidor que usa WUD) para avisos
|
||||||
|
# de fallo -- llega también sin sesión gráfica, a diferencia de notify-send.
|
||||||
|
# Fichero local-only, nunca tracked (ni chezmoi ni el repo arch-setup):
|
||||||
|
# mismo criterio que OVERRIDES_FILE. Si no existe, se omite sin más.
|
||||||
|
GOTIFY_ENV="$HOME/.config/pkgsync/gotify.env"
|
||||||
|
|
||||||
# flatpak sin --user/--system instala en "system" con la config actual de
|
# flatpak sin --user/--system instala en "system" con la config actual de
|
||||||
# install_flatpaks() en packages-common.sh. Si tu máquina usa --user, cambia
|
# install_flatpaks() en packages-common.sh. Si tu máquina usa --user, cambia
|
||||||
# esto (o verifica con: flatpak list --columns=installation,application).
|
# esto (o verifica con: flatpak list --columns=installation,application).
|
||||||
@@ -219,6 +231,34 @@ notify() {
|
|||||||
command -v notify-send &>/dev/null && timeout 5 notify-send --app-name=pkgsync "$1" "$2"
|
command -v notify-send &>/dev/null && timeout 5 notify-send --app-name=pkgsync "$1" "$2"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Como notify(), pero urgencia "critical" (se queda en pantalla hasta que se
|
||||||
|
# cierra a mano) y además deja constancia en $FAIL_MARKER: push corre en
|
||||||
|
# ExecStop durante el apagado, con la sesión/D-Bus ya cayéndose, así que su
|
||||||
|
# notify-send puede no llegar a mostrarse -- el marcador es la red de
|
||||||
|
# seguridad que garantiza el aviso en el siguiente pull, ya con la sesión
|
||||||
|
# gráfica completa.
|
||||||
|
notify_fail() {
|
||||||
|
echo "!! $1: $2" >&2
|
||||||
|
printf '%s -- %s: %s\n' "$(date -Iseconds)" "$1" "$2" >"$FAIL_MARKER"
|
||||||
|
command -v notify-send &>/dev/null && timeout 5 notify-send --app-name=pkgsync --urgency=critical "$1" "$2"
|
||||||
|
notify_gotify "$1" "$2"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Best-effort, nunca bloquea ni hace fallar el caller: mismo espíritu que el
|
||||||
|
# timeout de notify-send de arriba, pero via HTTPS -- llega aunque D-Bus/la
|
||||||
|
# sesión gráfica ya esté cayéndose (caso ExecStop en apagado) o no haya
|
||||||
|
# sesión gráfica en absoluto.
|
||||||
|
notify_gotify() {
|
||||||
|
[[ -f "$GOTIFY_ENV" ]] || return 0
|
||||||
|
local GOTIFY_URL GOTIFY_TOKEN
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$GOTIFY_ENV"
|
||||||
|
[[ -n "${GOTIFY_URL:-}" && -n "${GOTIFY_TOKEN:-}" ]] || return 0
|
||||||
|
timeout 10 curl -fsS --max-time 8 \
|
||||||
|
-F "title=$1" -F "message=$2" -F "priority=8" \
|
||||||
|
"${GOTIFY_URL%/}/message?token=${GOTIFY_TOKEN}" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
# --- subcomandos --------------------------------------------------------------
|
# --- subcomandos --------------------------------------------------------------
|
||||||
cmd_bootstrap() {
|
cmd_bootstrap() {
|
||||||
echo ">> pkgsync bootstrap"
|
echo ">> pkgsync bootstrap"
|
||||||
@@ -266,6 +306,19 @@ EOF
|
|||||||
echo ">> scaffold de $OVERRIDES_FILE creado (vacío, edítalo a mano)"
|
echo ">> scaffold de $OVERRIDES_FILE creado (vacío, edítalo a mano)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "$GOTIFY_ENV" ]]; then
|
||||||
|
mkdir -p "$(dirname "$GOTIFY_ENV")"
|
||||||
|
cat >"$GOTIFY_ENV" <<'EOF'
|
||||||
|
# Token de aplicación Gotify para los avisos de fallo de pkgsync (push.josevi.ovh).
|
||||||
|
# Crea una Application nueva en la UI de Gotify y pega su token aquí.
|
||||||
|
# Fichero local-only: pkgsync nunca lo lee/escribe salvo aquí, no viaja al repo.
|
||||||
|
#GOTIFY_URL="https://push.josevi.ovh"
|
||||||
|
#GOTIFY_TOKEN="pon-aqui-el-token"
|
||||||
|
EOF
|
||||||
|
chmod 600 "$GOTIFY_ENV"
|
||||||
|
echo ">> scaffold de $GOTIFY_ENV creado (comentado, edítalo a mano para activar avisos por Gotify)"
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ ! -d "$REPO_DIR/.git" ]]; then
|
if [[ ! -d "$REPO_DIR/.git" ]]; then
|
||||||
echo ">> clonando arch-setup en $REPO_DIR..."
|
echo ">> clonando arch-setup en $REPO_DIR..."
|
||||||
git clone "$REPO_URL" "$REPO_DIR"
|
git clone "$REPO_URL" "$REPO_DIR"
|
||||||
@@ -282,7 +335,7 @@ cmd_push() {
|
|||||||
echo "=== push $(date -Iseconds) ==="
|
echo "=== push $(date -Iseconds) ==="
|
||||||
|
|
||||||
if [[ ! -d "$REPO_DIR/.git" ]]; then
|
if [[ ! -d "$REPO_DIR/.git" ]]; then
|
||||||
echo "!! no existe $REPO_DIR, corre 'pkgsync bootstrap' primero"
|
notify_fail "pkgsync: push falló" "no existe el clon $REPO_DIR, corre 'pkgsync bootstrap'"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -314,25 +367,40 @@ cmd_push() {
|
|||||||
add_flatpak="$(comm -23 "$work/inst_flatpak" "$work/decl_flatpak" | comm -23 - "$work/overrides")"
|
add_flatpak="$(comm -23 "$work/inst_flatpak" "$work/decl_flatpak" | comm -23 - "$work/overrides")"
|
||||||
|
|
||||||
local pc="$REPO_DIR/shared/packages-common.sh"
|
local pc="$REPO_DIR/shared/packages-common.sh"
|
||||||
patch_array_file "$pc" PACMAN_COMMON "$remove_pacman" "$add_pacman"
|
local patch_failed=0
|
||||||
patch_array_file "$pc" AUR_COMMON "$remove_aur" "$add_aur"
|
patch_array_file "$pc" PACMAN_COMMON "$remove_pacman" "$add_pacman" || patch_failed=1
|
||||||
patch_array_file "$pc" FLATPAK_COMMON "$remove_flatpak" "$add_flatpak"
|
patch_array_file "$pc" AUR_COMMON "$remove_aur" "$add_aur" || patch_failed=1
|
||||||
|
patch_array_file "$pc" FLATPAK_COMMON "$remove_flatpak" "$add_flatpak" || patch_failed=1
|
||||||
|
|
||||||
rm -rf "$work"
|
rm -rf "$work"
|
||||||
|
|
||||||
|
# No commitear nunca un parcheo a medias/fallido -- así fue como el fichero
|
||||||
|
# acabó vacío en origin/main una vez (2026-08-27): el parcheo falló pero el
|
||||||
|
# script siguió y commiteó igualmente lo que hubiera en disco. El fichero
|
||||||
|
# de trabajo no se toca cuando patch_array_file falla (solo escribe si
|
||||||
|
# encuentra el array), así que abortar aquí es seguro: el próximo intento
|
||||||
|
# vuelve a partir del mismo estado.
|
||||||
|
if (( patch_failed )); then
|
||||||
|
notify_fail "pkgsync: push falló" "no se pudo parchear packages-common.sh (arrays no encontrados), reviso sin commitear -- $LOG"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
write_group_file
|
write_group_file
|
||||||
|
|
||||||
cd "$REPO_DIR" || return 0
|
cd "$REPO_DIR" || return 0
|
||||||
git add shared/packages-common.sh
|
git add shared/packages-common.sh
|
||||||
if git diff --cached --quiet; then
|
if git diff --cached --quiet; then
|
||||||
echo "sin cambios de paquetes que subir"
|
echo "sin cambios de paquetes que subir"
|
||||||
|
rm -f "$FAIL_MARKER"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
git commit -m "pkgsync: actualiza inventario de paquetes $(date '+%Y-%m-%d %H:%M')"
|
git commit -m "pkgsync: actualiza inventario de paquetes $(date '+%Y-%m-%d %H:%M')"
|
||||||
if timeout 20 git push origin main; then
|
if timeout 20 git push origin main; then
|
||||||
echo "push OK"
|
echo "push OK"
|
||||||
|
rm -f "$FAIL_MARKER"
|
||||||
else
|
else
|
||||||
echo "push falló (¿sin red?), el commit queda en local para el próximo intento"
|
notify_fail "pkgsync: push falló" "commit local OK pero 'git push' falló (¿sin red?); el commit queda en local para el próximo intento"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,17 +409,31 @@ cmd_pull() {
|
|||||||
exec >>"$LOG" 2>&1
|
exec >>"$LOG" 2>&1
|
||||||
echo "=== pull $(date -Iseconds) ==="
|
echo "=== pull $(date -Iseconds) ==="
|
||||||
|
|
||||||
|
# Red de seguridad: si un push anterior falló (típicamente en ExecStop
|
||||||
|
# durante el apagado, con la sesión/D-Bus ya cayéndose y su propio
|
||||||
|
# notify-send sin garantía de mostrarse), avisar aquí sí o sí -- pull corre
|
||||||
|
# al arrancar sesión, con el escritorio ya completo.
|
||||||
|
if [[ -f "$FAIL_MARKER" ]]; then
|
||||||
|
notify_fail "pkgsync: hay un fallo pendiente de revisar" "$(cat "$FAIL_MARKER")"
|
||||||
|
fi
|
||||||
|
|
||||||
if ! timeout 15 git ls-remote --exit-code "$REPO_URL" &>/dev/null; then
|
if ! timeout 15 git ls-remote --exit-code "$REPO_URL" &>/dev/null; then
|
||||||
echo "sin conexión con el remoto, me quedo con el estado local"
|
echo "sin conexión con el remoto, me quedo con el estado local"
|
||||||
elif [[ ! -d "$REPO_DIR/.git" ]]; then
|
elif [[ ! -d "$REPO_DIR/.git" ]]; then
|
||||||
echo "clonando arch-setup en $REPO_DIR..."
|
echo "clonando arch-setup en $REPO_DIR..."
|
||||||
mkdir -p "$(dirname "$REPO_DIR")"
|
mkdir -p "$(dirname "$REPO_DIR")"
|
||||||
timeout 30 git clone "$REPO_URL" "$REPO_DIR" && echo "clon inicial OK" || echo "clone falló"
|
if timeout 30 git clone "$REPO_URL" "$REPO_DIR"; then
|
||||||
|
echo "clon inicial OK"
|
||||||
|
else
|
||||||
|
notify_fail "pkgsync: pull falló" "no se pudo clonar $REPO_URL, revisa $LOG"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
if timeout 30 git -C "$REPO_DIR" pull --ff-only origin main; then
|
if timeout 30 git -C "$REPO_DIR" pull --ff-only origin main; then
|
||||||
echo "git pull OK"
|
echo "git pull OK"
|
||||||
else
|
else
|
||||||
echo "git pull falló (conflicto local o sin red); sigo con el estado que haya"
|
# ls-remote de arriba ya confirmó que hay red -- esto es un conflicto
|
||||||
|
# real (fast-forward imposible), no un simple "sin conexión".
|
||||||
|
notify_fail "pkgsync: pull falló" "'git pull --ff-only' falló (conflicto local, revisa $REPO_DIR a mano); sigo con el estado que haya"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,266 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Paquetes base, sourceados por kde/setup.sh (KDE Plasma es el único DE que
|
||||||
|
# instala este repo -- ver README "Decisiones").
|
||||||
|
# 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 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
|
||||||
|
# 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 (bluedevil) se 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 kde/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 kde/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
|
||||||
|
base
|
||||||
|
podman-compose
|
||||||
|
sudo
|
||||||
|
telegram-desktop
|
||||||
|
nano
|
||||||
|
android-tools
|
||||||
|
lzip
|
||||||
|
waydroid
|
||||||
|
glab
|
||||||
|
opencode
|
||||||
|
sshfs
|
||||||
|
isoimagewriter
|
||||||
|
)
|
||||||
|
|
||||||
|
# --- 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
|
||||||
|
vscodium-bin
|
||||||
|
betterbird-bin
|
||||||
|
onlyoffice-bin
|
||||||
|
ungoogled-chromium-bin
|
||||||
|
ventoy-bin
|
||||||
|
woeusb-ng
|
||||||
|
bibata-cursor-theme-bin
|
||||||
|
pamac-all
|
||||||
|
yay
|
||||||
|
# herramientas adicionales presentes en la máquina maestra
|
||||||
|
autofirma debtap gotify-desktop stably-orca-bin
|
||||||
|
codexbar-cli
|
||||||
|
metapac
|
||||||
|
paru
|
||||||
|
spotifast-bin
|
||||||
|
)
|
||||||
|
|
||||||
|
# --- helpers usados por los setup.sh --------------------------------------
|
||||||
|
|
||||||
|
# Ejecuta un paso NO crítico: si falla, lo registra en FAILED_STEPS y
|
||||||
|
# CONTINÚA en vez de abortar todo el script (set -e no debe tirar una
|
||||||
|
# instalación de 1h por un mirror caído o un D-Bus que falta en el chroot).
|
||||||
|
FAILED_STEPS=()
|
||||||
|
run_optional() {
|
||||||
|
local desc="$1"; shift
|
||||||
|
echo ">> $desc"
|
||||||
|
if ! "$@"; then
|
||||||
|
FAILED_STEPS+=("$desc")
|
||||||
|
echo "!! Falló (no crítico, revisa a mano luego): $desc" >&2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
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 --no-dbus -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 --no-dbus -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
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user