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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

### Changed

- **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.

## [1.1.2] - 2026-07-13
Expand Down
14 changes: 8 additions & 6 deletions docker/Makefile.postgresql
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ PG_MIGRATION_SQLS = $(wildcard $(PG_MIGRATIONS_DIR)/$(EXTENSION)--*--*.sql)
postgres-docker-build postgres-docker-build-asan postgres-docker-run postgres-docker-run-asan postgres-docker-stop postgres-docker-rebuild \
postgres-docker-debug-build postgres-docker-debug-run postgres-docker-debug-rebuild \
postgres-docker-shell postgres-dev-rebuild postgres-help unittest-pg \
postgres-supabase-build postgres-supabase-rebuild postgres-supabase-run-smoke-test \
postgres-docker-run-smoke-test
postgres-supabase-build postgres-supabase-rebuild postgres-supabase-run-test \
postgres-docker-run-test

# Verify that a cloudsync--<prev>--<curr>.sql upgrade script exists for the
# current CLOUDSYNC_VERSION in src/cloudsync.h. Release-blocking: a missing
Expand Down Expand Up @@ -364,10 +364,12 @@ postgres-supabase-build:
rm -f "$$tmp_dockerfile"; \
exit 1; \
fi; \
echo "Using base image: $$supabase_cli_image"; \
pg_major="$${supabase_cli_image##*:}"; pg_major="$${pg_major%%.*}"; \
case "$$pg_major" in ''|*[!0-9]*) pg_major=17;; esac; \
echo "Using base image: $$supabase_cli_image (PostgreSQL major $$pg_major)"; \
echo "Pulling fresh base image to avoid layer accumulation..."; \
docker pull "$$supabase_cli_image" 2>/dev/null || true; \
docker build --build-arg SUPABASE_POSTGRES_TAG="$(SUPABASE_POSTGRES_TAG)" --build-arg CLOUDSYNC_VERSION="$(CLOUDSYNC_VERSION_FULL)" -f "$$tmp_dockerfile" -t "$$supabase_cli_image" .; \
docker build --build-arg SUPABASE_POSTGRES_TAG="$(SUPABASE_POSTGRES_TAG)" --build-arg PG_MAJOR="$$pg_major" --build-arg CLOUDSYNC_VERSION="$(CLOUDSYNC_VERSION_FULL)" -f "$$tmp_dockerfile" -t "$$supabase_cli_image" .; \
rm -f "$$tmp_dockerfile"; \
echo "Build complete: $$supabase_cli_image"

Expand Down Expand Up @@ -434,8 +436,8 @@ postgres-help:
@echo " postgres-docker-shell - Open bash shell in running container"
@echo " postgres-supabase-build - Build CloudSync into Supabase CLI postgres image"
@echo " postgres-supabase-rebuild - Build CloudSync image and restart Supabase CLI stack"
@echo " postgres-supabase-run-smoke-test - Run smoke test against Supabase CLI database"
@echo " postgres-docker-run-smoke-test - Run smoke test against Docker database"
@echo " postgres-supabase-run-test - Run smoke test against Supabase CLI database"
@echo " postgres-docker-run-test - Run smoke test against Docker database"
@echo ""
@echo "Development:"
@echo " postgres-dev-rebuild - Rebuild extension in running container (fast)"
Expand Down
96 changes: 58 additions & 38 deletions docker/postgresql/Dockerfile.supabase
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
# Build stage for CloudSync extension (match Supabase runtime)
# 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
# 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
# .so is installed on either base. The runtime stage needs no compiler, so
# its userland (apt vs apk) never matters.
#
# 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
FROM public.ecr.aws/supabase/postgres:${SUPABASE_POSTGRES_TAG} AS cloudsync-builder

# Install build dependencies
RUN apt-get update && apt-get install -y \
# Build stage for CloudSync extension (glibc toolchain, matching PG headers)
FROM postgres:${PG_MAJOR} AS cloudsync-builder
ARG PG_MAJOR

# Install build dependencies (PGDG apt repo is preconfigured in this image)
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
ca-certificates \
git \
make \
postgresql-server-dev-${PG_MAJOR} \
&& rm -rf /var/lib/apt/lists/*

# Create directory for extension source
Expand All @@ -19,15 +33,10 @@ COPY modules/ ./modules/
COPY docker/ ./docker/
COPY Makefile .

# Build the CloudSync extension using Supabase's pg_config
ENV CLOUDSYNC_PG_CONFIG=/root/.nix-profile/bin/pg_config
RUN if [ ! -x "$CLOUDSYNC_PG_CONFIG" ]; then \
echo "Error: pg_config not found at $CLOUDSYNC_PG_CONFIG."; \
exit 1; \
fi; \
make postgres-build PG_CONFIG="$CLOUDSYNC_PG_CONFIG"
# Build the CloudSync extension against the PGDG headers
RUN make postgres-build PG_CONFIG=/usr/lib/postgresql/${PG_MAJOR}/bin/pg_config

# Collect build artifacts (avoid installing into the Nix store)
# Collect build artifacts
RUN mkdir -p /tmp/cloudsync-artifacts/lib /tmp/cloudsync-artifacts/extension && \
cp /tmp/cloudsync/cloudsync.so /tmp/cloudsync-artifacts/lib/ && \
cp /tmp/cloudsync/src/postgresql/cloudsync--*.sql /tmp/cloudsync-artifacts/extension/ && \
Expand All @@ -38,52 +47,63 @@ RUN mkdir -p /tmp/cloudsync-artifacts/lib /tmp/cloudsync-artifacts/extension &&
fi

# Runtime image based on Supabase Postgres
ARG SUPABASE_POSTGRES_TAG=17.6.1.071
FROM public.ecr.aws/supabase/postgres:${SUPABASE_POSTGRES_TAG}

# Extension version (derived from src/cloudsync.h by the Makefile and passed in
# as a build arg); used only for the image label.
ARG CLOUDSYNC_VERSION=unknown

# Match builder pg_config path
ENV CLOUDSYNC_PG_CONFIG=/root/.nix-profile/bin/pg_config
# pg_config is resolved dynamically at build time (its path differs between the
# Ubuntu and Alpine Supabase bases). Pass --build-arg CLOUDSYNC_PG_CONFIG=<path>
# to override. Kept an ARG so it does not leak into the built image.
ARG CLOUDSYNC_PG_CONFIG=""

# Install CloudSync extension artifacts
COPY --from=cloudsync-builder /tmp/cloudsync-artifacts/ /tmp/cloudsync-artifacts/
RUN if [ ! -x "$CLOUDSYNC_PG_CONFIG" ]; then \
echo "Error: pg_config not found at $CLOUDSYNC_PG_CONFIG."; \
exit 1; \
RUN set -eu; \
# Resolve pg_config: the Nix profiles the Supabase bases ship first, PATH last
PG_CONFIG="${CLOUDSYNC_PG_CONFIG:-}"; \
if [ -z "$PG_CONFIG" ]; then \
for c in /root/.nix-profile/bin/pg_config /nix/var/nix/profiles/default/bin/pg_config "$(command -v pg_config || true)"; do \
if [ -x "$c" ]; then PG_CONFIG="$c"; break; fi; \
done; \
fi; \
PKGLIBDIR="`$CLOUDSYNC_PG_CONFIG --pkglibdir`"; \
if [ ! -x "$PG_CONFIG" ]; then echo "Error: pg_config not found${PG_CONFIG:+ at $PG_CONFIG}"; exit 1; fi; \
PKGLIBDIR="$(${PG_CONFIG} --pkglibdir)"; \
# Supabase wraps postgres and overrides libdir via NIX_PGLIBDIR.
NIX_PGLIBDIR="`grep -E \"^export NIX_PGLIBDIR\" /usr/bin/postgres | sed -E \"s/.*'([^']+)'.*/\\1/\"`"; \
NIX_PGLIBDIR="$(grep -E '^export NIX_PGLIBDIR' /usr/bin/postgres | sed -E "s/.*'([^']+)'.*/\1/" || true)"; \
if [ -n "$NIX_PGLIBDIR" ]; then PKGLIBDIR="$NIX_PGLIBDIR"; fi; \
SHAREDIR_PGCONFIG="`$CLOUDSYNC_PG_CONFIG --sharedir`"; \
SHAREDIR_PGCONFIG="$(${PG_CONFIG} --sharedir)"; \
SHAREDIR_STD="/usr/share/postgresql"; \
install -d "$PKGLIBDIR" "$SHAREDIR_PGCONFIG/extension" && \
install -m 755 /tmp/cloudsync-artifacts/lib/cloudsync.so "$PKGLIBDIR/" && \
install -d "$PKGLIBDIR" "$SHAREDIR_PGCONFIG/extension"; \
install -m 755 /tmp/cloudsync-artifacts/lib/cloudsync.so "$PKGLIBDIR/"; \
install -m 644 /tmp/cloudsync-artifacts/extension/cloudsync* "$SHAREDIR_PGCONFIG/extension/"; \
if [ "$SHAREDIR_STD" != "$SHAREDIR_PGCONFIG" ]; then \
install -d "$SHAREDIR_STD/extension" && \
if [ "$SHAREDIR_STD" != "$SHAREDIR_PGCONFIG" ] && [ -d "$SHAREDIR_STD" ]; then \
install -d "$SHAREDIR_STD/extension"; \
install -m 644 /tmp/cloudsync-artifacts/extension/cloudsync* "$SHAREDIR_STD/extension/"; \
fi
fi; \
rm -rf /tmp/cloudsync-artifacts

# Verify installation
RUN if [ ! -x "$CLOUDSYNC_PG_CONFIG" ]; then \
echo "Error: pg_config not found at $CLOUDSYNC_PG_CONFIG."; \
exit 1; \
RUN set -eu; \
PG_CONFIG="${CLOUDSYNC_PG_CONFIG:-}"; \
if [ -z "$PG_CONFIG" ]; then \
for c in /root/.nix-profile/bin/pg_config /nix/var/nix/profiles/default/bin/pg_config "$(command -v pg_config || true)"; do \
if [ -x "$c" ]; then PG_CONFIG="$c"; break; fi; \
done; \
fi; \
NIX_PGLIBDIR="`grep -E \"^export NIX_PGLIBDIR\" /usr/bin/postgres | sed -E \"s/.*'([^']+)'.*/\\1/\"`"; \
echo "Verifying CloudSync extension installation..." && \
if [ ! -x "$PG_CONFIG" ]; then echo "Error: pg_config not found${PG_CONFIG:+ at $PG_CONFIG}"; exit 1; fi; \
NIX_PGLIBDIR="$(grep -E '^export NIX_PGLIBDIR' /usr/bin/postgres | sed -E "s/.*'([^']+)'.*/\1/" || true)"; \
echo "Verifying CloudSync extension installation..."; \
if [ -n "$NIX_PGLIBDIR" ]; then \
ls -la "$NIX_PGLIBDIR/cloudsync.so"; \
else \
ls -la "`$CLOUDSYNC_PG_CONFIG --pkglibdir`/cloudsync.so"; \
fi && \
ls -la "`$CLOUDSYNC_PG_CONFIG --sharedir`/extension/cloudsync"* && \
ls -la "$(${PG_CONFIG} --pkglibdir)/cloudsync.so"; \
fi; \
ls -la "$(${PG_CONFIG} --sharedir)/extension/cloudsync"*; \
if [ -d "/usr/share/postgresql/extension" ]; then \
ls -la /usr/share/postgresql/extension/cloudsync*; \
fi && \
fi; \
echo "CloudSync extension installed successfully"

# Expose PostgreSQL port
Expand Down
Loading