A blazingly fast, standalone microservice that converts HTML/CSS to production-ready PDFs. Built with Rust, powered by PrinceXML, and wrapped in a secure Axum web server.
While tools like Gotenberg use Headless Chrome (built for screens), this engine uses PrinceXML (built for print). If you are generating invoices, books, reports, or tickets, this is the tool for you.
- Print-Perfect CSS: Full support for
@pagerules, CMYK colors, footnotes, and physical margins. - Ultra-Lightweight: Compiles HTML directly to a PDF binary. No massive browser bloat.
- Built-in Templating: Send raw JSON and a Minijinja (Jinja2) template in one request.
- Direct-to-S3: Bypasses your main app by uploading directly to S3/MinIO and returning a signed URL.
The engine is available as a pre-built Docker image containing all necessary fonts and dependencies.
Run this command for quick testing:
docker run -d \
--name pdf-engine \
-p 6767:6767 \
-e API_BEARER_TOKEN="your_secret_token_here" \
zalven88/pdf-engine:latest
Add this to your docker-compose.yml. Note that inside a Docker network, you must use the service name (e.g., minio) for the STORAGE_URL.
services:
pdf-engine:
image: zalven88/pdf-engine:latest
container_name: pdf-engine
restart: always
ports:
- "6767:6767"
environment:
- API_PORT=6767
- API_BEARER_TOKEN=${PDF_ENGINE_TOKEN}
- STORAGE_DRIVER=minio
- STORAGE_ACCESS_KEY=${S3_KEY}
- STORAGE_SECRET_KEY=${S3_SECRET}
- STORAGE_BUCKET=my-bucket
- STORAGE_URL=http://minio:9000 # Internal Docker URL
- STORAGE_REGION=us-east-1
depends_on:
- minio
networks:
- app-network
networks:
app-network:
driver: bridge
All endpoints require a multipart/form-data payload and your Bearer token in the headers.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
template |
String | Yes | - | The Minijinja/HTML template. |
data |
JSON | No | null |
Data to inject into the template. |
width |
String | No | 8.5in |
Page width. |
height |
String | No | 11in |
Page height. |
filename |
String | No | document.pdf |
Download name (or S3 key suffix). |
password |
String | No | None | Encrypts the PDF with this password. |
Returns the raw binary PDF file.
curl -X POST http://localhost:6767/api/to-bytes \
-H "Authorization: Bearer my_secret_token" \
--form-string "template=<h1>Invoice</h1><p>Billed to: {{ name }}</p>" \
-F "data={\"name\": \"Zalven\"}" \
--output my_invoice.pdf
Uploads to S3/MinIO and returns a JSON URL.
curl -X POST http://localhost:6767/api/to-s3 \
-H "Authorization: Bearer my_secret_token" \
--form-string "template=<h1>Welcome {{ name }}</h1>" \
-F "data={\"name\": \"Zalven\"}"
If your logs show Connection Refused when trying to upload to S3/MinIO:
- Don't use
127.0.0.1orlocalhostin yourSTORAGE_URLif the storage is in another container. - Do use the service name defined in your compose file (e.g.,
http://minio:9000).
If you see a "Prince" watermark on your PDFs, you are using the free version. To remove it:
- Purchase a license from PrinceXML.
- Follow the license installation instructions (usually placing a
license.datfile in the engine's path).
The Rust application code is open-source under the MIT License.