How to deploy Gotenberg on Railway

How to deploy Gotenberg on Railway

Deploy Gotenberg on Railway with password protection and private networking, call it from your app, and keep the bill low with idle shutdown.

These are the exact steps we used to run Gotenberg on Railway for html-pdf.com.

Quick answer. Deploy a small Dockerfile based on gotenberg/gotenberg:8 with railway up, set a basic auth username and password, and call it from your other services at http://gotenberg.railway.internal:3000. If you would rather not run a server, one POST https://html-pdf.com/v1/pdf request does the same job (see the end of this page).

1. Create the service from a Dockerfile

This step gives you a pinned, hardened Gotenberg service. A tiny Dockerfile lets you pin the version and pass hardening flags. Railway sets a PORT variable, so the first flag tells Gotenberg to use it.

FROM gotenberg/gotenberg:8
CMD ["gotenberg", \
  "--api-port-from-env=PORT", \
  "--api-enable-basic-auth", \
  "--api-timeout=30s", \
  "--api-disable-download-from", \
  "--chromium-deny-private-ips", \
  "--chromium-idle-shutdown-timeout=15m", \
  "--libreoffice-disable-routes", \
  "--webhook-disable"]

Put it in its own folder (for example gotenberg/Dockerfile) and deploy with the Railway CLI.

railway up gotenberg --path-as-root --service gotenberg

You can also create the service from the gotenberg/gotenberg:8 image in the dashboard and set the start command there.

2. Set the variables

These variables turn on password protection. Set them on the Gotenberg service.

variable value
PORT 3000
GOTENBERG_API_BASIC_AUTH_USERNAME any username
GOTENBERG_API_BASIC_AUTH_PASSWORD a long random string

Use the CLI's stdin mode so secrets don't end up in your shell history.

openssl rand -hex 24 | railway variable set GOTENBERG_API_BASIC_AUTH_PASSWORD --stdin --service gotenberg

3. Call it over the private network

This step connects your app to Gotenberg without exposing it to the internet. Services in the same Railway project reach each other at <service>.railway.internal, so your app can use this URL.

GOTENBERG_URL=http://user:password@gotenberg.railway.internal:3000
curl -u user:password -F files=@index.html \
  http://gotenberg.railway.internal:3000/forms/chromium/convert/html -o out.pdf

Only add a public domain (Settings → Networking) if something outside Railway must call it. Keep basic auth on when you do.

4. Keep the cost down

One flag cuts most of the bill for low-traffic projects. Railway bills RAM by the minute, and an idle Chromium still holds memory.

--chromium-idle-shutdown-timeout=15m shuts Chromium down after 15 idle minutes. It restarts on the next request, which is about a second slower.

5. Verify

These two commands confirm the service is up and that auth is enforced. The second one should return 401.

curl -u user:password https://<your-domain>/health
curl -s -o /dev/null -w '%{http_code}\n' -F files=@index.html https://<your-domain>/forms/chromium/convert/html   # 401 without auth

Or skip the server

If you just need PDFs, you can use an API instead of running Gotenberg. Running it yourself means pinning versions, rotating secrets, watching memory and patching Chromium. html-pdf.com is that same hardened Gotenberg setup as an API.

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

There is no idle RAM bill. You get 100 free pages, then pay from $0.005 per page, and credits never expire. It also gives AI agents a remote MCP server.

FAQ

How much RAM does Gotenberg need on Railway?

Chromium holds memory even when idle, and Railway bills RAM by the minute. Setting --chromium-idle-shutdown-timeout=15m frees that memory after 15 idle minutes, at the cost of about a second on the next request.

How do I password-protect Gotenberg on Railway?

Start Gotenberg with --api-enable-basic-auth and set GOTENBERG_API_BASIC_AUTH_USERNAME and GOTENBERG_API_BASIC_AUTH_PASSWORD on the service. Requests without those credentials get a 401.

Do I need a public domain for Gotenberg on Railway?

No. Services in the same Railway project can call it at http://gotenberg.railway.internal:3000. Only add a public domain if something outside Railway must reach it, and keep basic auth on.

Is there a hosted alternative to running Gotenberg?

Yes. html-pdf.com runs the same hardened setup as an API at POST https://html-pdf.com/v1/pdf. You get 100 free credits once with no card, and purchased credits never expire.

Get a free API key · Self-host Gotenberg with Docker · Gotenberg in n8n

This page as markdown · text