209 lines
15 KiB
Markdown
209 lines
15 KiB
Markdown
# Chromium en este equipo: dónde se toca y cómo
|
|
|
|
Mapa de referencia de TODOS los puntos donde la configuración de Chromium se manipula en esta
|
|
máquina (Linux nativo, Ubuntu 24.04, Chromium 148 del paquete `.deb` de xtradeb — **no snap**).
|
|
Objetivo: no volver a redescubrir a ciegas de dónde sale cada comportamiento (extensiones, CDP,
|
|
proxy). Reconstruido el 2026-06-05 desde el sistema en vivo + transcripts de sesiones anteriores.
|
|
|
|
## El wrapper que une todo
|
|
|
|
`/usr/bin/chromium` es un **shell script** (no el binario). En cada arranque hace, en orden:
|
|
|
|
1. Sourcea **todos** los archivos de `/etc/chromium.d/*` (cada uno exporta/añade a `CHROMIUM_FLAGS`).
|
|
2. Lee las **managed policies** de `/etc/chromium/policies/managed/*.json`.
|
|
3. Aplica `master_preferences` (`/etc/chromium/master_preferences`) al crear un perfil nuevo.
|
|
4. Lanza el binario real `/usr/lib/chromium/chromium $CHROMIUM_FLAGS "$@"`.
|
|
|
|
Por eso cualquier cosa en `/etc/chromium.d/` o en el policy aplica a **TODO** chromium que se
|
|
lance, con cualquier perfil. Editar requiere `sudo` (`pass show claude/sudo | sudo -S ...`).
|
|
|
|
## Inventario de puntos de configuración
|
|
|
|
| Path | Qué controla | Quién/cuándo lo creó | Cómo editar |
|
|
|---|---|---|---|
|
|
| `/etc/chromium/policies/managed/extensions.json` | **Extensiones force-instaladas en cualquier perfil** (`ExtensionInstallForcelist`). Hoy: solo uBlock Origin Lite. | Proyecto "Code", migración de PC (2026-05-31), 4 extensiones. Reducido a uBlock 2026-06-04. | `fn run apply_chromium_extension_policy --keep <id>...` (idempotente, backup auto) o `sudo` editar el JSON. Backup: `extensions.json.bak.20260605` (las 4 originales). |
|
|
| `/etc/chromium.d/cdp` | **CDP global**: `--remote-debugging-port=9222 --remote-allow-origins=*` (bind loopback). | Proyecto web_scraping (2026-06-05), regla 8. | `fn run apply_chromium_cdp_flag [--remove]` o `sudo` editar/borrar el fragmento. |
|
|
| `/etc/chromium.d/web_proxy_ext` | Carga la **extensión de captura del proxy** (`--load-extension=~/.web_proxy/extension`). | Proyecto web_proxy (2026-06-02). | Función `install_chromium_proxy_extension_bash_browser` lo reescribe; `--uninstall` lo borra. |
|
|
| `/etc/chromium.d/extensions` | Pre-existente del `.deb`: `--enable-remote-extensions` + carga unpacked de `/usr/share/chromium/extensions/*` (vacío). | Paquete Debian (Jan 2025). | No tocar salvo necesidad. |
|
|
| `/etc/chromium.d/default-flags` | Flags base del `.deb`: `--show-component-extension-options`, `--enable-gpu-rasterization`, `--no-default-browser-check`, `--disable-pings`, `--media-router=0`. | Paquete Debian. | No tocar. |
|
|
| `/etc/chromium.d/dev-shm` | Añade `--disable-dev-shm-usage` si `/dev/shm` < 3.8 GB. | Paquete Debian. | No tocar. |
|
|
| `/etc/chromium.d/apikeys` | `GOOGLE_API_KEY` de Debian (pública, para sync/gmail). | Paquete Debian. | No tocar (no es secreto). |
|
|
| `/etc/chromium/master_preferences` | Estado inicial de perfiles nuevos (homepage, DuckDuckGo, signin off). **Sin extensiones.** | Distro. | No tocar para extensiones (no es el sitio). |
|
|
| `~/.web_proxy/extension/` | Código de la extensión toggle del proxy (MV3, `chrome.proxy`). | App web_proxy. | Vía `install_chromium_proxy_extension`. |
|
|
| `~/.mitmproxy/mitmproxy-ca-cert.pem` | CA de mitmproxy para HTTPS sin warnings. | mitmproxy. | `./web_proxy ca` para instrucciones. |
|
|
|
|
**No existe** (verificado): external-extensions dir (`/usr/share/chromium/extensions` está vacío;
|
|
`/opt/chromium.org/...` no existe), cron ni systemd-timer que regenere config de chromium, ni
|
|
política `recommended/`. La forcelist es un archivo **estático sin regenerador automático del
|
|
sistema**; se aplica de forma reproducible con `fn run apply_chromium_extension_policy` (idempotente,
|
|
backup automático) o editándola a mano con sudo (también persistente).
|
|
|
|
## Extensiones: el mecanismo (LO QUE MÁS CONFUNDE)
|
|
|
|
Las extensiones de la Chrome Web Store (uBlock, Dark Reader, NoScript, OneTab) se instalan en
|
|
**cualquier perfil** vía `ExtensionInstallForcelist` en el policy managed. Chrome las descarga de
|
|
`clients2.google.com/service/update2/crx` al arrancar cualquier perfil (incluido temporal/nuevo) y
|
|
quedan "managed" (no removibles por la UI). Para cambiarlas se edita el JSON (sudo).
|
|
|
|
- uBlock se usa en la variante **Lite** (`ddkjiahejlhfcafbddmgiahcphecmpfh`, MV3) porque el uBO
|
|
clásico (MV2) no carga en Chromium 148.
|
|
- IDs: uBlock Lite `ddkjiahejlhfcafbddmgiahcphecmpfh` · Dark Reader `eimadpbcbfnmbkopoojfekhnkhdbieeh`
|
|
· NoScript `doojmbjmlfjjnbmnoijecmcbfeoakpjm` · OneTab `chphlpgkkbolifaimnlloiipkdnihall`.
|
|
|
|
### Anomalía resuelta (2026-06-05): backups dentro de `managed/` reinyectan extensiones
|
|
|
|
Tras reducir la forcelist a solo uBlock **en disco**, los perfiles nuevos seguían instalando las 4
|
|
(incluso un `--user-data-dir` recién creado las recibía como `location=7` external_policy_download,
|
|
activas). Causa raíz: **Chromium lee TODOS los archivos del directorio `policies/managed/` sin filtrar
|
|
por extensión de nombre.** El backup `extensions.json.bak.20260605` (con las 4 originales) vivía dentro
|
|
de `managed/` y Chromium lo mergeaba con `extensions.json`, así que el forcelist efectivo seguía
|
|
teniendo las 4 — ganando incluso sobre un `ExtensionInstallBlocklist`. Mover el `.bak` fuera de
|
|
`managed/` (a `policies/policy-backups/`) dejó el forcelist efectivo en solo uBlock y los perfiles
|
|
nuevos pasaron a instalar únicamente uBlock.
|
|
|
|
> Regla dura: en `policies/managed/` (y `recommended/`) **solo** archivos `.json` de política activa.
|
|
> Cualquier `.bak`, `.old`, `.orig` ahí se carga como política. La función del registry
|
|
> `apply_chromium_extension_policy_bash_browser` ya guarda sus backups fuera de `managed/`.
|
|
|
|
El secundario (caché en memoria) también existe: aun con el disco correcto, hay que cerrar TODOS los
|
|
Chromium (`pkill -9 chromium`) o pulsar `chrome://policy → Reload policies` para que el cambio surta
|
|
efecto en runtime.
|
|
|
|
**Para diagnosticar la forcelist EFECTIVA (no la del archivo):** abrir `chrome://policy` en el
|
|
navegador y mirar `ExtensionInstallForcelist` (su columna *Source* y *Value*). No es scriptable por
|
|
CDP (`chrome.send` no accesible vía `Runtime.evaluate`); hay que verlo en la UI y pulsar
|
|
**"Reload policies"**.
|
|
|
|
**Para que un cambio en la forcelist surta efecto de verdad:** cerrar **todos** los procesos
|
|
chromium a la vez (`pkill -9 chromium`) y relanzar uno; o usar `chrome://policy → Reload policies`.
|
|
Mientras quede un chromium vivo con la política vieja, los perfiles nuevos pueden heredarla.
|
|
|
|
### Perfil limpio para scraping
|
|
|
|
Dos caminos (regla 9 de `CONVENTIONS.md`):
|
|
|
|
1. **Perfil nuevo desde cero** + forcelist=solo uBlock → nace solo con uBlock (una vez refrescada
|
|
la política). Es lo más limpio; no arrastra nada.
|
|
2. **`prepare_chrome_profile`** (clona el perfil real conservando solo uBlock): útil cuando se
|
|
necesitan las cookies/sesión del usuario. Borra carpetas de extensiones no-whitelist y purga sus
|
|
refs de `Preferences`/`Secure Preferences` (si no, Chrome las re-descarga del Web Store).
|
|
|
|
## CDP: mapa de puertos
|
|
|
|
| Puerto | Quién | Cómo se activa |
|
|
|---|---|---|
|
|
| 9222 | Chromium **diario** del usuario | Fragmento `/etc/chromium.d/cdp` (global, loopback). Todo chromium nuevo nace con él. |
|
|
| 9333 (o el que se pida) | Navegador de **automatización** dedicado | `script-navegador launch --port 9333` o `systemd-run ... chromium --remote-debugging-port=9333`. Se pasa `--port` para no chocar con el 9222 global. |
|
|
|
|
Dos procesos chromium **no** pueden compartir el mismo `--remote-debugging-port`. El `--port` en
|
|
cmdline sobreescribe al del fragmento global.
|
|
|
|
## Proxy / captura mitm (web_proxy)
|
|
|
|
- App: `projects/web_scraping/apps/web_proxy` (sub-repo Gitea `dataforge/web_proxy`). Compone
|
|
funciones del registry: `start_mitm_capture`, `query_mitm_flows`, `rotate_capture_flows`,
|
|
`launch_chromium_proxy`, `install_chromium_proxy_extension`.
|
|
- Servicio `web_proxy.service` (systemd --user, `Restart=always`): mitmdump/mitmweb.
|
|
- Puertos: **proxy de captura `127.0.0.1:8889`**, UI mitmweb `http://127.0.0.1:8081`.
|
|
- Capturas: `~/captures/traffic-*.mitm`, rotación configurable (`--rotate-min`), retención 2048 MB
|
|
/ 7 días. El addon hace `flush()` por flujo (sobrevive a kill -9).
|
|
- **Enrutar el navegador al proxy — dos vías:**
|
|
1. Extensión toggle `~/.web_proxy/extension`: popup ON → `chrome.proxy` a `127.0.0.1:8889`; OFF →
|
|
directo. **Desde 2026-06-05 se instala vía managed policy, no con `--load-extension`** (Chromium
|
|
137+ desactiva `--load-extension` en cuanto hay una managed policy activa: "Loading of unpacked
|
|
extensions is disabled by the administrator"). La extensión se empaquetó como `.crx`
|
|
(`chromium --pack-extension`, clave en `~/.web_proxy/extension.pem` — NO perder, fija el id
|
|
`nanldmckabfghgdebblpfbdbhphhbnde`), con un `~/.web_proxy/update.xml` (`file://`), y se fuerza con
|
|
`apply_chromium_extension_policy --keep "<id>=file://$HOME/.web_proxy/update.xml"`. Si se edita la
|
|
extensión: re-empaquetar con la MISMA `.pem`, subir `version` en `manifest.json` y `update.xml`.
|
|
`/etc/chromium.d/web_proxy_ext` ya NO usa `--load-extension`.
|
|
2. Perfil dedicado: `chromium --proxy-server=127.0.0.1:8889` (+ CA mitmproxy o
|
|
`--ignore-certificate-errors` para HTTPS).
|
|
- Consultar: `./web_proxy query "~d dominio.com" --last`, `./web_proxy har salida.har`,
|
|
`./web_proxy inspect`.
|
|
|
|
## "Si quiero X, toco Y" (resumen accionable)
|
|
|
|
| Quiero… | Toco… |
|
|
|---|---|
|
|
| Cambiar qué extensiones tiene cualquier perfil | `fn run apply_chromium_extension_policy --keep <id>...` (o editar el JSON con sudo) + cerrar TODO chromium + relanzar |
|
|
| Activar/quitar CDP global | `fn run apply_chromium_cdp_flag [--remove]` (o editar `/etc/chromium.d/cdp` con sudo) |
|
|
| Controlar un chromium con CDP | puerto 9222 (diario) o `script-navegador launch --port N` (dedicado) |
|
|
| Capturar tráfico HTTP/HTTPS | `web_proxy` (proxy 8889, UI 8081); navegador con `--proxy-server=127.0.0.1:8889` o extensión toggle ON |
|
|
| Perfil de scraping limpio | perfil nuevo desde cero (política da solo uBlock) o `prepare_chrome_profile --src ~/.config/chromium --dst <perfil>` |
|
|
| Ver la política EFECTIVA | `chrome://policy` en la UI (no por CDP) → "Reload policies" |
|
|
|
|
## Selector de perfil — SIEMPRE pasar `--profile-directory`
|
|
|
|
Este equipo tiene **varios perfiles** de chromium en `~/.config/chromium`: `Default`, `Personal`,
|
|
`Profile 1`, `Automation` (+ `System Profile`). Si se lanza chromium **sin**
|
|
`--profile-directory=<perfil>`, Chrome se queda en el **selector de perfil** y NO carga ninguno.
|
|
Consecuencias observadas:
|
|
|
|
- CDP responde (`/json/version` OK) pero **no hay perfil activo** → los comandos operan sobre una
|
|
ventana vacía.
|
|
- Las extensiones **no se procesan**: las force-removed de la política no se desinstalan (fue la
|
|
causa real de que las 3 extensiones "no se quitaran" — el diario estaba atascado en el picker).
|
|
- La sesión (`--restore-last-session`) no se restaura.
|
|
|
|
**Regla: SIEMPRE lanzar con `--profile-directory="<perfil>"`.**
|
|
|
|
- Navegador diario del usuario: `--profile-directory="Default"` (o el que use a diario).
|
|
- Navegador de automatización/scraping: `--profile-directory="Automation"` (perfil dedicado), o un
|
|
`--user-data-dir` nuevo (que tiene un solo perfil y por tanto no muestra picker).
|
|
|
|
```bash
|
|
# Diario (visible, con su perfil y CDP global)
|
|
systemd-run --user --unit=chromium-daily --collect --setenv=DISPLAY=:0.0 \
|
|
chromium --profile-directory="Default" --restore-last-session
|
|
|
|
# Automatización (perfil dedicado, proxy mitm, CDP en puerto propio)
|
|
systemd-run --user --unit=ws-explore --collect --setenv=DISPLAY=:0.0 \
|
|
chromium --profile-directory="Automation" --remote-debugging-port=9333 \
|
|
'--remote-allow-origins=*' --proxy-server=127.0.0.1:8889 --ignore-certificate-errors \
|
|
--window-size=1366,768 about:blank
|
|
```
|
|
|
|
> Nota: `script-navegador launch` con `--user-data-dir` propio evita el picker (perfil único). Para
|
|
> apuntar al perfil real multi-perfil del usuario, añadir `--profile-directory`.
|
|
|
|
## Gotchas aprendidos (para no repetir)
|
|
|
|
- **`.bak`/`.old`/`.orig` en directorios "source-todo" se activan**: tanto
|
|
`/etc/chromium/policies/managed/` como `/etc/chromium.d/` se cargan ENTEROS (todos los archivos, sin
|
|
filtrar por extensión de nombre). Un `extensions.json.bak` en `managed/` se mergea como política (y
|
|
reinyecta sus extensiones); un `cdp.bak` en `chromium.d/` se sourcea como shell. Guardar SIEMPRE los
|
|
backups FUERA de esos directorios (este equipo usa `policies/policy-backups/` y
|
|
`chromium/chromiumd-backups/`).
|
|
- **Perfil diario real = `~/.config/chromium-cdp`** (lo fuerza `/etc/chromium.d/cdp`), NO
|
|
`~/.config/chromium`. Limpiar/inspeccionar el perfil del usuario = operar sobre `chromium-cdp`.
|
|
- **Selector de perfil**: con varios perfiles, sin `--profile-directory` Chrome se atasca en el
|
|
picker y no carga nada (ver sección arriba). SIEMPRE especificarlo.
|
|
- **El archivo de policy en disco ≠ política efectiva**: Chrome cachea; verifica siempre en
|
|
`chrome://policy`, no solo con `cat`. Para aplicar cambios, cierra todos los chromium.
|
|
- **Lanzar chromium desde el Bash tool de Claude da exit-144** (el harness mata el cgroup). Usa
|
|
`systemd-run --user --unit=<x> --collect chromium ...` aislado. Ver memoria
|
|
`harness-exit-144-chromium`. (No afecta a binarios Go ni al uso real del usuario.)
|
|
- **`--remote-allow-origins=*` debe ir entre comillas en zsh** (el `*` se expande como glob).
|
|
- **Dark Reader no toca páginas `chrome://`**: una captura de `chrome://version` sale clara aunque
|
|
Dark Reader esté activo; usa una web normal para verificar si está oscureciendo.
|
|
- **`prepare_chrome_profile` clonando**: borra carpetas Y purga `Preferences`, pero pueden quedar
|
|
refs benignas en `commands`/pins; lo que causa re-descarga es `extensions.settings` (ya se purga).
|
|
- **Lock por user-data-dir**: dos procesos chromium NO pueden compartir el mismo `--user-data-dir`
|
|
(aunque sea con `--profile-directory` distinto). Si el diario tiene `~/.config/chromium` abierto,
|
|
un segundo chromium sobre ese mismo user-data-dir muere/delegará al existente y su
|
|
`--remote-debugging-port` no escucha. Para automatización en paralelo: usar un `--user-data-dir`
|
|
dedicado (p.ej. `~/.local/share/web_scraping/scrape-fresh`).
|
|
- **Ventana visible (headless=false) desde systemd-run**: hay que pasar el entorno gráfico:
|
|
`--setenv=DISPLAY=:0 --setenv=XAUTHORITY=$HOME/.Xauthority`. Sin ellos chromium no conecta al X
|
|
server y muere. (`DISPLAY` es `:0`, no `:0.0`.)
|
|
- **Mover la ventana sin xdotool/wmctrl** (no instalados): usar CDP nativo —
|
|
`Browser.getWindowForTarget` (sobre el ws browser-level de `/json/version`) → `windowId`, luego
|
|
`Browser.setWindowBounds {left,top,width,height}`. Funciona en modo visible; `windowState:normal`
|
|
confirma ventana real.
|
|
- **Proxy mitm (8889) ralentiza/cuelga sitios externos**: con `--proxy-server=127.0.0.1:8889`, la
|
|
navegación a sitios externos (p.ej. TED) puede tardar mucho o dejar el renderer atascado, y eso
|
|
bloquea `open`/`eval`/`shot` sobre esa tab. Para scraping con captura: subir timeouts, o revisar
|
|
la salud del upstream del proxy. Sin proxy, en este equipo la salida directa a internet puede dar
|
|
`ERR_CONNECTION_RESET` (la red parece pasar por la infra de captura). A revisar.
|