Migrating from LibreOffice headless / A report designer or markup toolchain
Migrating off headless LibreOffice conversion, and its templates
An office suite run headless to convert documents to PDF, where the template is a word processor file and the conversion is a whole application invoked per document.
What ports and what does not
The content ports; the template does not. The layout lives in an ODT or DOCX file that somebody edited in a word processor, and the merge fields or placeholders in it are filled by whatever templating you put in front. Rebuilding it as HTML means re-creating the design, which is real work and has a real upside: the office file was probably edited by a non-developer, and moving to markup moves it into the codebase. That is a change in who can edit the document, and it is worth agreeing before rather than after.
What the call becomes
The soffice invocation with --headless --convert-to pdf becomes a POST to /v1/pdf with html. The profile directory, the timeout wrapper and the lock file handling that every LibreOffice pipeline accumulates all disappear. Page setup moves from the office document's page settings into options.format and options.margin or a page rule.
Side by side
The old shape and the new one, with the parts that have no counterpart called out in comments rather than quietly omitted.
# Before
soffice --headless --norestore \
-env:UserInstallation=file:///tmp/lo-$$ \
--convert-to pdf --outdir /tmp/out /tmp/in/invoice.docx
# After
curl -X POST https://api.pdfpipe.xyz/v1/pdf \
-H "Authorization: Bearer $PDFPIPE_KEY" \
-H "Content-Type: application/json" \
-d '{ "html": "<!doctype html>...", "options": { "format": "A4" } }'
# What goes away with the binary:
# the per-process user profile directory, and the lock contention
# that made concurrent conversions unreliable
# the timeout wrapper around a process that sometimes does not exit
# the font packages in the image, and the substitution surprises
# when a font was missing
# the whole office suite in the container
#
# What has to be decided:
# who edits the template now. It was a word processor file; it is
# about to be markup in a repository, and the person who maintained
# it may not be able to any more.The CSS delta, in both directions
What the old engine accepted that a current one does not, and what it refused that a current one wants. The second direction is the one people forget, and it is where the value of the migration is.
- Nothing to migrate, because the source was not CSS. The office document's styles are the specification and transcribing them is the work.
- Page setup, headers and footers move from the office document's own settings into the page rule and the header and footer options.
- Fonts move from packages installed in the container to @font-face, which removes the substitution problem that headless conversion is notorious for.
- Everything CSS offers is new relative to what a word processor template expressed.
What changes without anything erroring
The dangerous list. Each of these produces a different document and no diagnostic, so none of them are caught by a test that only checks the render succeeded.
- Everything visual, because it is a rebuild.
- Font rendering, which in the old pipeline depended on which fonts happened to be installed in the image and frequently substituted without complaint.
- Page count, which in the old pipeline was already unstable across image rebuilds for the same reason.
- Who can change the document, which is not a technical change and is the one most likely to cause friction.
What to diff before cutting over
Compare against a conversion done on a machine with the right fonts installed, not against whatever your container currently produces, because the container's output may already be wrong in ways nobody noticed. Then diff extracted text.
The one thing that always breaks
The editing workflow. The template was a file somebody in the business could open and change, and after the migration it is markup in a repository behind a pull request. Nothing technical fails, and the person who used to fix a wording change in ten minutes now files a ticket, which is discovered the first time a wording change is needed.
Frequently asked
Do I have to rewrite my templates to leave LibreOffice headless?
Effectively yes, and it is better to plan for that than to discover it. The old tool did not have HTML templates to port, so the document has to be expressed as markup for the first time. The value in the old code is the data layer underneath the drawing, and that part survives untouched.
Can I run both for a while?
Yes, and it is the safest way to do it. Put both behind one internal function that takes your data and returns bytes, switch on an environment variable, and run the new path on real traffic while the old one still serves. You get a diff on real documents rather than on fixtures, and you keep a way back that does not involve a deploy.
What about the documents already generated?
Nothing here changes them. They are files that already exist. What is worth deciding before the cutover is whether a regenerated document has to match the original byte for byte or merely say the same thing, because for anything with a legal or audit character the answer is usually to keep the original file rather than to be able to reproduce it.
Other migrations
The nearest neighbours first, then others that started from the same kind of tool, because the model matters more than the language.
Migrating off DOCX templating, and keeping the Word deliverable
A pipeline that fills placeholders in a Word template and converts the result to PDF, where the conversion step is what you are replacing and the Word file may still be a deliverable.
Migrating off Crystal Reports, and rebuilding the formula fields
A reporting product whose layouts live in binary report files edited in a designer, with sections, formula fields and its own formula language, none of which are portable.
Migrating off SSRS, from RDL and tablix to markup
A reporting service whose layouts are RDL files built around a tablix, with the report server providing scheduling, subscriptions and delivery alongside the rendering.
Migrating off JasperReports, and what happens to the bands
A reporting engine whose layouts are XML files built in a visual designer, organised into bands that repeat by rule, where nothing about the layout is portable and the band model has no equivalent.
Migrating off Apache FOP, from XSL-FO to CSS
A formatter taking XSL-FO, an XML vocabulary for paged layout, usually produced from your data by an XSLT transform, where the transform is the template and both halves change.
Every migration, grouped by what you are coming from
The full list, sorted by the model the old tool used rather than by its name.
What this API actually does
One page per option and endpoint that exists, which is what the mappings above point at.
Render one of your existing documents through the playground before changing any code. That comparison is the whole of the risk assessment for this migration.