Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ name: Release and Update Website Changelog
on:
push:
tags:
- "v*.*.*"
# main.yml creates release tags without a "v" prefix (e.g. 1.1.3)
- "*.*.*"
workflow_dispatch:
inputs:
test_version:
Expand Down
52 changes: 31 additions & 21 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ jobs:
strategy:
fail-fast: false
matrix:
postgres_tag: ['17', '15']
postgres_tag: ['18', '17', '15']

steps:

Expand Down Expand Up @@ -332,6 +332,10 @@ jobs:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
arch: x86_64
name: linux
postgres_version: '18'
- os: ubuntu-22.04
arch: x86_64
name: linux
Expand All @@ -340,6 +344,10 @@ jobs:
arch: x86_64
name: linux
postgres_version: '15'
- os: ubuntu-22.04-arm
arch: arm64
name: linux
postgres_version: '18'
- os: ubuntu-22.04-arm
arch: arm64
name: linux
Expand All @@ -348,6 +356,10 @@ jobs:
arch: arm64
name: linux
postgres_version: '15'
- os: macos-15
arch: arm64
name: macos
postgres_version: '18'
- os: macos-15
arch: arm64
name: macos
Expand All @@ -356,6 +368,10 @@ jobs:
arch: arm64
name: macos
postgres_version: '15'
- os: macos-15
arch: x86_64
name: macos
postgres_version: '18'
- os: macos-15
arch: x86_64
name: macos
Expand Down Expand Up @@ -617,8 +633,8 @@ jobs:
[**Expo**](https://www.npmjs.com/package/@sqliteai/sqlite-sync-expo): `npm install @sqliteai/sqlite-sync-expo`
[**Android**](https://central.sonatype.com/artifact/ai.sqlite/sync): `ai.sqlite:sync:${{ steps.tag.outputs.version }}`
[**Swift**](https://github.com/sqliteai/sqlite-sync#swift-package): [Installation Guide](https://github.com/sqliteai/sqlite-sync#swift-package)
[**Docker (PostgreSQL)**](https://hub.docker.com/r/sqlitecloud/sqlite-sync-postgres): `docker pull sqlitecloud/sqlite-sync-postgres:17` or `:15`
[**Docker (Supabase)**](https://hub.docker.com/r/sqlitecloud/sqlite-sync-supabase): `docker pull sqlitecloud/sqlite-sync-supabase:17`, `:15` or `:17-alpine`
[**Docker (PostgreSQL)**](https://hub.docker.com/r/sqlitecloud/sqlite-sync-postgres): `docker pull sqlitecloud/sqlite-sync-postgres:18`, `:17` or `:15`
[**Docker (Supabase)**](https://hub.docker.com/r/sqlitecloud/sqlite-sync-supabase): `docker pull sqlitecloud/sqlite-sync-supabase:17` or `:15`

---

Expand All @@ -631,7 +647,7 @@ jobs:

docker-publish:
runs-on: ubuntu-22.04
name: docker ${{ matrix.image }} pg${{ matrix.pg_major }}${{ matrix.tag_suffix }}${{ github.ref != 'refs/heads/main' && ' beta' || '' }}
name: docker ${{ matrix.image }} pg${{ matrix.pg_major }}${{ github.ref != 'refs/heads/main' && ' beta' || '' }}
needs: [build, postgres-test, postgres-build, release]
# main: publish the versioned release tags, only when the release job cut a new
# release. Any other branch: release is skipped, publish/overwrite a per-branch
Expand All @@ -646,29 +662,26 @@ jobs:
fail-fast: false
matrix:
include:
- image: sqlite-sync-postgres
pg_major: '18'
dockerfile: docker/postgresql/Dockerfile.release
- image: sqlite-sync-postgres
pg_major: '17'
dockerfile: docker/postgresql/Dockerfile.release
- image: sqlite-sync-postgres
pg_major: '15'
dockerfile: docker/postgresql/Dockerfile.release
# :<major> tracks whatever base Supabase currently ships for that major.
# Both lines are on an Alpine userland now (still a glibc Nix postgres,
# so the same glibc artifact is installed); there are no family suffixes.
- image: sqlite-sync-supabase
pg_major: '17'
dockerfile: docker/postgresql/Dockerfile.supabase.release
supabase_tag: '17.6.1.071'
supabase_tag: '17.6.1.170'
- image: sqlite-sync-supabase
pg_major: '15'
dockerfile: docker/postgresql/Dockerfile.supabase.release
supabase_tag: '15.8.1.135'
# Newer Supabase 17 images use an Alpine userland (still a glibc Nix
# postgres, so the same glibc artifact is installed). Published behind
# explicit -alpine / exact-base tags; the shared :17 alias stays on the
# Ubuntu build until we decide the alias scheme.
- image: sqlite-sync-supabase
pg_major: '17'
dockerfile: docker/postgresql/Dockerfile.supabase.release
supabase_tag: '17.6.1.151'
tag_suffix: '-alpine'
supabase_tag: '15.14.1.170'

steps:

Expand Down Expand Up @@ -738,15 +751,12 @@ jobs:
VERSION=${{ steps.version.outputs.version }}
IMAGE=${{ env.DOCKERHUB_ORG }}/${{ matrix.image }}
SUPABASE_TAG=${{ matrix.supabase_tag }}
# Empty for the default (Ubuntu) rows; "-alpine" for the Alpine variant.
# Keeps the Alpine images from colliding with the :<major> aliases.
SUFFIX="${{ matrix.tag_suffix }}"
BETA="${{ steps.beta.outputs.slug }}"
{
if [ -n "$BETA" ]; then
echo "tags=${IMAGE}:${{ matrix.pg_major }}${SUFFIX}-beta-${BETA}"
echo "tags=${IMAGE}:${{ matrix.pg_major }}-beta-${BETA}"
else
echo "tags=${IMAGE}:${{ matrix.pg_major }}${SUFFIX},${IMAGE}:${{ matrix.pg_major }}${SUFFIX}-${VERSION},${IMAGE}:${SUPABASE_TAG}"
echo "tags=${IMAGE}:${{ matrix.pg_major }},${IMAGE}:${{ matrix.pg_major }}-${VERSION},${IMAGE}:${SUPABASE_TAG}"
fi
echo "build_args<<EOF"
echo "SUPABASE_POSTGRES_TAG=${SUPABASE_TAG}"
Expand Down Expand Up @@ -794,7 +804,7 @@ jobs:
psql -h 127.0.0.1 -U "$PSQL_USER" -d postgres -v ON_ERROR_STOP=1 \
-c 'CREATE EXTENSION IF NOT EXISTS cloudsync;' \
-c 'SELECT cloudsync_version();'; then
echo "::error::cloudsync failed to load in ${{ matrix.image }} pg${{ matrix.pg_major }}${{ matrix.tag_suffix }}"
echo "::error::cloudsync failed to load in ${{ matrix.image }} pg${{ matrix.pg_major }}"
docker logs cloudsync-smoke
exit 1
fi
Expand Down
12 changes: 9 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,22 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [Unreleased]
## [1.1.3] - 2026-09-11

### Added

- **`sqlitecloud/sqlite-sync-supabase:17-alpine`** — CloudSync on the newer Alpine-userland Supabase Postgres images (roughly `17.6.1.084` and later). The extension is identical to the Ubuntu build — the PostgreSQL binary is glibc-linked on both — so only the base image differs. Use it when your Supabase stack pins one of these newer bases; `:17` continues to track the Ubuntu base.
- **`sqlitecloud/sqlite-sync-postgres:18`** — CloudSync on PostgreSQL 18, alongside the existing `:17` and `:15` images. PostgreSQL 18 release artifacts (`cloudsync-postgresql18-*`) are published for Linux x86_64/arm64 and macOS arm64/x86_64, and the test suite runs against 18 in CI.

### Changed

- **The Supabase images now track the base image Supabase currently ships for each major.** `sqlitecloud/sqlite-sync-supabase:17` moves from `17.6.1.071` to `17.6.1.170` and `:15` moves from `15.8.1.085` to `15.14.1.170` — the latter also advances PostgreSQL from 15.8 to 15.14. Both Supabase lines are now on an Alpine userland, so `:<major>` is the only tag you need; the transitional `:17-alpine` tag is retired because `:17` is the same image. Exact-base tags (e.g. `:17.6.1.170`) are still published for stacks that pin one. Supabase base images do not pin the `postgres` user's UID, so moving an **existing** data directory across base families needs a one-time `chown` of the data directory and the `supabase_db-config` volume — see [Self-Hosted Supabase](docs/postgresql/quickstarts/supabase-self-hosted.md) for how to discover the new UID and apply it. The CloudSync extension itself is unchanged.
- **The local build-from-source path (`make postgres-supabase-build`, `docker/postgresql/Dockerfile.supabase`) now works with the Alpine-userland Supabase bases** as well as the Ubuntu ones. The extension is compiled in a dedicated glibc builder stage (official `postgres:<major>` image with PGDG headers, the same toolchain that produces the release artifacts) whose PostgreSQL major version is derived from the base image tag, and `pg_config` is resolved by probing the Nix profile paths instead of a hardcoded Ubuntu-only path. The runtime stage no longer needs a compiler or package manager, so the base userland is irrelevant.
- **The `sqlitecloud/sqlite-sync-supabase:15` image now builds on Supabase base `15.8.1.135`** (previously `15.8.1.085`), which moves it from Ubuntu 20.04 to 24.04. Ubuntu 24.04 allocates system UIDs differently, so the `postgres` user changes from `105:106` to `101:102` and an **existing** data directory becomes unreadable: the container fails with `cat: /etc/postgresql-custom/pgsodium_root.key: Permission denied` followed by `FATAL: invalid secret key`. Existing deployments need a one-time `chown -R 101:102` on the data directory and the `supabase_db-config` volume before starting the new image — see [Self-Hosted Supabase](docs/postgresql/quickstarts/supabase-self-hosted.md) for the procedure. New deployments are unaffected, and the CloudSync extension itself is unchanged.
- **The development Docker Compose files mount the Postgres data volume at `/var/lib/postgresql` instead of `/var/lib/postgresql/data`.** PostgreSQL 18 keeps its data in a major-version subdirectory and refuses to start when a volume is mounted at the old path; the parent path works for every supported major. Existing local volumes need to be recreated (`docker compose -f docker/postgresql/docker-compose.yml down -v`).

### Fixed

- PostgreSQL payload apply now supports wide tables by growing prepared-statement parameter storage dynamically instead of rejecting statements with more than 32 bound values.
- The website changelog workflow now triggers on the release tags this repository actually creates (`1.1.3`); it was listening for `v`-prefixed tags and never fired automatically.

## [1.1.2] - 2026-07-13

Expand Down
2 changes: 1 addition & 1 deletion docker/Makefile.postgresql
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ DOCKER_TAG ?= latest
DOCKER_BUILD_ARGS ?=
SUPABASE_CLI_IMAGE ?= $(shell docker ps --format '{{.Image}} {{.Names}}' | awk '/supabase_db/ {print $$1; exit}')
SUPABASE_CLI_DOCKERFILE ?= docker/postgresql/Dockerfile.supabase
SUPABASE_POSTGRES_TAG ?= 17.6.1.071
SUPABASE_POSTGRES_TAG ?= 17.6.1.170
SUPABASE_WORKDIR ?=
SUPABASE_WORKDIR_ARG = $(if $(SUPABASE_WORKDIR),--workdir $(SUPABASE_WORKDIR),)
SUPABASE_DB_HOST ?= 127.0.0.1
Expand Down
25 changes: 12 additions & 13 deletions docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ docker exec -it cloudsync-postgres psql -U postgres -d cloudsync_test -c "CREATE
```

This starts:
- PostgreSQL 16 on `localhost:5432`
- PostgreSQL 17 on `localhost:5432` (override with `POSTGRES_TAG`, e.g. `18` or `15`)
- CloudSync extension pre-installed
- pgAdmin on `localhost:5050` (optional, use `--profile admin`)

Expand Down Expand Up @@ -107,19 +107,18 @@ Run the SQL that exercises the code path. If `psql` blocks, the backend is pause

Use this when you're running `supabase start` and want CloudSync inside the local stack.
The Supabase CLI uses a bundled PostgreSQL image (for example,
`public.ecr.aws/supabase/postgres:17.6.1.071`). Build a matching image that
`public.ecr.aws/supabase/postgres:17.6.1.170`). Build a matching image that
includes CloudSync, then tag it with the same name so the CLI reuses it. This
keeps your local Supabase stack intact (auth, realtime, storage, etc.) while
enabling the extension in the CLI-managed Postgres container.

> **Note on Ubuntu vs Alpine bases.** Newer Supabase Postgres images (roughly
> `17.6.1.084` and later) use an Alpine-based userland instead of the earlier
> Ubuntu one. The published release image (`Dockerfile.supabase.release`, used
> for `sqlitecloud/sqlite-sync-supabase:*`) detects the userland automatically
> and works on both. The local build-from-source flow below
> (`make postgres-supabase-build`, `Dockerfile.supabase`) currently assumes an
> Ubuntu base; if your CLI stack pulls a newer Alpine image, prefer the
> published `:17-alpine` release image.
> **Note on Ubuntu vs Alpine bases.** Supabase moved both the PG15 and PG17
> lines to an Alpine-based userland, starting at roughly `15.14.1.x` and
> `17.6.1.084` respectively; earlier bases in both lines were Ubuntu. The published release
> image (`Dockerfile.supabase.release`, used for
> `sqlitecloud/sqlite-sync-supabase:*`) and the local build-from-source flow
> below (`make postgres-supabase-build`, `Dockerfile.supabase`) both detect the
> userland automatically and work on either family.

### Prerequisites

Expand Down Expand Up @@ -149,12 +148,12 @@ enabling the extension in the CLI-managed Postgres container.
`SUPABASE_CLI_IMAGE=public.ecr.aws/supabase/postgres:<tag>`.
Example:
```bash
SUPABASE_CLI_IMAGE=public.ecr.aws/supabase/postgres:17.6.1.071 make postgres-supabase-build
SUPABASE_CLI_IMAGE=public.ecr.aws/supabase/postgres:17.6.1.170 make postgres-supabase-build
```
You can also set the Supabase base image tag explicitly (defaults to
`17.6.1.071`). This only affects the base image used in the Dockerfile:
`17.6.1.170`). This only affects the base image used in the Dockerfile:
```bash
SUPABASE_POSTGRES_TAG=17.6.1.071 make postgres-supabase-build
SUPABASE_POSTGRES_TAG=17.6.1.170 make postgres-supabase-build
```

4. Restart the stack:
Expand Down
6 changes: 3 additions & 3 deletions docker/postgresql/Dockerfile.supabase
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Supabase PostgreSQL with CloudSync (sqlite-sync) built from source
#
# Works with both Supabase base image families:
# - Ubuntu/glibc images (e.g. PG15 15.8.1.135, older PG17 17.6.1.071)
# - Alpine-userland images (e.g. PG17 17.6.1.084+); still a glibc Nix postgres
# - Alpine-userland images, which both the PG15 and PG17 lines now ship
# - the older Ubuntu/glibc images (PG17 up to 17.6.1.071, PG15 up to 15.8.1.x)
# Both families run a Nix-built, glibc-linked PostgreSQL, so the extension is
# compiled in a glibc builder stage (official postgres image + PGDG headers,
# the same toolchain that produces the release artifacts) and the identical
Expand All @@ -12,7 +12,7 @@
# PG_MAJOR must match the major version of SUPABASE_POSTGRES_TAG; the
# postgres-supabase-build Makefile target derives it automatically.
ARG PG_MAJOR=17
ARG SUPABASE_POSTGRES_TAG=17.6.1.071
ARG SUPABASE_POSTGRES_TAG=17.6.1.170

# Build stage for CloudSync extension (glibc toolchain, matching PG headers)
FROM postgres:${PG_MAJOR} AS cloudsync-builder
Expand Down
8 changes: 4 additions & 4 deletions docker/postgresql/Dockerfile.supabase.release
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# Supabase PostgreSQL with pre-compiled CloudSync (sqlite-sync) extension
#
# Works with both Supabase base image families:
# - Ubuntu/glibc images (e.g. PG15 15.8.1.135, older PG17 17.6.1.071)
# - Alpine-userland images (e.g. PG17 17.6.1.084+); still a glibc Nix postgres
# - Alpine-userland images, which both the PG15 and PG17 lines now ship
# - the older Ubuntu/glibc images (PG17 up to 17.6.1.071, PG15 up to 15.8.1.x)
# Both run a Nix-built, glibc-linked PostgreSQL, so the SAME glibc extension
# artifact is installed in either case. Only the build-time userland tooling
# differs (apt-get vs apk), which this file detects at runtime.
#
# Usage:
# docker build \
# --build-arg SUPABASE_POSTGRES_TAG=17.6.1.151 \
# --build-arg SUPABASE_POSTGRES_TAG=17.6.1.170 \
# --build-arg CLOUDSYNC_VERSION=<version> \
# -f docker/postgresql/Dockerfile.supabase.release \
# -t my-cloudsync-supabase-postgres .
Expand All @@ -18,7 +18,7 @@
# docker pull sqlitecloud/sqlite-sync-supabase:17
#

ARG SUPABASE_POSTGRES_TAG=17.6.1.071
ARG SUPABASE_POSTGRES_TAG=17.6.1.170
FROM public.ecr.aws/supabase/postgres:${SUPABASE_POSTGRES_TAG}

ARG CLOUDSYNC_VERSION
Expand Down
5 changes: 4 additions & 1 deletion docker/postgresql/docker-compose.debug.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ services:
- ../../Makefile:/tmp/cloudsync/Makefile:ro
- ../../.vscode:/tmp/cloudsync/.vscode:ro
# Persist database data
- postgres_data:/var/lib/postgresql/data
# PostgreSQL 18+ stores data in a major-version subdirectory and refuses to
# start with a mount at the old /var/lib/postgresql/data path, so mount the
# parent instead — it works for every supported major.
- postgres_data:/var/lib/postgresql
# Mount init script
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
healthcheck:
Expand Down
5 changes: 4 additions & 1 deletion docker/postgresql/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ services:
- ../../docker:/tmp/cloudsync/docker:ro
- ../../Makefile:/tmp/cloudsync/Makefile:ro
# Persist database data
- postgres_data:/var/lib/postgresql/data
# PostgreSQL 18+ stores data in a major-version subdirectory and refuses to
# start with a mount at the old /var/lib/postgresql/data path, so mount the
# parent instead — it works for every supported major.
- postgres_data:/var/lib/postgresql
# Mount init script
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
healthcheck:
Expand Down
17 changes: 9 additions & 8 deletions docs/internal/supabase-flyio-fly-deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ is intended hardening, not a broken route.
```yaml
services:
db:
image: ${CLOUDSYNC_IMAGE:-sqlitecloud/sqlite-sync-supabase:17-alpine}
image: ${CLOUDSYNC_IMAGE:-sqlitecloud/sqlite-sync-supabase:17}
volumes:
- ./cloudsync.sql:/docker-entrypoint-initdb.d/init-scripts/100-cloudsync.sql:Z
ports:
Expand Down Expand Up @@ -140,7 +140,7 @@ override:

```bash
fly secrets set -a "$FLY_APP" \
CLOUDSYNC_IMAGE=sqlitecloud/sqlite-sync-supabase:17-alpine-beta-<branch>
CLOUDSYNC_IMAGE=sqlitecloud/sqlite-sync-supabase:17-beta-<branch>
```

### Secrets
Expand Down Expand Up @@ -208,7 +208,7 @@ release the public IPs, and use `fly proxy 8000 -a <app>`.

| Task | Command |
|---|---|
| Update the CloudSync image | released tag: redeploy (compose pulls `:17-alpine`); beta: `fly secrets set CLOUDSYNC_IMAGE=…` |
| Update the CloudSync image | released tag: redeploy (compose pulls `:17`); beta: `fly secrets set CLOUDSYNC_IMAGE=…` |
| Update Supabase services | bump `SUPABASE_REF` in the `Dockerfile`, `fly deploy` |
| Restart the stack | `fly machine restart -a <app>` — the entrypoint re-runs everything |
| Inspect containers | `fly ssh console -a <app> -C "docker ps"` |
Expand Down Expand Up @@ -380,7 +380,7 @@ it with `CLOUDSYNC_IMAGE`. To build one locally instead:
git submodule update --init --recursive # else: fractional_indexing.h: No such file or directory

docker build --platform linux/amd64 \
--build-arg SUPABASE_POSTGRES_TAG=17.6.1.151 \
--build-arg SUPABASE_POSTGRES_TAG=17.6.1.170 \
-f docker/postgresql/Dockerfile.supabase \
-t <registry>/<image>:<tag> .

Expand Down Expand Up @@ -415,10 +415,11 @@ without credentials, or `docker login` has to run on the Machine.

## Image / version notes

The Alpine CloudSync images are built from `supabase/postgres:17.6.1.151` (see the
publish matrix in `.github/workflows/main.yml`), while the pinned upstream compose
expects `17.6.1.136`. Same PG 17 line, newer patch base — fine, but re-check after
bumping either side.
`:17` is built from `supabase/postgres:17.6.1.170` (see the publish matrix in
`.github/workflows/main.yml`), while the pinned upstream compose expects
`17.6.1.136`. Same PG 17 line, newer patch base — fine, but re-check after bumping
either side. The tag tracks whatever base Supabase currently ships for the major,
so it moves when upstream does; there is no longer a separate `:17-alpine` tag.

The pinned compose runs 11 services: `db`, `supavisor`, `auth`, `rest`, `realtime`,
`storage`, `imgproxy`, `meta`, `functions`, `studio` and the gateway. Upstream has
Expand Down
Loading
Loading