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.
- Don't publish the port. Keep it on a private Docker network and call it only from your app.
- Add basic auth if it must be reachable remotely.
docker run -p 3000:3000 \ -e GOTENBERG_API_BASIC_AUTH_USERNAME=me -e GOTENBERG_API_BASIC_AUTH_PASSWORD=long-random-secret \ gotenberg/gotenberg:8 gotenberg --api-enable-basic-auth - Block SSRF. HTML from users can point
<img>or<iframe>athttp://169.254.169.254or your internal services. Add--chromium-deny-private-ips(and--api-disable-download-fromif you don't use that feature). - Turn off what you don't use. Use
--libreoffice-disable-routes,--pdfengines-disable-routesand--webhook-disable. - Bound resources. Set
--api-timeout=30s,--chromium-max-queue-size=20, and a memory limit on the container, because Chromium memory use spikes.
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.
- Updates. Chromium ships security fixes constantly and Gotenberg releases follow. Pin a major version (
:8) and pull regularly. - Memory. Plan for 1-2 GB of RAM for comfortable concurrency.
- Scaling and queues. Bursts of large documents need horizontal scaling or a queue in front.
- Monitoring. You need health checks, restarts and logs.
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
- JSON in, PDF out. No multipart and no
index.htmlnaming rules. - SSRF protection, timeouts and updates are handled for you.
- A remote MCP server lets Claude, ChatGPT and Cursor make PDFs directly.
- 100 free pages, then pay per page (from $0.005). Credits never expire.
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.
