Configuración del renderer de Chrome para NextPDF Artisan
En resumen
Sección titulada «En resumen»El puente lanza y controla un proceso local de Chrome/Chromium mediante chrome-php/chrome. En esta página se configura ese runtime para que los renders se completen correctamente, incluidas las decisiones sobre contenedores y sandbox.
Cómo se comunica el puente con Chrome
Sección titulada «Cómo se comunica el puente con Chrome»BrowserPool construye una chrome-php/chromeBrowserFactory (opcionalmente con una ruta de binario explícita) y lanza Chrome con un conjunto fijo de flags: headless: true, keepAlive: true, windowSize: [1200, 800], sendSyncDefaultTimeout: renderTimeout * 1000, y los flags personalizados que se enumeran en la página /integrations/artisan/configuration/. Después, el puente controla el proceso lanzado mediante el Chrome DevTools Protocol. No se conecta a un Chrome ejecutándose por separado a través de un puerto de depuración remota, por lo que no hay ningún endpoint de red que exponer ni autenticar. Chrome se ejecuta como proceso hijo del worker de PHP. El test tests/Unit/Artisan/BrowserPoolTest.php::getBrowserCreatesAndReusesInstanceWithExpectedOptions verifica exactamente estas opciones de lanzamiento.
Aprovisionar el binario
Sección titulada «Aprovisionar el binario»Instalar una build de Chrome o Chromium que el usuario worker pueda ejecutar:
# Debian / Ubuntuapt-get install -y chromium
# RHEL / Fedoradnf install -y chromium
# Alpine (containers)apk add --no-cache chromium nss freetype harfbuzz ttf-freefontVerificar que se ejecute en modo headless como el usuario worker:
chromium --headless --dump-dom about:blankUn código de salida 0 con un DOM vacío indica que el binario y sus bibliotecas compartidas están presentes. Una salida distinta de cero es el mismo fallo que el puente expone como un ChromeRenderException. Debe corregirse aquí primero.
Apuntar el puente al binario
Sección titulada «Apuntar el puente al binario»La detección automática (el comportamiento predeterminado de chrome-php/chrome) funciona cuando existe un binario en una ruta estándar. Para obtener determinismo en producción, conviene fijarlo explícitamente:
$config = new ChromeRendererConfig( chromeBinaryPath: '/usr/bin/chromium',);o con configuración en array:
$config = ChromeRendererConfig::fromArray([ 'chrome_binary' => '/usr/bin/chromium',]);Aprovisionamiento en contenedores y decisión del sandbox
Sección titulada «Aprovisionamiento en contenedores y decisión del sandbox»En un contenedor, el sandbox del sistema operativo de Chrome a menudo no puede inicializarse como root / PID 1 sin capabilities de kernel adicionales. Hay dos caminos:
- Mantener el sandbox (preferido). Ejecutar el worker como un usuario no root y otorgar al contenedor las capabilities que necesita el sandbox de Chrome (habitualmente
SYS_ADMIN, o un perfil de seccomp que permita crear espacios de nombres de usuario). Esto mantiene intacto el aislamiento de procesos de Chrome. - Desactivar el sandbox. Establecer
no_sandbox: true. Chrome se lanza con--no-sandbox. Esto elimina el sandbox de aislamiento de procesos de Chrome: una reducción real de la contención, no un flag cosmético. Usarlo solo donde el sandbox no pueda habilitarse, ejecutar Chrome como un usuario no root dentro de un contenedor restringido y tratar el despliegue como si exigiera un nivel de confianza mayor en la entrada. Las barreras de red del puente (CSP + bloqueo de CDP) siguen vigentes en cualquier caso, pero no sustituyen al aislamiento de procesos. Esto se alinea con la guía de mínimo privilegio y aislamiento de OWASP ASVS para renderizar contenido no confiable.
La declaración completa de la frontera —lo que el sandbox protege y lo que no— está en la página /integrations/artisan/security-and-operations/. Esta página no afirma que desactivar el sandbox sea seguro.
Forma de contenedor de referencia
Sección titulada «Forma de contenedor de referencia»FROM php:8.4-cliRUN apt-get update && apt-get install -y --no-install-recommends \ chromium fonts-liberation \ && rm -rf /var/lib/apt/lists/*RUN useradd -m -u 10001 workerUSER workerENV CHROME_BINARY=/usr/bin/chromium# Set CHROME_NO_SANDBOX=1 only if the sandbox cannot be enabled in your runtime.Ejecutar el worker como worker (uid 10001), no como root. El puente ya aplica el flag --disable-dev-shm-usage, que evita el crash por /dev/shm pequeño, habitual en contenedores sin más ajustes.
Fuentes
Sección titulada «Fuentes»El puente bloquea las descargas de fuentes remotas (--disable-remote-fonts y CSP). Instalar las fuentes necesarias en la capa del sistema operativo, o incrustarlas mediante URI data: en reglas @font-face dentro de defaultCss o del HTML. La salida CJK requiere un paquete de fuentes CJK (por ejemplo fonts-noto-cjk) instalado en la imagen.
Sonda de salud
Sección titulada «Sonda de salud»Usar esta sonda independiente para probar la ruta completa del puente sin la aplicación host:
<?php
declare(strict_types=1);
use NextPDF\Artisan\ChromeHtmlRenderer;use NextPDF\Artisan\ChromeRendererConfig;
require __DIR__ . '/vendor/autoload.php';
$renderer = new ChromeHtmlRenderer( ChromeRendererConfig::fromArray([ 'chrome_binary' => getenv('CHROME_BINARY') ?: null, 'no_sandbox' => (bool) getenv('CHROME_NO_SANDBOX'), ]),);
$result = $renderer->render('<p>ok</p>', 200.0, 0.0);fwrite(STDOUT, strlen($result->getPdfData()) > 0 ? "CHROME_OK\n" : "CHROME_EMPTY\n");$renderer->close();CHROME_OK confirma el lanzamiento, el render y el import. Una excepción lanzada identifica el fallo preciso. Consultarla en la página /integrations/artisan/troubleshooting/. Conectarla como comprobación de readiness en despliegues orquestados.
Notas sobre aislamiento de recursos
Sección titulada «Notas sobre aislamiento de recursos»- Ejecutar Chrome como un usuario no root dedicado.
- Aplicar un límite de memoria del host; el puente acota el crecimiento con un reinicio cada 100 renders, pero sigue siendo necesario un techo del host.
- Combinar
render_timeoutcon un presupuesto de solicitud aguas arriba en cualquier ruta alcanzable por entrada no confiable. - No exponer un puerto de depuración remota de Chrome. El puente no usa ninguno y un puerto CDP abierto es un canal de control sin autenticar.
Modos de fallo y resolución de problemas
Sección titulada «Modos de fallo y resolución de problemas»| Síntoma | Causa probable | Dónde mirar |
|---|---|---|
ChromeNotAvailableException | chrome-php/chrome no instalado | /integrations/artisan/install/ |
ChromeRenderException en el primer render | Binario ausente / el sandbox no puede inicializarse | Esta página; /integrations/artisan/troubleshooting/ |
| PDF vacío | Sin caja visible / crash de Chrome | /integrations/artisan/troubleshooting/ |
| Imágenes remotas en blanco | Red bloqueada por diseño | /integrations/artisan/security-and-operations/ |
| Pico de latencia periódico | Reinicio cada 100 renders | /integrations/artisan/production-usage/ |
Véase también
Sección titulada «Véase también»- /integrations/artisan/install/
- /integrations/artisan/configuration/
- /integrations/artisan/security-and-operations/
- /integrations/artisan/troubleshooting/
- /integrations/artisan/production-usage/