Upgrading
To upgrade, pull the new images and restart:
docker compose pull
docker compose up -d
This updates all four containers to the version your compose file names (:latest by default). The database upgrades itself on start. Read the changelog first, and the notes below if you're crossing one of these versions.
To 3.18 or later: CSV, JSON and XML uploads
Uploaded .csv, .json and .xml files are read by PullMD itself, so the output differs from the MarkItDown output: JSON and XML arrive in a code block. Documents fetched by URL go through MarkItDown as before. See Upload formats PullMD reads itself.
To 3.17 or later: status check and anonymous deletes
- An instance that updates
pullmdbut keeps apullmd-playwrightimage older than 3.17.0 gets503from/api/status, with"error": "policy-missing", until the sidecar is updated. See Health check. - With
DISABLE_PUBLIC_HISTORY=trueand sign-in off,DELETE /api/cacheandDELETE /api/cache/:idreturn403to anonymous callers.
To 3.16 or later: markers under Reddit images
On an instance with a vision provider and the default PULLMD_EMBEDDED_IMAGES=on-request, image posts carry an Image not transcribed marker under each image without a transcript. See Describe images in Reddit posts.
To 3.15.2 or later: update the browser sidecar too
3.15.2 fixes a security issue in the Playwright sidecar (GHSA-26wr-prg5-vr77). The fix spans the pullmd and pullmd-playwright images: the sidecar enforces the policy and pullmd sends the allowed hosts and handles the refusal. docker compose pull does both. If you pin versions, change the tag on both images.
To 3.13 or later: reverse proxy settings
3.13 has no breaking API change, but it stops trusting forwarding headers by default. If PullMD runs behind a reverse proxy other than the bundled Traefik file:
- Set
PULLMD_TRUST_PROXY. Without it, all visitors share one set of rate limits. - Set
PUBLIC_URLto the publichttps://address, so the session cookie staysSecureand links point to the right place. - If you use sign-in, check that the proxy passes the original
Hostheader and doesn't sendReferrer-Policy: no-referrer. See Sign-in behind a proxy.
Also changed in 3.13:
- OAuth access tokens work only on
/mcp. Scripts calling/apineed an API key. - MCP
list_recentshows signed-in users their own conversions only. /api/statsshows per-domain lists only to the admin, or to everyone when sign-in is off and public history is on.- Image captions, audio transcripts and PDF OCR share an hourly budget,
PULLMD_LLM_RATE_LIMIT(default 30). - Fetched pages and documents are limited to
PULLMD_MAX_FETCH_BYTES(default 50 MB), and a page fetch has a 60-second timeout. - New accounts need an email address with a dotted domain.
If you keep your own compose file, add - PULLMD_TRUST_PROXY=${PULLMD_TRUST_PROXY:-} to the pullmd service.
To 3.0 or later: clean body
3.0 changed the Markdown body. It now starts with # Title and goes straight into the content. The source line that used to follow the title (domain, date and URL, or the subreddit line for Reddit) is gone; the same information is in the frontmatter (url, fetched, subreddit, author, upvotes, published).
To get the old body back:
PULLMD_SOURCE_HEADER=true
If you used format=text and relied on the URL in the body, request frontmatter=true or set PULLMD_SOURCE_HEADER=true.
The Claude Code skill was renamed from web-reader to pullmd in 3.0. Remove the old one before installing the new one: see Claude Code skill.
Pin and roll back
Pin an exact version on every image to control when you upgrade:
image: aeternalabshq/pullmd:3.18.2
Before a big upgrade, copy the ./data folder. To roll back, pin the previous version and run docker compose up -d. 3.13 doesn't change the database schema, and 3.0 only adds a metadata column to the conversions table, which older versions ignore. Rolling back across them needs no restore. For other versions, check the changelog for schema changes first. To stay on the 2.x output format, use aeternalabshq/pullmd:2.
For the full history, including upgrades from 1.x and 2.x, see MIGRATION.md.