Install plone.pgthumbor

This guide covers installing both the Plone-side package (plone.pgthumbor) and the Thumbor-side loader (zodb-pgjsonb-thumborblobloader), then verifying that everything works together.

Requirements

  • Python 3.12+

  • Plone 6.2+ (Classic or Volto)

  • PostgreSQL 14+ (tested with 17)

  • zodb-pgjsonb >= 1.1 as the ZODB storage backend

  • Thumbor 7+

Install the Plone package

Install plone.pgthumbor into your Plone environment:

uv pip install plone.pgthumbor
# or
pip install plone.pgthumbor

This also installs libthumbor (for HMAC URL signing) and plone.pgcatalog as dependencies.

Install the Thumbor loader

On the machine or container running Thumbor, install the blob loader:

uv pip install zodb-pgjsonb-thumborblobloader
# or
pip install zodb-pgjsonb-thumborblobloader

This installs psycopg[binary] (async PostgreSQL driver) and boto3 (optional, for S3 fallback).

Configure ZODB storage

Your zope.conf must use zodb-pgjsonb as the ZODB storage backend. plone.pgthumbor discovers its PostgreSQL connection from the storage layer.

%import zodb_pgjsonb

<zodb_db main>
  <pgjsonb>
    dsn dbname=zodb host=localhost port=5432 user=zodb password=zodb
    blob-temp-dir /app/var/blobstorage
  </pgjsonb>
  mount-point /
</zodb_db>

Configure Thumbor

Create a thumbor.conf that uses the zodb-pgjsonb blob loader:

LOADER = "zodb_pgjsonb_thumborblobloader.loader"

HANDLER_LISTS = [
    "thumbor.handler_lists.healthcheck",
    "zodb_pgjsonb_thumborblobloader.auth_handler",
]

SECURITY_KEY = "your-secret-key"
ALLOW_UNSAFE_URL = False

RESULT_STORAGE = "thumbor.result_storages.file_storage"
RESULT_STORAGE_FILE_STORAGE_ROOT_PATH = "/tmp/thumbor/result_storage"

PGTHUMBOR_DSN = "dbname=zodb host=localhost port=5432 user=zodb password=zodb"

See Configure Thumbor for plone.pgthumbor for the full list of settings.

Set Plone environment variables

Plone needs to know where to point image URLs. Set these environment variables before starting Zope:

export PGTHUMBOR_SERVER_URL="http://localhost:8080/thumbor"
export PGTHUMBOR_SECURITY_KEY="your-secret-key"

The security key must match the SECURITY_KEY in thumbor.conf. See Configure Plone settings for all available settings.

Apply the GenericSetup profile

Install via Plone’s Add-on installer (Site Setup > Add-ons > plone.pgthumbor), or programmatically:

setup_tool = portal.portal_setup
setup_tool.runAllImportStepsFromProfile("profile-plone.pgthumbor:default")

The profile registers the @@images override and the @thumbor-auth REST service.

plone.pgthumbor is autodiscovered via z3c.autoinclude – no %import is needed in zope.conf.

Verify installation

Start Thumbor:

thumbor --conf=/etc/thumbor.conf

Start Zope:

runwsgi instance/etc/zope.ini

Upload an image in Plone. Right-click the displayed image and inspect the URL. It should point to your Thumbor server (the value of PGTHUMBOR_SERVER_URL) with an HMAC signature and blob coordinates:

http://localhost:8080/thumbor/<hmac>/400x300/<zoid_hex>/<tid_hex>

Open the URL in a new tab. You should see the scaled image.

If the image does not load, check:

  • Thumbor logs for connection errors to PostgreSQL

  • That the PGTHUMBOR_DSN in thumbor.conf is correct

  • That the PGTHUMBOR_SECURITY_KEY matches between Plone and Thumbor

  • That the blob_state table exists in PostgreSQL (created by zodb-pgjsonb)