How to self-host Gotenberg with Docker

How to self-host Gotenberg with Docker

Self-host Gotenberg with Docker in five minutes, lock it down for production, and learn when a hosted HTML-to-PDF API is the better deal.

Gotenberg is an open-source (MIT) Docker image that wraps headless Chromium and LibreOffice behind a simple HTTP API. html-pdf.com runs it under the hood, so everything below comes from running it in production.

Quick answer. Start the container with docker run --rm -p 3000:3000 gotenberg/gotenberg:8, then post an index.html file to /forms/chromium/convert/html. If you would rather not run a server, the hosted API takes JSON and returns a PDF:

curl https://html-pdf.com/v1/pdf -H "Authorization: Bearer $HTML_PDF_KEY" \
  -d '{"html": "<h1>Hello</h1>"}' -o out.pdf

1. Start Gotenberg

This step gets a local Gotenberg server running with one command.

docker run --rm -p 3000:3000 gotenberg/gotenberg:8

Check that it is up.

curl http://localhost:3000/health

2. Convert HTML to PDF

Here you turn an HTML file or a live URL into a PDF. Gotenberg expects a multipart/form-data request with a file named exactly index.html.

echo '<h1>Hello from Gotenberg</h1>' > index.html
curl -F files=@index.html http://localhost:3000/forms/chromium/convert/html -o out.pdf

Useful form fields include paperWidth / paperHeight (inches or units like 210mm), marginTop…marginLeft, landscape=true, printBackground=true and waitDelay=2s. You can send images, fonts and CSS as extra files and reference them by name from index.html.

To render a live web page instead, use the URL route.

curl -F url=https://example.com http://localhost:3000/forms/chromium/convert/url -o page.pdf

3. Lock it down before exposing it

These settings keep a public Gotenberg from becoming a security hole. By default it renders anything for anyone who can reach it, so fix that before it touches the internet.

4. docker compose for production

This compose file puts the hardening flags together with your app on a private network.

services:
  gotenberg:
    image: gotenberg/gotenberg:8
    restart: unless-stopped
    command:
      - gotenberg
      - --api-timeout=30s
      - --chromium-deny-private-ips
      - --api-disable-download-from
      - --libreoffice-disable-routes
      - --chromium-idle-shutdown-timeout=15m
    mem_limit: 2g
  app:
    build: .
    environment:
      GOTENBERG_URL: http://gotenberg:3000
    depends_on: [gotenberg]

--chromium-idle-shutdown-timeout lets Chromium sleep when idle, which saves memory on small servers. The first request after a pause takes about a second longer.

5. What you sign up for

This is the ongoing work that comes with self-hosting. The licence is free, but your time is not.

Or skip the server

If you only need HTML (or a URL) in and a PDF out, html-pdf.com gives you a hosted, hardened Gotenberg behind an API key.

curl https://html-pdf.com/v1/pdf -H "Authorization: Bearer $HTML_PDF_KEY" \
  -d '{"html": "<h1>Hello</h1>", "format": "A4"}' -o out.pdf

Get a free API key · API reference · Deploy Gotenberg on Railway

FAQ

Is Gotenberg free to use?

Yes. Gotenberg is open source under the MIT licence, so you only pay for the server you run it on and the time to maintain it.

How much memory does Gotenberg need?

Plan for 1-2 GB of RAM for comfortable concurrency, and set a container memory limit because Chromium memory use spikes on large documents.

How do I secure a self-hosted Gotenberg?

Keep the port on a private Docker network, add basic auth if it must be remote, and use --chromium-deny-private-ips to block SSRF. Also set --api-timeout and disable routes you don't use.

Is there a hosted alternative to running Gotenberg myself?

Yes. html-pdf.com runs Gotenberg for you behind a JSON API with POST https://html-pdf.com/v1/pdf. You get 100 free credits without a card, then pay from $0.005 per page, and failed renders cost nothing.

This page as markdown · text