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
120 changes: 114 additions & 6 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ jobs:

postgres-build:
runs-on: ${{ matrix.os }}
name: postgresql-${{ matrix.name }}-${{ matrix.arch }} build
name: postgresql${{ matrix.postgres_version }}-${{ matrix.name }}-${{ matrix.arch }} build
timeout-minutes: 15
strategy:
fail-fast: false
Expand All @@ -286,15 +286,35 @@ jobs:
- os: ubuntu-22.04
arch: x86_64
name: linux
postgres_version: '17'
- os: ubuntu-22.04
arch: x86_64
name: linux
postgres_version: '15'
- os: ubuntu-22.04-arm
arch: arm64
name: linux
postgres_version: '17'
- os: ubuntu-22.04-arm
arch: arm64
name: linux
postgres_version: '15'
- os: macos-15
arch: arm64
name: macos
postgres_version: '17'
- os: macos-15
arch: arm64
name: macos
postgres_version: '15'
- os: macos-15
arch: x86_64
name: macos
postgres_version: '17'
- os: macos-15
arch: x86_64
name: macos
postgres_version: '15'
steps:

- uses: actions/checkout@v4.2.2
Expand All @@ -307,23 +327,23 @@ jobs:
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg
sudo apt-get update
sudo apt-get install -y postgresql-server-dev-17
sudo apt-get install -y postgresql-server-dev-${{ matrix.postgres_version }}

- name: macos install postgresql
if: matrix.name == 'macos'
run: brew install postgresql@17 gettext
run: brew install postgresql@${{ matrix.postgres_version }} gettext

- name: build and package postgresql extension (linux)
if: matrix.name == 'linux'
run: make postgres-package
run: make postgres-package PG_CONFIG=/usr/lib/postgresql/${{ matrix.postgres_version }}/bin/pg_config

- name: build and package postgresql extension (macos)
if: matrix.name == 'macos'
run: make postgres-package PG_CONFIG=$(brew --prefix postgresql@17)/bin/pg_config PG_EXTRA_CFLAGS="-I$(brew --prefix gettext)/include ${{ matrix.arch == 'x86_64' && '-arch x86_64' || '' }}"
run: make postgres-package PG_CONFIG=$(brew --prefix postgresql@${{ matrix.postgres_version }})/bin/pg_config PG_EXTRA_CFLAGS="-I$(brew --prefix gettext)/include ${{ matrix.arch == 'x86_64' && '-arch x86_64' || '' }}"

- uses: actions/upload-artifact@v4.6.2
with:
name: cloudsync-postgresql-${{ matrix.name }}-${{ matrix.arch }}
name: cloudsync-postgresql${{ matrix.postgres_version }}-${{ matrix.name }}-${{ matrix.arch }}
path: dist/postgresql/
if-no-files-found: error

Expand Down Expand Up @@ -546,6 +566,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` or `:15`

---

Expand All @@ -555,3 +577,89 @@ jobs:
cloudsync-*-${{ steps.tag.outputs.version }}.*
CloudSync-*-${{ steps.tag.outputs.version }}.*
make_latest: true

docker-publish:
runs-on: ubuntu-22.04
name: docker ${{ matrix.image }} pg${{ matrix.pg_major }}
needs: [release]
if: github.ref == 'refs/heads/main'

env:
DOCKERHUB_ORG: sqlitecloud

strategy:
fail-fast: false
matrix:
include:
- image: sqlite-sync-postgres
pg_major: '17'
dockerfile: docker/postgresql/Dockerfile.release
- image: sqlite-sync-postgres
pg_major: '15'
dockerfile: docker/postgresql/Dockerfile.release
- image: sqlite-sync-supabase
pg_major: '17'
dockerfile: docker/postgresql/Dockerfile.supabase.release
supabase_tag: '17.6.1.071'
- image: sqlite-sync-supabase
pg_major: '15'
dockerfile: docker/postgresql/Dockerfile.supabase.release
supabase_tag: '15.8.1.085'

steps:

- uses: actions/checkout@v4.2.2
with:
submodules: true

- name: get cloudsync version
id: version
run: echo "version=$(make version)" >> $GITHUB_OUTPUT

- uses: docker/setup-qemu-action@v3

- uses: docker/setup-buildx-action@v3

- uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: set docker tags and build args (standalone)
if: matrix.image == 'sqlite-sync-postgres'
id: standalone
run: |
VERSION=${{ steps.version.outputs.version }}
PG=${{ matrix.pg_major }}
IMAGE=${{ env.DOCKERHUB_ORG }}/${{ matrix.image }}
{
echo "tags=${IMAGE}:${PG},${IMAGE}:${PG}-${VERSION}"
echo "build_args<<EOF"
echo "POSTGRES_TAG=${PG}"
echo "CLOUDSYNC_VERSION=${VERSION}"
echo "EOF"
} >> $GITHUB_OUTPUT

- name: set docker tags and build args (supabase)
if: matrix.image == 'sqlite-sync-supabase'
id: supabase
run: |
VERSION=${{ steps.version.outputs.version }}
IMAGE=${{ env.DOCKERHUB_ORG }}/${{ matrix.image }}
SUPABASE_TAG=${{ matrix.supabase_tag }}
{
echo "tags=${IMAGE}:${{ matrix.pg_major }},${IMAGE}:${{ matrix.pg_major }}-${VERSION},${IMAGE}:${SUPABASE_TAG}"
echo "build_args<<EOF"
echo "SUPABASE_POSTGRES_TAG=${SUPABASE_TAG}"
echo "CLOUDSYNC_VERSION=${VERSION}"
echo "EOF"
} >> $GITHUB_OUTPUT

- uses: docker/build-push-action@v6
with:
context: .
file: ${{ matrix.dockerfile }}
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ matrix.image == 'sqlite-sync-postgres' && steps.standalone.outputs.tags || steps.supabase.outputs.tags }}
build-args: ${{ matrix.image == 'sqlite-sync-postgres' && steps.standalone.outputs.build_args || steps.supabase.outputs.build_args }}
2 changes: 1 addition & 1 deletion API.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ When designing your database schema for SQLite Sync, follow these essential requ
- **Foreign Key Compatibility**: Be aware of potential conflicts during CRDT merge operations and RLS policy interactions.
- **Trigger Compatibility**: Triggers may cause duplicate operations or be called multiple times due to column-by-column processing.

For comprehensive guidelines, see the [Database Schema Recommendations](docs/SCHEMA.md).
For comprehensive guidelines, see the [Database Schema Recommendations](docs/schema.md).

The function supports three overloads:
- `cloudsync_init(table_name)`: Uses the default 'cls' CRDT algorithm.
Expand Down
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Built on **CRDT** (Conflict-free Replicated Data Types), it guarantees:

### 1. Install

Download a pre-built binary from the [Releases](https://github.com/sqliteai/sqlite-sync/releases) page, or install a platform package (see [full installation guide](./docs/INSTALLATION.md) for platform-specific code examples):
Download a pre-built binary from the [Releases](https://github.com/sqliteai/sqlite-sync/releases) page, or install a platform package (see [full installation guide](./docs/installation.md) for platform-specific code examples):

| Platform | Install |
|----------|---------|
Expand Down Expand Up @@ -165,7 +165,7 @@ SELECT cloudsync_init('notes');
SELECT cloudsync_set_column('notes', 'body', 'algo', 'block');
```

Now two agents (or devices) can edit different lines of the same note, and both edits are preserved after sync. See the full guide: **[Block-Level LWW Documentation](./docs/BLOCK-LWW.md)**.
Now two agents (or devices) can edit different lines of the same note, and both edits are preserved after sync. See the full guide: **[Block-Level LWW Documentation](./docs/block-lww.md)**.

## Row-Level Security

Expand All @@ -174,16 +174,16 @@ With SQLite Cloud's RLS, a single shared cloud database serves all users while e
- One database, multiple tenants, no per-user database provisioning.
- Each client syncs only authorized rows, minimal bandwidth and storage.

See the full guide: **[Row-Level Security Documentation](./docs/ROW-LEVEL-SECURITY.md)**.
See the full guide: **[Row-Level Security Documentation](./docs/row-level-security.md)**.

## Documentation

- **[API Reference](./API.md)**: all functions, parameters, and examples
- **[Installation Guide](./docs/INSTALLATION.md)**: platform-specific setup (Swift, Android, Expo, React Native, Flutter, WASM)
- **[Block-Level LWW Guide](./docs/BLOCK-LWW.md)**: line-level text merge for markdown and documents
- **[Row-Level Security Guide](./docs/ROW-LEVEL-SECURITY.md)**: multi-tenant access control with server-enforced policies
- **[Database Schema Recommendations](./docs/SCHEMA.md)**: primary keys, constraints, foreign keys, triggers
- **[Custom Network Layer](./docs/Network.md)**: replace the built-in libcurl networking
- **[Installation Guide](./docs/installation.md)**: platform-specific setup (Swift, Android, Expo, React Native, Flutter, WASM)
- **[Block-Level LWW Guide](./docs/block-lww.md)**: line-level text merge for markdown and documents
- **[Row-Level Security Guide](./docs/row-level-security.md)**: multi-tenant access control with server-enforced policies
- **[Database Schema Recommendations](./docs/schema.md)**: primary keys, constraints, foreign keys, triggers
- **[Custom Network Layer](./docs/internal/network.md)**: replace the built-in libcurl networking
- **[Examples](./examples/)**: complete walkthroughs (todo app, sport tracker, Swift multiplatform)

## SQLite Cloud Setup
Expand Down
50 changes: 50 additions & 0 deletions docker/postgresql/Dockerfile.release
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# PostgreSQL with pre-compiled CloudSync (sqlite-sync) extension
#
# Usage:
# docker build \
# --build-arg POSTGRES_TAG=17 \
# --build-arg CLOUDSYNC_VERSION=1.0.1 \
# -t sqlite-sync-postgres:17 \
# -f docker/postgresql/Dockerfile.release .
#
# Or pull the pre-built image from Docker Hub:
# docker pull sqlitecloud/sqlite-sync-postgres:17
#

ARG POSTGRES_TAG=17
FROM postgres:${POSTGRES_TAG}

ARG CLOUDSYNC_VERSION
ARG TARGETARCH

# Map Docker platform arch to artifact arch
RUN case "${TARGETARCH}" in \
amd64) ARCH="x86_64" ;; \
arm64) ARCH="arm64" ;; \
*) echo "Unsupported architecture: ${TARGETARCH}" && exit 1 ;; \
esac && \
apt-get update && apt-get install -y --no-install-recommends curl ca-certificates && \
ASSET="cloudsync-postgresql${PG_MAJOR}-linux-${ARCH}-${CLOUDSYNC_VERSION}.tar.gz" && \
URL="https://github.com/sqliteai/sqlite-sync/releases/download/${CLOUDSYNC_VERSION}/${ASSET}" && \
echo "Downloading ${URL}" && \
curl -fSL "${URL}" -o /tmp/cloudsync.tar.gz && \
mkdir -p /tmp/cloudsync && \
tar -xzf /tmp/cloudsync.tar.gz -C /tmp/cloudsync && \
install -m 755 /tmp/cloudsync/cloudsync.so "$(pg_config --pkglibdir)/" && \
install -m 644 /tmp/cloudsync/cloudsync--1.0.sql "$(pg_config --sharedir)/extension/" && \
install -m 644 /tmp/cloudsync/cloudsync.control "$(pg_config --sharedir)/extension/" && \
rm -rf /tmp/cloudsync /tmp/cloudsync.tar.gz && \
apt-get purge -y curl && apt-get autoremove -y && rm -rf /var/lib/apt/lists/*

# Verify installation
RUN ls -la "$(pg_config --pkglibdir)/cloudsync.so" && \
ls -la "$(pg_config --sharedir)/extension/cloudsync"* && \
echo "CloudSync extension installed successfully"

# Copy initialization script (auto-creates the extension on first start)
COPY docker/postgresql/init.sql /docker-entrypoint-initdb.d/

EXPOSE 5432

LABEL org.sqliteai.cloudsync.description="PostgreSQL with CloudSync CRDT extension" \
org.opencontainers.image.source="https://github.com/sqliteai/sqlite-sync"
72 changes: 72 additions & 0 deletions docker/postgresql/Dockerfile.supabase.release
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Supabase PostgreSQL with pre-compiled CloudSync (sqlite-sync) extension
#
# Usage:
# docker build \
# --build-arg SUPABASE_POSTGRES_TAG=15.8.1.085 \
# --build-arg CLOUDSYNC_VERSION=1.0.1 \
# -f docker/postgresql/Dockerfile.supabase.release \
# -t my-cloudsync-supabase-postgres .
#
# Or pull the pre-built image from Docker Hub:
# docker pull sqlitecloud/sqlite-sync-supabase:15
#

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

ARG CLOUDSYNC_VERSION
ARG TARGETARCH

ENV CLOUDSYNC_PG_CONFIG=/root/.nix-profile/bin/pg_config

# Download pre-compiled extension and install into Supabase's Nix layout
RUN case "${TARGETARCH}" in \
amd64) ARCH="x86_64" ;; \
arm64) ARCH="arm64" ;; \
*) echo "Unsupported architecture: ${TARGETARCH}" && exit 1 ;; \
esac && \
# Derive PG major version from pg_config
PG_MAJOR=$(${CLOUDSYNC_PG_CONFIG} --version | sed 's/[^0-9]*//' | cut -d. -f1) && \
apt-get update && apt-get install -y --no-install-recommends curl ca-certificates && \
ASSET="cloudsync-postgresql${PG_MAJOR}-linux-${ARCH}-${CLOUDSYNC_VERSION}.tar.gz" && \
URL="https://github.com/sqliteai/sqlite-sync/releases/download/${CLOUDSYNC_VERSION}/${ASSET}" && \
echo "Downloading ${URL}" && \
curl -fSL "${URL}" -o /tmp/cloudsync.tar.gz && \
mkdir -p /tmp/cloudsync && \
tar -xzf /tmp/cloudsync.tar.gz -C /tmp/cloudsync && \
# Resolve Supabase's Nix library path
PKGLIBDIR="$(${CLOUDSYNC_PG_CONFIG} --pkglibdir)" && \
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_STD="/usr/share/postgresql" && \
install -d "$PKGLIBDIR" "$SHAREDIR_PGCONFIG/extension" && \
install -m 755 /tmp/cloudsync/cloudsync.so "$PKGLIBDIR/" && \
install -m 644 /tmp/cloudsync/cloudsync--1.0.sql /tmp/cloudsync/cloudsync.control "$SHAREDIR_PGCONFIG/extension/" && \
if [ "$SHAREDIR_STD" != "$SHAREDIR_PGCONFIG" ]; then \
install -d "$SHAREDIR_STD/extension" && \
install -m 644 /tmp/cloudsync/cloudsync--1.0.sql /tmp/cloudsync/cloudsync.control "$SHAREDIR_STD/extension/"; \
fi && \
rm -rf /tmp/cloudsync /tmp/cloudsync.tar.gz && \
apt-get purge -y curl && apt-get autoremove -y && rm -rf /var/lib/apt/lists/*

# Verify installation
RUN 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"* && \
if [ -d "/usr/share/postgresql/extension" ]; then \
ls -la /usr/share/postgresql/extension/cloudsync*; \
fi && \
echo "CloudSync extension installed successfully"

EXPOSE 5432

WORKDIR /

LABEL org.sqliteai.cloudsync.description="Supabase PostgreSQL with CloudSync CRDT extension" \
org.opencontainers.image.source="https://github.com/sqliteai/sqlite-sync"
2 changes: 1 addition & 1 deletion docs/ROW-LEVEL-SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,6 @@ CREATE TABLE users (
);
```

For more schema guidelines, see [Database Schema Recommendations](./SCHEMA.md).
For more schema guidelines, see [Database Schema Recommendations](./schema.md).

For full RLS documentation, see the [SQLite Cloud RLS documentation](https://docs.sqlitecloud.io/docs/rls).
File renamed without changes.
File renamed without changes.
File renamed without changes.
8 changes: 4 additions & 4 deletions docs/postgresql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Additional CRDTs can be implemented if needed, though LWW covers most real-world

### Observability

* Metrics dashboard available in [grafana-dashboard.json](grafana-dashboard.json)
* Metrics dashboard available in [grafana-dashboard.json](../internal/grafana-dashboard.json)


# Postgres Sync
Expand Down Expand Up @@ -97,6 +97,6 @@ The PostgreSQL integration is actively evolving. Current limitations include:
* **Beta Status**: While extensively tested, the PostgreSQL sync stack should currently be considered **beta software**. Please report any issues; we are committed to resolving them quickly.

# Next
* [CLIENT](CLIENT.md) installation and setup
* [SUPABASE](SUPABASE.md) configuration and setup
* [SPORT-TRACKER APP](SPORT_APP_README_SUPABASE.md) demo web app based on SQLite Sync WASM
* [CLIENT](client.md) installation and setup
* [SUPABASE](integrations/supabase.md) configuration and setup
* [SPORT-TRACKER APP](examples/sport-app-supabase.md) demo web app based on SQLite Sync WASM
Loading
Loading