JoseviandClaude Sonnet 5 a8b4e3f51d kde/setup.sh: añade bit ejecutable
git ls-files lo tenía como 100644; ./kde/setup.sh (tal como indica el
README) fallaba con "permission denied" en un clon fresco. Detectado
durante una prueba end-to-end en VM.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 21:06:35 +02:00
2026-08-03 13:43:14 +02:00
2026-09-20 21:06:35 +02:00

arch-setup

Instalación automatizada de Arch Linux para mis dos máquinas (hardware idéntico), en un único comando desde el USB live, sin reiniciar entre la base y la config. Escritorio: KDE Plasma (único, sin GNOME — ver "Decisiones").

arch-setup/
├── kde/      archinstall-config.json + setup.sh   (KDE Plasma, sddm)
├── shared/   packages-common.sh                   (paquetes base)
├── pkgsync/  pkgsync.sh + systemd/                (sync de paquetes entre máquinas)
└── README.md

Procedimiento paso a paso completo en INSTALL.md.

Uso (desde el USB live de Arch, como root)

pacman -Sy --noconfirm git
git clone https://gitea.josevi.ovh/josevi/arch-setup
cd arch-setup
./kde/setup.sh

El script te pide: usuario a crear, token de Gitea (para el repo arch-configs privado), nombre y email de git. Después, sin más intervención:

  1. archinstall --silent con kde/archinstall-config.json → instala base + KDE Plasma en /mnt.
  2. Se copia a sí mismo a /mnt y entra en arch-chroot.
  3. Dentro del chroot: crea el usuario, instala paquetes (pacman + AUR vía paru), aplica el aspecto y ejecuta chezmoi init --apply apuntando a gitea.josevi.ovh/josevi/arch-configs.
  4. Quitas el USB y reboot. El tema se aplica en el primer login gráfico.

Decisiones

  • AUR-first: lo que está en repos oficiales va por pacman; el resto por paru (se bootstrapea solo). Sin Flatpak salvo que lo añadas.
  • Contenedores: Podman + podman-docker (capa de compat), no Docker.
  • Navegador: Zen Browser. También ungoogled-chromium.
  • Aspecto: JetBrains Mono Nerd + tema global Layan + iconos Tela + cursores Layan-white (paquetes AUR, ver kde/setup.sh) + splash Animated-Abstract-Cube; look capturado del portátil con shared/capture-kde.sh y aplicado vía chezmoi.
  • Solo KDE Plasma, sin GNOME: hubo variante GNOME en su día; se retiró porque en el uso real KDE es lo único que se usa. Si algún día hiciera falta recuperarla, está en el historial de git (commit anterior a la retirada).
  • Dotfiles en repo separado, paquetes en este mismo: no es arbitrario. arch-configs (dotfiles, vía chezmoi) es datos personales sin relación con "cómo se instala nada" — cambian solos a su ritmo, generan un historial de commits ruidoso ("Auto-backup HH:MM"), y setup.sh los aplica como último paso, con el sistema ya funcionando; si chezmoi init --apply fallara entero, igualmente tendrías un Arch+KDE arrancable, solo que sin tu toque personal. shared/packages-common.sh en cambio es el instalador, no datos sobre el instalador: kde/setup.sh hace source de ese fichero y pasa sus arrays directamente a install_pacman/install_aur — el array es el input directo de la lógica de instalación, en el mismo repo que arranca todo el proceso. Meterlo en un repo aparte obligaría a setup.sh a clonar un segundo repo a medias de la instalación (dentro del chroot, sin red garantizada) solo para saber qué paquetes meter. La línea divisoria es "cómo se construye el sistema" (este repo, código + su propia lista de paquetes) vs "qué aspecto tiene una vez construido" (arch-configs, datos personales) — pkgsync (sección más abajo) vive aquí porque edita exactamente el mismo array que el instalador consume.

⚠️ Antes de lanzar

  • Se borran los discos FIJOS detectados ("wipe": true). Los discos se autodetectan filtrando por NO removible (RM=0 en lsblk), así el USB instalador (sdb, removible) queda fuera y da igual que el SSD sea nvme0n1 o un SSD PCIe que enumera como sda. Esquema:

    • Disco de sistema (1º; nvme si existe) → ESP 512M (/boot/efi) + /boot ext4 1G + / btrfs (resto)
    • 2º disco fijo (si hay) → ext4 todo el disco en /home (ojo: destruye el disco de datos). Si solo hay 1 disco, /home vive dentro del / btrfs.
    • swap = zram ("swap": true), sin partición de swap
    • bootloader GRUB (coherente con ESP en /boot/efi + /boot separado)

    Verifica con lsblk qué discos quedan como fijos. Para forzar nombres a mano: gen-disk-config.py BASE.json /dev/SISTEMA [/dev/HOME].

  • Esquema de particiones de archinstall cambia entre versiones, y el particionado manual multi-disco es lo más sensible. Si archinstall se queja del disk_config, abre archinstall interactivo, define los discos a mano, usa Save configuration y pega ese bloque disk_config en el JSON.

  • Zona horaria/teclado fijados a Europe/Madrid / us-acentos. Ajusta si hace falta.

Apps que se instalan

Comunes (shared/packages-common.sh): zsh+starship+CLI moderno, git+base-devel, Podman, nodejs/python/rustup, Bitwarden, DBeaver, Obsidian, GIMP, Syncthing, Remmina+FreeRDP, Apostrophe, guvcview, KVIrc, Zen Browser, VSCode, Betterbird, OnlyOffice, Spotify, ungoogled-chromium, Karere, HelpWire (vía .deb→debtap). KDE añade kcalc/ark/spectacle/kdeconnect/kinfocenter (inline en kde/setup.sh, ver "Decisiones").

pkgsync — sincronización de paquetes entre las dos máquinas

Mismo patrón que chezmoi para los dotfiles (chezmoi-boot-sync.service / chezmoi-shutdown-sync.service en el repo arch-configs), pero para qué paquetes hay instalados de verdad (pacman + AUR + flatpak). Fuente de verdad: los arrays PACMAN_COMMON/AUR_COMMON/FLATPAK_COMMON de shared/packages-common.sh. Motor de diff/aplicación: metapac (AUR), con paru como backend para que cubra repos oficiales y AUR en una sola pasada.

pkgsync/
├── pkgsync.sh            CLI: bootstrap/push/pull/diff/apply/log/incoming/audit
└── systemd/
    ├── pkgsync-push.service   captura+sube al cerrar sesión/apagar
    └── pkgsync-pull.service   trae+compara al iniciar sesión (nunca instala/desinstala)

Cómo funciona

  • pkgsync push (dispara pkgsync-push.service al cerrar sesión, mismo truco ExecStop en unidad oneshot RemainAfterExit que usa chezmoi-shutdown-sync.service): captura el inventario real (pacman -Qqen/pacman -Qqem/flatpak list), parchea los tres arrays de packages-common.sh en un clon dedicado (~/.local/share/arch-setup) — añade lo nuevo, quita lo que ya no está instalado — y hace git commit + push best-effort con timeout, igual que chezmoi. El parcheo respeta los comentarios de agrupación existentes: lo nuevo se añade en un bloque marcador al final del array, listo para que lo reorganices a mano cuando quieras.
  • pkgsync pull (dispara pkgsync-pull.service al iniciar sesión): git pull best-effort con timeout (nunca bloquea el login), calcula el diff entre lo declarado y lo instalado, y solo notifica (notificación de escritorio + detalle en ~/.local/share/pkgsync.log). No instala ni desinstala nada por sí solo.
  • pkgsync apply (manual, cuando tú decidas revisar el diff): corre metapac sync (instala lo que falte) y metapac clean (desinstala lo sobrante), ambos con la confirmación interactiva nativa de metapac — nunca se pasa --no-confirm, así que siempre ves y confirmas cada borrado antes de que ocurra.
  • pkgsync diff: igual que el cálculo de pull pero solo imprime, sin tocar git ni notificar.
  • pkgsync incoming: commits nuevos en origin/main aún no traídos (equivalente a git log HEAD..origin/main).
  • pkgsync log [--patch]: historial legible de cambios de paquetes (git log sobre shared/packages-common.sh).
  • pkgsync audit: paquetes instalados localmente que no están declarados en ningún array ni en el override local — drift no capturado. Nota: los paquetes específicos de KDE hardcodeados en kde/setup.sh (plasma-desktop, sddm, temas AUR, etc.) siempre van a aparecer aquí — no viven en los arrays por diseño, no es drift real.

Paquetes críticos (nunca se borran automáticamente)

pkgsync.sh lleva una lista CRITICAL_PACKAGES hardcodeada (kernel, bootloader, drivers gráficos, red de rollback btrfs, y todo lo que sea soporte de hardware: CPU/energía, audio, bluetooth, red física, USB) que es independiente del array — sobrevive aunque el array se corrompa por error humano. Dos capas de protección: push nunca la quita del array aunque detecte que un paquete crítico no está instalado localmente (solo avisa en el log), y el group file que se genera para metapac siempre fuerza la unión con esta lista, así que metapac clean nunca puede verlos como "no declarados". La lista completa está al principio de pkgsync.sh.

Overrides locales (divergencias legítimas entre máquinas)

~/.config/metapac/groups/overrides.local.toml — mismo formato de group file que usa metapac. No vive en ningún repo git (fuera de arch-setup, en ~/.config/metapac/), así que ya queda fuera del control de versiones sin necesidad de nada más. pkgsync lo lee solo para no proponer esos paquetes como "nuevos" en push ni marcarlos como drift en audit; nunca lo escribe ni lo sobreescribe. bootstrap deja un scaffold comentado si no existe.

Instalación

Máquinas nuevas: automático, install_pkgsync() (en packages-common.sh) se llama desde kde/setup.sh justo después de chezmoi init --apply.

Máquinas ya instaladas (retrofit, sin reinstalar):

mkdir -p ~/.local/bin ~/.config/systemd/user
git clone https://gitea.josevi.ovh/josevi/arch-setup.git ~/.local/share/arch-setup
cp ~/.local/share/arch-setup/pkgsync/pkgsync.sh ~/.local/bin/ && chmod +x ~/.local/bin/pkgsync.sh
cp ~/.local/share/arch-setup/pkgsync/systemd/*.service ~/.config/systemd/user/
pkgsync.sh bootstrap
systemctl --user enable --now pkgsync-push.service pkgsync-pull.service

loginctl enable-linger ya está activo por el run_once de chezmoi, no hace falta repetirlo. Verifica una vez con flatpak list --columns=installation,application que tu instalación de Flatpak es system (si es user, cambia FLATPAK_INSTALLATION al principio de pkgsync.sh).

Auto-instalar sin supervisión (opt-in, apagado por defecto)

pkgsync pull respeta la variable de entorno PKGSYNC_AUTO_INSTALL=1: si está activada, corre metapac sync --no-confirm justo después de calcular el diff (solo instala lo que falte). Nunca toca metapac clean — los borrados siguen requiriendo pkgsync apply manual, pase lo que pase.

S
Description
No description provided
Readme
153 KiB
Languages
Shell 87.4%
Python 12.6%