Upgrading
Memship is released as versioned Docker images. Upgrading means pointing at a newer image tag, pulling, and recreating the stack — database migrations run automatically on startup.
Versioning
Memship follows semantic versioning. Git tags are the single source of truth for the version — there is no VERSION file. Published images are tagged with the release version (e.g. 1.2.0) and latest.
Pin a specific version in production rather than tracking latest, so upgrades are deliberate. Set it in .env:
IMAGE_TAG=1.2.0Upgrade procedure
Back up first. See Backups & restore.
Review the release notes for the target version (breaking changes, new required settings) on the releases page.
Pull the repository, not only the image tag:
cd /path/to/memship git pullPart of a release ships in the git checkout rather than in the images —
docker-compose.yml, theCaddyfile,scripts/install.sh. BumpingIMAGE_TAGalone leaves an install half-upgraded: the new backend running behind the old proxy configuration.Bump the tag in
.env:IMAGE_TAG=1.3.0Pull and recreate:
docker compose pull docker compose up -d docker compose up -d --force-recreate caddyThe last line matters. The
Caddyfileis bind-mounted, so changing its contents does not change the container’s configuration —docker compose up -dsees no reason to recreate Caddy and leaves it serving the old one.
Upgrading from a release before the non-root backend
The backend containers used to run as root, so anything they wrote into the storage directory landed root-owned. They now run as HOST_UID/HOST_GID, which is what makes bind-mounted uploads readable on the host without sudo — but the container can no longer write the files its root-era self left behind.
Take ownership once, after upgrading:
sudo chown -R $(id -u):$(id -g) "$MEMSHIP_DATA_ROOT/storage"scripts/install.sh detects this and prints the exact command; running it by hand has the same effect.
Two related changes in the same release:
uv runno longer works inside the containers. The virtualenv is onPATHinstead, so nothing under/appis written at runtime — that is what lets the container run under any uid. Usedocker compose exec api python -m …, notdocker compose exec api uv run python -m …. Anything you have scripted against the containers needs the same edit.Persistent data moved from named volumes to bind mounts under
MEMSHIP_DATA_ROOT. If you are upgrading an install that used named volumes, copy each one across before starting:docker run --rm -v pgdata:/from -v /srv/openmemship/data/postgres:/to \ alpine cp -a /from/. /to/
Database migrations
Migrations run automatically on backend startup when RUN_MIGRATIONS=1 (the default in the Compose stack). No manual migration step is needed for a standard upgrade.
If you prefer to run migrations manually, set RUN_MIGRATIONS=0 and run them yourself against the backend container after pulling the new image.
Rolling back
Roll back by setting IMAGE_TAG to the previous version and recreating the stack. Note that database migrations are not automatically reversed — if a release included a migration, restore the database backup you took in step 1 rather than only downgrading the image.