ConvertX: a self-hosted file converter that bundles 20 converter engines behind one web UI
ConvertX is a self-hosted web application that converts files across more than 1,000 document, image, audio, and video formats.
At a glance
- What is it?
- ConvertX is a TypeScript and Bun web application that shells out to LibreOffice, FFmpeg, Pandoc, Calibre and others to convert across more than a thousand formats. It is a good fit for a private network with a container host and a little patience for image size.
- Who is it for?
- Adopt ConvertX if you already run a container host, want conversions to stay on your own hardware, and are willing to carry a Debian image that ships LibreOffice, Calibre, FFmpeg, Inkscape and Ghostscript. Do not adopt it if you need per-request isolation, a documented HTTP API, or a small image.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 6 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What ConvertX solves, and who it is actually for
The problem is mundane and recurring: someone has a file in a format the next tool will not open, and the conversion has to happen without uploading the file to a third party. ConvertX addresses that by running a web application on your own machine or server and doing the conversion locally. The README describes it as "a self-hosted online file converter" that supports over a thousand formats, written with TypeScript, Bun and Elysia.
The audience is narrower than the format count suggests. This is for people who already have somewhere to run a container: a home lab, a NAS with Docker, a small VPS. If you have no container runtime and no intention of adding one, the project offers you nothing that a desktop converter does not. The README's own deployment section assumes Docker, and the repository ships a compose.yaml, a Dockerfile and a .devcontainer directory, which tells you where the maintainer expects this to run.
The feature list is short and honest: convert files to different formats, process multiple files at once, password protection, multiple accounts. Password protection here means account login, not per-file encryption. Nothing in the README claims the stored files are encrypted at rest, and the default volume mount is a plain directory on the host.
How the conversion actually happens: a dispatcher over 20 external tools
ConvertX is not a converter. It is a router. The README's converter table lists the external programs it invokes and, for each, how many formats it accepts and produces. ImageMagick is credited with 245 input formats and 183 output formats, FFmpeg with roughly 472 and roughly 199, Pandoc with 43 and 65, LibreOffice with 41 and 22. The README notes that many FFmpeg file formats are duplicates, so the headline number of over a thousand formats is a sum of overlapping lists rather than a thousand distinct capabilities.
That design has consequences worth understanding before you deploy. The Dockerfile's release stage installs the toolchain with apt: assimp-utils, calibre, dasel, dcraw, dvisvgm, ffmpeg, ghostscript, graphicsmagick, imagemagick-7.q16, inkscape, latexmk, libheif-examples, libjxl-tools, libreoffice, libva2, libvips-tools, and more. Each of those is a separate program with its own bugs, its own memory profile and its own history of parsing untrusted input. ConvertX's job is to pick one, pass the file through, and hand back the result.
Because the converters are separate processes, the application itself stays small: the package.json lists only six runtime dependencies, including elysia, @elysiajs/jwt, @elysiajs/static, @kitajs/html, sanitize-filename and tar. The complexity lives in the container image and in the converter binaries, not in the TypeScript.
Installing ConvertX with Docker Compose and converting a first file
The README gives a docker-compose.yml to copy. The image is ghcr.io/c4illin/convertx, the container listens on port 3000, and ./data is mounted to /app/data. JWT_SECRET is optional but the README recommends setting it; if it is unset the application generates one with randomUUID().
services:
convertx:
image: ghcr.io/c4illin/convertx
container_name: convertx
restart: unless-stopped
ports:
- "3000:3000"
environment:
- JWT_SECRET=aLongAndSecretStringUsedToSignTheJSONWebToken1234
volumes:
- ./data:/app/dataStart it with docker compose up -d, then open http://localhost:3000 and create your account. The README warns explicitly: "Don't leave it unconfigured and open, as anyone can register the first account." That is the whole access-control story for a fresh install. If the page will not let you log in, the README's warning block points at the cause: unless you are on localhost or HTTPS, you need HTTP_ALLOWED=true.
The single-container form is shorter and does the same thing, with a random JWT secret and no compose file to keep:
docker run -p 3000:3000 -v ./data:/app/data ghcr.io/c4illin/convertxOnce you are logged in, upload a file, choose a target format, and run it. Converted output and history are written under the mounted data directory, and the history page is visible unless HIDE_HISTORY is set to true. If the container reports "unable to open database file", the README's fix is a permissions change on the host path: chown -R $USER:$USER path.
The environment variables that decide whether this is safe to expose
Four variables control the security posture, and three of them default to the safe value. ACCOUNT_REGISTRATION defaults to false, so no one can create a second account unless you turn it on. HTTP_ALLOWED defaults to false. ALLOW_UNAUTHENTICATED defaults to false. The README repeats the same caution for the last two: only set this to true locally. That phrasing is a warning, not a suggestion, and it is worth taking literally.
AUTO_DELETE_EVERY_N_HOURS defaults to 24 and, per the README, checks every n hours for files older than n hours and deletes them. Setting it to 0 disables deletion entirely. This is the one default that pushes against the others: on a default install, anything you convert and forget about is gone within a day. If you are using ConvertX to keep a converted archive, you have to set this to 0 and accept that the data directory will grow without bound.
WEBROOT lets you serve the interface under a subpath; the README's example is setting it to "/convert" so the site answers on example.com/convert/. FFMPEG_ARGS and FFMPEG_OUTPUT_ARGS pass extra flags to FFmpeg, for example -hwaccel vaapi on the input or -preset veryfast on the output, and the README links issue 190 for hardware acceleration details. HIDE_HISTORY removes the history tab. The compose.yaml in the repository adds TZ, defaulting to UTC, and UNAUTHENTICATED_USER_SHARING, which the comment says is for use with ALLOW_UNAUTHENTICATED=true to share history across unauthenticated users and devices.
Where ConvertX is the wrong tool
The most obvious limitation is the image. The Dockerfile's release stage installs LibreOffice, Calibre, Inkscape, Ghostscript, ImageMagick, GraphicsMagick, FFmpeg, assimp-utils and more on top of debian:testing-slim. That is a large amount of software, and it is the reason the project can claim broad format coverage at all. You cannot get the format count without the binaries. If you wanted a slim converter for one format family, this is the wrong shape of tool.
Second, every converter is a parser of untrusted input, and they all run in the same container as the web application. There is no sandboxing described in the README, no per-job container, no seccomp profile mentioned. The repository does carry a SECURITY.md, which suggests the maintainer thinks about this, but the README does not describe process isolation. If you plan to let untrusted users upload files, that is a design decision you are making, not one the project has made for you.
Third, the README does not document an HTTP API for scripted conversions. The interfaces it describes are the web UI and the environment variables. If your workflow is a CI job that needs to convert a file and read the result, nothing in the README tells you how to do that without driving the browser.
Fourth, the maintenance signal. The last push to main was on 2026-06-21, which is also the date of the v0.18.0 release. The previous release, v0.17.0, was on 2026-01-13. That is a gap of roughly five months between releases, so the project moves in bursts rather than continuously.
ConvertX compared with a single-purpose CLI pipeline
The realistic alternative is not another web application. It is the same underlying tools driven directly: ffmpeg for audio and video, pandoc for documents, ImageMagick or libvips for images, Calibre's ebook-convert for ebooks. Every one of those is already inside the ConvertX image.
The difference in approach is the interface and the state. A CLI pipeline has no accounts, no history page, no upload form, and no retention policy to configure; it also has no format-selection logic, so you have to know which tool handles which pair. ConvertX's contribution is the routing table plus a UI, so a user who does not know that LibreOffice handles one document pair and Pandoc handles another can still get a result.
If you are one person converting a handful of files a month, the CLI is less to install and less to keep patched. ConvertX earns its place when several people need to convert files and none of them want to learn the tool matrix, or when the files must not leave your network. The trade is clear: you accept a large image and a web-facing service in exchange for not explaining FFmpeg flags to anyone.
Licence and the cost of keeping the image current
ConvertX is licensed AGPL-3.0, which is a copyleft licence with a network-use clause. The practical implication for a self-hoster running it privately is limited: you are not distributing the software. If you modify ConvertX and expose the modified version to users over a network, the AGPL's source-availability condition is the part to read carefully. That is a description of the licence, not legal advice; if you plan to build a product on a modified ConvertX, have someone qualified read the LICENSE file in the repository.
Upgrade cost is dominated by the image, not the application code. The Dockerfile pins Bun to v1.4.2 and builds on debian:testing-slim, so a rebuild pulls whatever the testing suite currently contains for LibreOffice, FFmpeg, Calibre and the rest. The repository includes a renovate.json, which indicates dependency updates are automated, and releases are tagged, so there is a version to pin to rather than tracking main. Pinning a tag and rebuilding on your own schedule is the lower-risk path; rebuilding from main means you inherit the testing-suite churn as well as the application's changes.
Editorial conclusion
Adopt ConvertX if you already run a container host, want conversions to stay on your own hardware, and are willing to carry a Debian image that ships LibreOffice, Calibre, FFmpeg, Inkscape and Ghostscript. Do not adopt it if you need per-request isolation, a documented HTTP API, or a small image. Before committing, check the licence text, confirm the container can write to the mounted ./data volume, and verify that AUTO_DELETE_EVERY_N_HOURS matches how long you need converted files to survive.
Frequently asked questions
What is ConvertX?
It is a self-hosted web application that converts files between more than a thousand document, image, audio and video formats. It is written in TypeScript with Bun and Elysia, and it works by invoking external converters such as FFmpeg, LibreOffice and Pandoc.
Is ConvertX self-hosted?
Yes. The README describes it as a self-hosted online file converter and gives Docker Compose and docker run instructions for running it on your own machine or server, with a ./data volume mounted to /app/data.
How to install ConvertX?
Use the compose file from the README with the image ghcr.io/c4illin/convertx, port 3000, and a ./data volume, then visit http://localhost:3000 and create your account. The README warns not to leave it unconfigured and open, because anyone can register the first account.
How to use ConvertX?
After logging in, upload a file, pick a target format and run the conversion; the README also lists processing multiple files at once as a feature. Converted files and history live under the mounted data directory, and the history page is hidden if HIDE_HISTORY is set to true.
Is ConvertX good?
It depends on what you need. It covers a very wide format range by bundling about twenty converters into one Debian-based image, but the README documents no HTTP API and no process isolation between the web app and the converters, so it is a poor fit for untrusted uploads or scripted pipelines.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/c4illin-convertx)