docx-to-pdf
Documentation: oxidestack.github.io/docx-to-pdf
docx-to-pdf turns office documents into PDF faster and with less memory than Gotenberg and moalhaddar/docx-to-pdf on the same documents, and no document — however large, malicious or broken — can take it down, hold it past its timeout or make it reach the network.
- Less CPU than Gotenberg: Gotenberg uses 1.20–1.23× the CPU a conversion as it ships, and 1.08–1.14× without its restarts (the row).
- Less memory than Gotenberg: its container peaks at 1.65–1.76× the memory as it ships, and 1.80–1.86× without its restarts (the row).
- The service it replaces, outrun: 3.05–3.24× moalhaddar/docx-to-pdf’s throughput at 0.30–0.32× its CPU a conversion and 0.42–0.44× its memory (the row).
- Bombs stopped at once: a deflate bomb,
pages-500000p, a document that inflates past any limit, and a picture bomb,px-8x1024mpx, eight gigapixel pictures, each get 413 in 0.01–0.04 s at a 235–237 MiB peak; Gotenberg answers 503 in 30.00–30.03 s while its LibreOffice goes on to 7 609–8 078 MiB, and moalhaddar/docx-to-pdf gives no answer in 300.02–300.11 s, at 9 347–9 374 MiB on the deflate bomb; the same answers in each of the 3 runs (the deflate bomb, the picture bomb).
Measured by make compare on 2026-10-29 17:16 UTC, and in 2 earlier full runs on 2026-10-27 13:57 UTC and 2026-10-28
10:06 UTC, each on an Intel(R) Xeon(R) Gold 6248R CPU @ 3.00GHz (x86_64) virtual machine of 8 vCPUs, 1 pinned vCPU and a
pool of 1 a service: a run’s figure is the mean ± σ (n) over 3 interleaved blocks, and a ratio above is the range of the
3 runs’ ratios; a bomb is one run a side in each run. The image measured is release 1.0.0, pulled by digest in the
latest run; the earlier runs measured the code of their day, built by the command, before the heap trim.
Benchmarks has every figure of the latest run, the rows where
Gotenberg wins, and the raw results of every run.
An HTTP service that turns an office document into a PDF with LibreOffice.
It answers the same requests as moalhaddar/docx-to-pdf 2.1.0-13, so a client of that service moves to this one without changing a line, and it is built to stay up under load that service does not survive: a document that never finishes converting, a request that never finishes uploading, a file that is not a document, a burst of more requests than there are LibreOffice processes. It is written in Rust, ships a current LibreOffice, and reports what it does over OpenTelemetry.
Quick start
Section titled “Quick start”docker run --rm -p 8080:8080 quay.io/oxidestack/docx-to-pdf:1.1.0In another terminal, once it has started:
curl -F document=@report.docx http://localhost:8080/pdf -o report.pdfreport.pdf is the document as LibreOffice lays it out. A test replays this curl against the service.
Every release is signed and carries its SBOM and build provenance;
Verifying a release checks an image or a chart with cosign and
gh attestation verify.
What it gives
Section titled “What it gives”- Word and OpenDocument text in, PDF out: DOCX, DOCM, DOTX, DOC, ODT, OTT, flat ODT and RTF. The format is
decided from the document’s bytes, not its name; anything else is refused with
415before any conversion starts. - The interface of moalhaddar/docx-to-pdf:
POST /pdfandPOST /docx-to-pdf, the document in a multipart file part nameddocument, the PDF as the answer. - Reliability: a time limit on every conversion, a bounded wait for a free LibreOffice process, limits on the size of a document and of what it inflates to, LibreOffice processes replaced when they crash, hang or have run a set number of conversions, and a graceful shutdown that finishes the conversions in progress. Every error is an RFC 9457 problem document with a status that says what went wrong.
- Telemetry: traces, logs and metrics over OTLP, Prometheus metrics at
/metrics, and the health checks/livezand/readyzfor Kubernetes. - A locked-down container for
linux/amd64andlinux/arm64: a non-root user, a read-only root file system, no Linux capabilities, and only free fonts, metric-compatible with the common Microsoft ones.
Documentation
Section titled “Documentation”The guide is published at oxidestack.github.io/docx-to-pdf; the same
pages are in docs/guide/:
- Installation —
docker run, Docker Compose and Kubernetes with the Helm chart, and the resources to give it - Configuration — every environment variable, its default and its effect
- API reference — the endpoints, the formats accepted, every status and its detail
- Operations — the container, health checks, Kubernetes, telemetry and metrics, limits, sizing and fonts
- Troubleshooting — every error answer and other problems, what each means and what to do
- Migrating from moalhaddar/docx-to-pdf — what stays the same, what a client or a deployment changes, and every deliberate difference
- Changelog — what each release changed, and what an operator has to do when a release asks it
- Compared with Gotenberg and moalhaddar/docx-to-pdf — what each does, speed, memory and hostile documents, from the measurements on record, and the commands that repeat them
Building and testing
Section titled “Building and testing”The repository carries moalhaddar/docx-to-pdf as a git submodule, which the tests read, so clone it with its submodules:
git clone --recursive https://github.com/oxidestack/docx-to-pdf.gitIn a clone made without --recursive, run git submodule update --init once.
make imagebuilds the container image for your machine’s architecture asdocx-to-pdf:dev.make checkruns formatting, clippy and the library tests.cargo testruns every test; it needs a Rust toolchain and poppler onPATH(pdfinfo,pdftotext,pdftoppm:brew install poppleron macOS,apt-get install poppler-utilson Debian), and the tests that convert real documents need LibreOffice.tools/instance-test/run.shruns them in a Linux container that carries all three.make lintruns every quality gate the CI runs, each in its own pinned container; CONTRIBUTING.md’s checks lists them, and the CI badge above is their state onmain.
Getting help
Section titled “Getting help”Questions go to Discussions, bugs to issues, vulnerabilities to a private report (SECURITY.md). CONTRIBUTING.md says how to build, test and send a change.
Licence
Section titled “Licence”The code is licensed under the Apache License, Version 2.0 (Apache-2.0). The documentation — this README,
the guides under docs/ and the chart’s README — is licensed under
Creative Commons Attribution 4.0 International (CC-BY-4.0). The
material taken from moalhaddar/docx-to-pdf, the fonts and LibreOffice keep their own licences and are attributed in
NOTICE.