Guía de despliegue

Alojar Gotenberg en un VPS: API PDF para desarrolladores

Desplegar en un VPS Cloud →

Tutorial

Alojar Gotenberg en un VPS: API PDF para desarrolladores

Desarrollo8 min de lectura5 pasos

Todo servicio de PDF en modo SaaS cobra por página o por documento. Gotenberg, no. Es un microservicio HTTP de código abierto con licencia MIT que genera PDF a partir de HTML, URL, Markdown y documentos LibreOffice, con Chromium y LibreOffice integrados en un único contenedor Docker. Esta guía cubre el despliegue completo en un VPS — rutas de API, reverse proxy nginx, ejemplos de integración PHP/Python/Node.js, configuración avanzada y resolución de errores comunes.

Contenido· ¿Por qué autoalojar una API de generación de PDF?1/11
  1. 01¿Por qué autoalojar una API de generación de PDF?
  2. 02¿Gotenberg, WeasyPrint, Stirling-PDF o Puppeteer?
  3. 03Lo que Gotenberg puede convertir
  4. 04Requisitos previos
  5. 05Desplegar Gotenberg paso a paso
  6. 06Rutas y formatos de la API
  7. 07Reverse proxy nginx
  8. 08Integración avanzada: PHP, Python, Node.js
  9. 09Configuración avanzada
  10. 10Resolución de errores comunes
  11. 11Integrarlo con su aplicación

¿Por qué autoalojar una API de generación de PDF?

Los servicios de PDF en modo SaaS (Puppeteer Cloud, PDFShift, DocRaptor) cobran por documento, por página o por volumen de llamadas a la API. En cuanto su aplicación genera facturas, informes o contratos a escala, el costo aumenta de forma lineal con su uso. Gotenberg los sustituye por un costo mensual fijo de VPS, sea cual sea el número de PDF generados. También preserva la confidencialidad de sus documentos: nada sale de su infraestructura durante la conversión.

¿Gotenberg, WeasyPrint, Stirling-PDF o Puppeteer?

Desplace la tabla

HerramientaFormatos fuenteRAM mínimaAPI RESTLicencia
Gotenberg 8.xHTML, URL, DOCX/ODT/XLSX, Markdown, imágenes2 GB (Chromium)Sí — multipart/form-dataMIT
WeasyPrintHTML + CSS (sin JS)256 MBNo — lib Python/CLIBSD
Stirling-PDFPDF (edición, OCR, fusión)512 MBSí — JSON/multipartMIT (AGPLv3 para Pro)
Puppeteer soloHTML + URL via Chrome headless1,5 GBNo — lib Node.jsApache 2.0

Lo que Gotenberg puede convertir

  • HTML a PDF mediante una instancia completa de Chromium — se respetan CSS, fuentes web, JavaScript y las media queries de impresión.
  • Cualquier URL a PDF — archive vistas de paneles de control, genere informes semanales o capture recibos de pago.
  • Documentos LibreOffice (DOCX, XLSX, PPTX, ODT, ODS, ODP y más de 20 formatos) a PDF sin Microsoft Office.
  • Markdown a PDF por la ruta Chromium, con CSS configurable.
  • Varios PDF fusionados en un único archivo con una sola llamada a la API.
  • Imágenes (PNG, JPEG, WebP, TIFF) convertidas a PDF.

Requisitos previos

Un VPS con al menos 1 vCPU y 2 GB de RAM (Chromium solo consume entre 1,2 y 1,5 GB durante el renderizado; 1 GB de RAM es insuficiente en cuanto hay una conversión en curso). Ubuntu 22.04 o 24.04 con Docker y Docker Compose v2 instalados. Gotenberg escucha en el puerto 3000 por defecto. No hace falta ningún dominio si llama a la API desde el mismo servidor — http://127.0.0.1:3000 es suficiente. Para exponerlo a otros servicios se recomienda un reverse proxy nginx (véase más abajo).

Desplegar Gotenberg paso a paso

  1. Crear el archivo compose

    Conéctese por SSH a su VPS y cree un directorio:

    mkdir gotenberg && cd gotenberg

    Cree docker-compose.yml:

    services:
      gotenberg:
        image: gotenberg/gotenberg:8
        restart: unless-stopped
        ports:
          - "127.0.0.1:3000:3000"
        command:
          - gotenberg
          - --chromium-disable-javascript=false
          - --api-timeout=30s
          - --chromium-max-queue-size=10

    La vinculación a 127.0.0.1 impide el acceso directo desde Internet. En 2026 la versión estable es 8.x (8.9.1 y superiores) — la imagen :8 sigue la última 8.x.

  2. Arrancar el contenedor

    Ejecute docker compose up -d. Gotenberg descarga la imagen (~1,5 GB, incluye Chromium y LibreOffice) e inicia el servidor HTTP. Compruebe el endpoint de salud:

    curl http://127.0.0.1:3000/health

    Una respuesta {"status":"up"} confirma que el servicio está listo.

  3. Generar su primer PDF a partir de HTML

    Cree un archivo HTML mínimo (factura.html) y conviértalo:

    curl -s --request POST http://127.0.0.1:3000/forms/chromium/convert/html \
      --form '[email protected]' \
      -o factura.pdf

    La respuesta es el PDF en flujo binario — rediríjalo a un archivo, a un objeto de respuesta o a una subida a S3.

  4. Convertir un documento Word a PDF

    Suba un archivo DOCX a la ruta LibreOffice:

    curl -s --request POST http://127.0.0.1:3000/forms/libreoffice/convert \
      --form '[email protected]' \
      -o contrat.pdf

    Gotenberg utiliza el motor LibreOffice integrado para la conversión — no se requiere ninguna licencia de Microsoft Office.

  5. Añadir una autenticación (recomendado)

    Gotenberg no trae autenticación integrada. El enfoque recomendado: instale nginx, cree un reverse proxy de https://gotenberg.su-dominio.com hacia http://127.0.0.1:3000 y añada una autenticación HTTP basic. No lo exponga nunca sin autenticación a la Internet pública, ya que puede utilizarse para renderizar URL arbitrarias.

Rutas y formatos de la API

Gotenberg expone dos familias de rutas REST, todas en POST multipart/form-data.

Rutas Chromium — renderizado mediante navegador headless:
- POST /forms/chromium/convert/html — conversión desde un archivo HTML local (campo index.html).
- POST /forms/chromium/convert/url — conversión desde una URL pública (campo url); Chromium carga la página completa, JavaScript incluido.
- POST /forms/chromium/convert/markdown — conversión Markdown con hoja de estilos opcional.

Rutas LibreOffice — conversión de documentos ofimáticos:
- POST /forms/libreoffice/convert — acepta DOCX, XLSX, PPTX, ODT, ODS, ODP y más de 20 formatos; varios archivos fusionados en un único PDF si envía merge=true.

Rutas PDF — manipulación de PDF existentes:
- POST /forms/pdfengines/merge — fusiona varios archivos PDF en uno.
- POST /forms/pdfengines/convert — convierte a PDF/A (archivo a largo plazo).

Webhook: en lugar de recibir el PDF como respuesta síncrona, pase una cabecera Gotenberg-Webhook-Url — Gotenberg enviará entonces el PDF mediante POST a su URL en cuanto finalice la conversión.

Reverse proxy nginx

Para exponer Gotenberg a otros servicios o llamarlo desde un dominio dedicado, añada un bloque location en su configuración nginx:

server {
    listen 443 ssl;
    server_name gotenberg.su-dominio.com;

    ssl_certificate     /etc/letsencrypt/live/gotenberg.su-dominio.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/gotenberg.su-dominio.com/privkey.pem;

    location / {
        proxy_pass         http://127.0.0.1:3000;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_read_timeout 60s;
        client_max_body_size 50M;

        auth_basic           "Gotenberg API";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }
}

Si Gotenberg corre en el mismo servidor que su backend, prefiera la llamada directa a http://127.0.0.1:3000 — menor latencia y no es necesario exponer el servicio en un dominio.

Integración avanzada: PHP, Python, Node.js

Gotenberg es independiente del lenguaje — cualquier cliente HTTP capaz de enviar multipart/form-data funciona.

PHP / Laravel — use el paquete oficial gotenberg-php:

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::chromium('http://127.0.0.1:3000')
    ->pdf()
    ->html(Stream::path('/ruta/a/factura.html'));

$response = $client->sendRequest($request);
file_put_contents('factura.pdf', $response->getBody());

Python — con la librería gotenberg-client:

from gotenberg_client import GotenbergClient

with GotenbergClient('http://127.0.0.1:3000') as client:
    with client.chromium.html_to_pdf() as route:
        route.index(Path('factura.html'))
        response = route.run()
        Path('factura.pdf').write_bytes(response.content)

Node.js — con fetch nativo (Node 18+):

const form = new FormData();
form.append('index.html', new Blob([htmlContent], { type: 'text/html' }), 'index.html');

const res = await fetch('http://127.0.0.1:3000/forms/chromium/convert/html', {
  method: 'POST',
  body: form,
});
const pdf = Buffer.from(await res.arrayBuffer());
fs.writeFileSync('factura.pdf', pdf);

Para Node.js, el paquete chromiumly envuelve la API completa si prefiere evitar el FormData manual.

Configuración avanzada

Los parámetros se pasan como argumentos al comando gotenberg en su docker-compose.yml (o mediante variables de entorno con el prefijo GOTENBERG_).

Tiempo límite: --api-timeout=30s — duración máxima de una conversión. Auméntelo (p. ej. 60s) para documentos DOCX largos o páginas con JavaScript pesado.

Concurrencia: --chromium-max-queue-size=10 — número máximo de conversiones Chromium en cola. Superado este límite, Gotenberg responde 503 en lugar de acumular en memoria.

Logs: Gotenberg registra en JSON en stdout — docker compose logs gotenberg le da el detalle de cada conversión.

Deshabilitar LibreOffice (si solo necesita Chromium, ahorra RAM):

command:
  - gotenberg
  - --libreoffice-disable-listener=true

Para arquitecturas de alto volumen, lance varias réplicas de Gotenberg detrás de un balanceador de carga nginx (upstream): cada instancia mantiene sus propios workers de Chromium y escala horizontalmente sin estado compartido.

Resolución de errores comunes

Timeout de Chromium — context deadline exceeded: la conversión HTML supera el timeout configurado. Causas frecuentes: JavaScript lento, recursos externos (CDN, Google Fonts) inaccesibles desde el servidor, o DOM demasiado grande. Solución: aumente --api-timeout, aloje sus assets localmente y adjúntelos como campos multipart.

Puerto 3000 ya en uso: otra aplicación escucha en 3000. Cambie el mapeo en docker-compose.yml: "127.0.0.1:3001:3000" y actualice la URL en sus llamadas.

Archivo demasiado grande — 413 Request Entity Too Large: nginx corta la petición antes de llegar a Gotenberg. Aumente client_max_body_size en el bloque nginx (p. ej. 100M para archivos XLSX grandes).

Sin memoria — OOMKilled: Docker mata el contenedor cuando Chromium supera la RAM disponible. Verifique con docker inspect gotenberg | grep OOMKilled. Remedios: añada RAM al VPS, limite la concurrencia (--chromium-max-queue-size=3), o deshabilite JavaScript si su HTML no lo requiere (--chromium-disable-javascript=true).

Error de LibreOffice — archivo corrupto o formato no reconocido: algunos DOCX generados por herramientas de terceros no son conformes con el estándar OOXML. Verifique primero que el archivo se abre sin errores en LibreOffice Desktop. La cabecera del log de Gotenberg indica el mensaje exacto de LibreOffice (docker compose logs gotenberg --tail 50).

Integrarlo con su aplicación

Gotenberg es independiente del lenguaje: cualquier cliente HTTP funciona. Existen bibliotecas para PHP (gotenberg-php), Node.js (chromiumly), Python (gotenberg-client), Go y otros. Para Laravel, un paquete oficial encapsula la API. En Node.js, puede llamarla con axios o con la API fetch nativa enviando un objeto FormData con el contenido HTML o el archivo. Consulte la sección de integración avanzada de más arriba para ejemplos de código listos para usar en cada lenguaje.

Despliegue Gotenberg en minutos en un VPS Cloud ServOrbit

Con un VPS Cloud ServOrbit que incluye Docker preconfigurado y recursos escalables, instala Gotenberg y obtiene una API de generación de PDF privada para todos sus backends, sin cobro por petición.

¿Necesita ayuda?

Consulte nuestro centro de ayuda y nuestra FAQ, o contacte con nuestro equipo: llamada, WhatsApp o correo electrónico. Soporte en francés, inglés y árabe.

Escribir por WhatsAppse abre en una pestaña nueva