Skip to content

Upgrading

Read the release notes before every upgrade. Breaking changes are listed there. Back up the database and your originals first; see Backup and restore.

  1. If your .env file sets FRAMELEAF_VERSION, change it to the version you want.
  2. In the folder with your docker-compose.yml, run:
Terminal window
docker compose pull && docker compose up -d

To free disk space afterwards, remove the old images:

Terminal window
docker image prune

If you run the machine learning container on another computer, upgrade it at the same time. See Remote machine learning.

  • A slower first start. After some upgrades the server builds a database index before it’s ready. For example, one release builds an index on the paths of generated files, and saving generated files waits until it’s done. On a large library this takes longer than usual. Let it finish; nothing else is needed.
  • Model downloads. Smart search, face recognition and text recognition models download from the Frameleaf model mirror at models.frameleaf.cloud. The order is MACHINE_LEARNING_MODEL_SOURCE_URL, then HF_ENDPOINT, then the Frameleaf mirror, so a mirror of your own is still used. A mirror must serve the models under the frameleaf organisation. The machine learning log names the source at startup.

Upgrading from an older installation doesn’t need you to move media or recreate the database. Keep your Compose project name, .env, upload and database paths, volume names, external library mounts and database settings, and keep the stack in the same folder, because relative paths are resolved from the Compose files.

  • The service names (immich-server, immich-machine-learning, database, redis), the project name immich and the machine learning address http://immich-machine-learning:3003 stay the same for compatibility.
  • The displayed container names are frameleaf_server, frameleaf_machine_learning, frameleaf_postgres and frameleaf_redis. Update any scripts that address a container by an old name.
  • Environment variables are named FRAMELEAF_*, such as FRAMELEAF_VERSION and FRAMELEAF_LOG_LEVEL. The old IMMICH_* names keep working as deprecated aliases, and the server logs one warning listing them with their new names. Setting an old and a new name to different values stops the server, which names the pair.
  • immich-admin and immich-healthcheck still work as aliases of frameleaf-admin and frameleaf-healthcheck. See Server commands.

Commands that use the service name work with any container name:

Terminal window
docker compose config --images
docker compose pull
docker compose up -d
docker compose logs immich-server
docker compose exec immich-server frameleaf-admin list-users
docker compose exec database pg_isready

Frameleaf uses semantic versioning: <major>.<minor>.<patch>. Breaking changes, including to the API or deployment, are meant to happen only in major releases.

Tag Follows
release, latest The current stable release
edge Development builds
A major version, such as v3 The newest release of that major version. Doesn’t follow release candidates
An exact version That release only. Release bundles pin this

Machine learning images with hardware acceleration add a suffix, for example release-cuda. See Hardware acceleration.

Patches aren’t backported to older versions, and downgrading isn’t supported, even within the same minor version.

A new release can reach servers in stages: the update notice in About reaches a growing share of servers over a few days, so one server may see it before another. Each server’s place in line is a random value it keeps to itself; nothing identifying is sent. You can always upgrade as soon as a release is published.

If a serious problem is found, the release is withdrawn. Servers stop offering it, its release notes start with withdrawn: and the reason, and the release and latest tags point at the previous release again.

A newer version upgrades your database, and an older version can’t run on it. To go back:

  1. Stop Frameleaf: docker compose down.
  2. Restore the database backup taken before the upgrade. See Backup and restore. Your photos and videos aren’t changed by an upgrade.
  3. Set FRAMELEAF_VERSION in .env to the release you ran before (for example frameleaf-v3.2.0-15), or use that release’s installation files.
  4. Start Frameleaf: docker compose pull && docker compose up -d.

Skip step 2 only if the withdrawal notice says the release didn’t change the database. Files uploaded between the upgrade and the restore stay in the library folder but aren’t in the restored database, so upload them again.

Every Frameleaf release image is signed. To check an image before you run it, install cosign, download Frameleaf’s public key cosign.pub, and verify the image by its tag, or by the digest in the release’s release-manifest.json:

Terminal window
cosign verify --key cosign.pub ghcr.io/frameleaf/frameleaf-server:<release tag>
cosign verify-attestation --key cosign.pub \
--type https://frameleaf.app/attestations/release-manifest/v2 \
ghcr.io/frameleaf/frameleaf-server:<release tag>

The first command checks the signature. The second checks the attached release manifest, which names the source commit and the build and deployment runs that qualified it. Releases published before signing began aren’t signed.

VectorChord is the database extension Frameleaf uses for smart search and face recognition. It replaced the older pgvecto.rs extension, which is no longer supported, and it’s faster in almost every way.

If your docker-compose.yml uses a database image with vectorchord in its tag, such as ghcr.io/frameleaf/frameleaf-postgres:14-vectorchord0.4.3-pgvectors0.2.0, and you haven’t set DB_VECTOR_EXTENSION, you’re already on VectorChord and there’s nothing to do.

If you’re still on the old pgvecto-rs image:

  1. Back up your database.
  2. In docker-compose.yml, change the database service as shown below: use the new image, add shm_size: 128mb, and remove the old healthcheck and command sections, which are now built into the image.
  3. If your database is on a hard drive rather than an SSD, uncomment DB_STORAGE_TYPE: 'HDD'.
  4. Start Frameleaf as normal.
database:
container_name: frameleaf_postgres
image: docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:739cdd626151ff1f796dc95a6591b55a714f341c737e27f045019ceabf8e8c52
image: ghcr.io/frameleaf/frameleaf-postgres:14-vectorchord0.4.3-pgvectors0.2.0
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_DB: ${DB_DATABASE_NAME}
POSTGRES_INITDB_ARGS: '--data-checksums'
# Uncomment the DB_STORAGE_TYPE: 'HDD' var if your database isn't stored on SSDs
# DB_STORAGE_TYPE: 'HDD'
volumes:
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
healthcheck:
...
command: >-
postgres
-c shared_preload_libraries=vectors.so
...
shm_size: 128mb
restart: always

The first start reindexes the database, which takes from seconds to minutes. With more than 100,000 items or a modest server, the logs can sit at Reindexing clip_index and Reindexing face_index for a while. If there are no errors, give it time.

Frameleaf publishes one database image, for PostgreSQL 14 with pgvecto.rs 0.2.0, and it can’t open a database from another PostgreSQL major version. If your old image was a different combination, such as pg16-v0.3.0, or you run your own PostgreSQL server, follow Standalone PostgreSQL instead.

Is the health check gone? No. The removed lines are now built into the image, with some extra tuning.

Can I still restore older backups? Yes. The image also includes pgvector and pgvecto.rs, so it restores backups made with either. Backups made after the switch need an image with VectorChord.

Why does SSD or HDD matter? The best settings differ. Either setting works on either kind of drive, but the right one makes Frameleaf snappier. Keep the database on an SSD when you can.

Can I use the image for other things? Yes. It’s a standard PostgreSQL image with the VectorChord, pgvector and pgvecto.rs extensions added.