Files
arch-setup/README.md
T
Josevi c074095d68 Añade pkgsync: sincronización de paquetes entre máquinas (mismo patrón que chezmoi)
Nuevo pkgsync/pkgsync.sh + servicios systemd --user (push al cerrar sesión,
pull+diff+notifica al iniciar sesión, sin aplicar cambios solo) usando
metapac como motor de diff/aplicación sobre los arrays de
packages-common.sh. Lista de paquetes críticos protegidos de borrado
automático, fichero de overrides local para divergencias entre máquinas, y
comandos de introspección (diff/log/incoming/audit).

De paso, grub/efibootmgr y los drivers gráficos pasan de estar hardcodeados
en cada <de>/setup.sh a vivir en PACMAN_COMMON, para que pkgsync pueda
declararlos y protegerlos.
2026-08-18 10:46:23 +02:00

184 lines
9.2 KiB
Markdown

# 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.
Dos variantes de escritorio: **GNOME** y **KDE Plasma**.
```
arch-setup/
├── gnome/ archinstall-config.json + setup.sh (GNOME, gdm)
├── kde/ archinstall-config.json + setup.sh (KDE Plasma, sddm)
├── shared/ packages-common.sh (paquetes comunes a ambos)
├── pkgsync/ pkgsync.sh + systemd/ (sync de paquetes entre máquinas)
└── README.md
```
> Procedimiento paso a paso completo en [INSTALL.md](INSTALL.md).
## Uso (desde el USB live de Arch, como root)
```bash
pacman -Sy --noconfirm git
git clone https://gitea.josevi.ovh/josevi/arch-setup
cd arch-setup
./gnome/setup.sh # o ./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 el JSON de la variante → instala base + escritorio
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 en ambos escritorios; el resto diverge por DE.
GNOME: Catppuccin Mocha + iconos Papirus-Dark + Dash-to-Dock y extensiones
(AppIndicator, Blur my Shell, Caffeine, Clipboard Indicator, Vitals). KDE: 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.
- **Dotfiles**: `chezmoi` apuntando a un repo separado (`arch-configs`).
## ⚠️ 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, DavMail,
Betterbird, OnlyOffice, Spotify, ungoogled-chromium, Karere, HelpWire (vía
`.deb`→`debtap`). GNOME añade gnome-calculator/tweaks; KDE añade
kcalc/ark/spectacle/kdeconnect/kinfocenter.
## 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](https://github.com/ripytide/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/GNOME hardcodeados en `<de>/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 `<de>/setup.sh` justo después de
`chezmoi init --apply`.
**Las dos máquinas ya instaladas** (retrofit, sin reinstalar):
```bash
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.