You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+13-7Lines changed: 13 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,7 +5,7 @@
5
5
6
6
<h1>SQLite-Sync</h1>
7
7
<p><strong>Offline-first sync for SQLite, powered by CRDTs.</strong><br>
8
-
Local writes, conflict-free merges, real-time collaboration across devices. Sync to SQLite Cloud, PostgreSQL, or Supabase — no central coordinator required.</p>
8
+
Local writes, conflict-free merges, real-time collaboration across devices. Sync to SQLite Cloud, <ahref="./docs/postgresql/quickstarts/postgres.md">PostgreSQL</a>, or <ahref="./docs/postgresql/quickstarts/supabase-self-hosted.md">Supabase</a> — no central coordinator required.</p>
> **Need a sync backend?** Plug into any PostgreSQL or Supabase instance, or use **[SQLite Cloud CloudSync](https://www.sqlite.ai/pricing)** — managed device sync with auth, ACL, and a free tier for up to 3 devices.
35
+
> **Need a sync backend?** Plug into any [PostgreSQL](./docs/postgresql/quickstarts/postgres.md) or [self-hosted Supabase](./docs/postgresql/quickstarts/supabase-self-hosted.md) instance, or use **[SQLite Cloud CloudSync](https://www.sqlite.ai/pricing)**
**SQLite Sync** is a multi-platform extension that turns any SQLite database into a **conflict-free, offline-first replica** that syncs automatically with **[SQLite Cloud](https://sqlitecloud.io/)** nodes, **PostgreSQL** servers, and **Supabase** instances. One function call is all it takes: no backend to build, no sync protocol to implement.
43
+
**SQLite Sync** is a multi-platform extension that turns any SQLite database into a **conflict-free, offline-first replica** that syncs automatically with **[SQLite Cloud](https://sqlitecloud.io/)** nodes, **[PostgreSQL](./docs/postgresql/quickstarts/postgres.md)** servers, and **[Supabase](./docs/postgresql/quickstarts/supabase-self-hosted.md)** instances. One function call is all it takes: no backend to build, no sync protocol to implement.
44
44
45
45
Built on **CRDT** (Conflict-free Replicated Data Types), it guarantees:
46
46
@@ -91,7 +91,7 @@ Built on **CRDT** (Conflict-free Replicated Data Types), it guarantees:
91
91
92
92
### 1. Install
93
93
94
-
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):
94
+
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):
95
95
96
96
| Platform | Install |
97
97
|----------|---------|
@@ -131,6 +131,8 @@ SELECT * FROM tasks;
131
131
132
132
### 4. Sync with the cloud
133
133
134
+
The example below uses SQLite Cloud CloudSync. If you are wiring up a self-hosted backend instead, use the [PostgreSQL quick start](./docs/postgresql/quickstarts/postgres.md) or the [self-hosted Supabase quick start](./docs/postgresql/quickstarts/supabase-self-hosted.md).
135
+
134
136
```sql
135
137
-- Connect to your SQLite Cloud managed database
136
138
-- (get the managed database ID from the OffSync page on the SQLite Cloud dashboard)
@@ -188,7 +190,7 @@ SELECT cloudsync_terminate();
188
190
189
191
Back on Device A, calling `cloudsync_network_sync()` will pull Device B's changes. The CRDT engine ensures all devices converge to the same data, automatically, with no conflicts.
190
192
191
-
> **Note:** every device participating in the same sync must create **the same set of tables with the same structure** and initialize each one with `cloudsync_init()`. sqlite-sync derives a schema hash from the synced tables, and the server rejects payloads whose hash it does not recognize. For multi-tenant setups where each client should see only a subset of rows, use a shared schema with a tenant/scope column and enforce isolation with [Row-Level Security](./docs/row-level-security.md) — do not give each client a different table.
193
+
> **Note:** every device participating in the same sync must create **the same set of tables with the same structure** and initialize each one with `cloudsync_init()`. sqlite-sync derives a schema hash from the synced tables, and the server rejects payloads whose hash it does not recognize. For multi-tenant setups where each client should see only a subset of rows, use a shared schema with a tenant/scope column and enforce isolation with [RLS Overview](./docs/rls-overview.md) — do not give each client a different table.
192
194
193
195
## Block-Level LWW
194
196
@@ -214,21 +216,25 @@ With SQLite Cloud's RLS, a single shared cloud database serves all users while e
214
216
- One database, multiple tenants, no per-user database provisioning.
215
217
- Each client syncs only authorized rows, minimal bandwidth and storage.
216
218
217
-
See the full guide: **[Row-Level Security Documentation](./docs/row-level-security.md)**.
219
+
See the full guide: **[RLS Overview](./docs/rls-overview.md)**.
218
220
219
221
## Documentation
220
222
221
223
-**[API Reference](./API.md)**: all functions, parameters, and examples
-**[Custom Network Layer](./docs/internal/network.md)**: replace the built-in libcurl networking
228
232
-**[Examples](./examples/)**: complete walkthroughs (todo app, sport tracker, Swift multiplatform)
229
233
230
234
## SQLite Cloud Setup
231
235
236
+
If you are not using SQLite Cloud as the sync backend, see the [self-hosted PostgreSQL quick start](./docs/postgresql/quickstarts/postgres.md) or the [self-hosted Supabase quick start](./docs/postgresql/quickstarts/supabase-self-hosted.md).
237
+
232
238
1. Sign up at [SQLite Cloud](https://sqlitecloud.io/) and create a project.
233
239
2. Create a database and your tables in the [dashboard](https://dashboard.sqlitecloud.io/).
234
240
3. Enable synchronization: click **"OffSync"** for your database and select the tables to sync.
Copy file name to clipboardExpand all lines: docs/internal/postgres-flyio.md
+104Lines changed: 104 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -836,6 +836,108 @@ docker compose pull db
836
836
docker compose up -d db
837
837
```
838
838
839
+
### Update CloudSync from a GitHub Actions PostgreSQL artifact
840
+
841
+
If you already run the Dockerized PostgreSQL setup from this guide and want to test a newer CloudSync PostgreSQL build without rebuilding and pushing a custom image, you can copy the packaged extension files into the running `db` container.
842
+
843
+
1. Confirm the running PostgreSQL major version and current CloudSync version:
docker compose exec db psql -U postgres -d postgres -c "SELECT name, default_version, installed_version FROM pg_available_extensions WHERE name = 'cloudsync';"
850
+
uname -m
851
+
```
852
+
853
+
For a standard Fly Ubuntu VM running PostgreSQL 17 on x86_64, download the artifact named:
854
+
855
+
```text
856
+
cloudsync-postgresql17-linux-x86_64
857
+
```
858
+
859
+
2. Download the artifact from the GitHub Actions run on your local machine while signed into GitHub, then upload the zip to the VM:
860
+
861
+
```bash
862
+
fly ssh sftp shell --app <your-app-name>
863
+
```
864
+
865
+
At the SFTP prompt:
866
+
867
+
```text
868
+
cd /data
869
+
put /absolute/path/to/cloudsync-postgresql17-linux-x86_64.zip cloudsync-postgresql17-linux-x86_64.zip
870
+
```
871
+
872
+
3. SSH back into the VM, extract the package, and verify the files:
873
+
874
+
```bash
875
+
fly ssh console --app <your-app-name>
876
+
877
+
apt-get update
878
+
apt-get install -y unzip
879
+
880
+
cd /data
881
+
mkdir -p cloudsync-package
882
+
cd cloudsync-package
883
+
cp ../cloudsync-postgresql17-linux-x86_64.zip .
884
+
unzip -o cloudsync-postgresql17-linux-x86_64.zip
885
+
ls -1
886
+
```
887
+
888
+
The extracted package should contain:
889
+
890
+
-`cloudsync.so`
891
+
-`cloudsync.control`
892
+
-`cloudsync--<version>.sql`
893
+
- any `cloudsync--<from>--<to>.sql` upgrade scripts
894
+
895
+
4. Copy those files into the running PostgreSQL container:
docker exec cloudsync-postgres psql -U postgres -d postgres -c "SELECT name, default_version, installed_version FROM pg_available_extensions WHERE name = 'cloudsync';"
931
+
```
932
+
933
+
For example, after a successful `1.0.16 -> 1.1.0` upgrade you should see:
934
+
935
+
-`cloudsync_version()` returns `1.1.0`
936
+
-`default_version = 1.1`
937
+
-`installed_version = 1.1`
938
+
939
+
> **Important:** this is an in-place container modification. It survives a container restart, but it does **not** survive recreating the container from the original image. If you later run `docker compose pull`, change the image tag, or recreate `db`, you will lose the manually copied files unless the image itself already includes that newer CloudSync build.
940
+
839
941
### View logs
840
942
841
943
```bash
@@ -852,10 +954,12 @@ docker compose logs -f auth # Auth server only
852
954
|---------|----------|
853
955
|`fractional_indexing.h: No such file or directory`| Run `git submodule update --init --recursive` before building |
854
956
|`cloudsync_version()` not found | Init scripts only run on first start. Run `CREATE EXTENSION IF NOT EXISTS cloudsync;` manually |
957
+
|`unzip: command not found`| Install it on the Fly VM first: `apt-get update && apt-get install -y unzip`|
855
958
| Auth server won't start | Check `docker compose logs auth`. Ensure `npm install` was run in `auth-server/`|
856
959
| Token verification fails (HS256) | Ensure `JWT_SECRET` matches exactly — CloudSync uses the raw string, not base64-decoded |
857
960
| Token verification fails (JWKS) | Ensure CloudSync can reach the JWKS endpoint and `JWT_ISSUER` matches the `ISSUER` env var |
858
961
| JWKS keys lost after restart | The JWKS server generates new keys on each start. For production, persist keys to a volume |
859
962
| Docker commands not found after VM restart | Run `/data/startup.sh` — Fly VM root filesystem resets on stop/start |
860
963
|`fuse-overlayfs` not working | Install it: `apt-get install -y fuse-overlayfs`|
964
+
| Manual artifact upgrade disappears after `docker compose up` recreation | This method only patches the running container. Rebuild or switch to an image that already contains the new CloudSync build for a durable upgrade. |
861
965
| Can't connect to Postgres from outside Fly | Use `fly proxy 5432:5432 -a <your-app-name>`|
2. Execute the schema with [sport-tracker-schema-postgres.sql](../../examples/sport-tracker-app/sport-tracker-schema-postgres.sql).
16
+
2. Execute the schema with [sport-tracker-schema-postgres.sql](../../../examples/sport-tracker-app/sport-tracker-schema-postgres.sql).
17
17
3. Enable CloudSync for all tables on the remote database with:
18
18
```sql
19
19
CREATE EXTENSION IF NOT EXISTS cloudsync;
@@ -40,4 +40,4 @@ npm run dev
40
40
41
41
### Demo
42
42
43
-
Continue reading on the official [README](https://github.com/sqliteai/sqlite-sync/blob/main/examples/sport-tracker-app/README.md#demo-use-case-multi-user-sync-scenario).
43
+
Continue reading on the official [README](https://github.com/sqliteai/sqlite-sync/blob/main/examples/sport-tracker-app/README.md#demo-use-case-multi-user-sync-scenario).
Copy file name to clipboardExpand all lines: docs/rls-overview.md
+4-2Lines changed: 4 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,9 @@
1
-
# Row-Level Security
1
+
# RLS Overview
2
2
3
3
SQLite Sync supports **Row-Level Security (RLS)** through the underlying [SQLite Cloud](https://sqlitecloud.io/) infrastructure. RLS allows you to use a **single shared cloud database** while each client only sees and modifies its own data. Policies are enforced on the server, so the security boundary is at the database level, not in application code.
4
4
5
+
> **Using self-hosted PostgreSQL or Supabase?** Start with the backend-specific [RLS Reference](./postgresql/reference/rls.md) for CloudSync apply behavior, PostgreSQL roles and grants, Supabase notes, and troubleshooting.
6
+
5
7
## How It Works
6
8
7
9
- Control not just who can read or write a table, but **which specific rows** they can access.
@@ -44,6 +46,6 @@ CREATE TABLE users (
44
46
);
45
47
```
46
48
47
-
For more schema guidelines, see [Database Schema Recommendations](./schema.md).
49
+
For more schema guidelines, see [Database Schema Recommendations](./schema.md). If you are running a self-hosted backend, also see the PostgreSQL/Supabase [RLS Reference](./postgresql/reference/rls.md).
48
50
49
51
For full RLS documentation, see the [SQLite Cloud RLS documentation](https://docs.sqlitecloud.io/docs/rls).
Copy file name to clipboardExpand all lines: docs/schema.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,7 +16,7 @@ sqlite-sync computes a **schema hash** from the synced tables and includes it in
16
16
cloudsync operation failed: Cannot apply the received payload because the schema hash is unknown <hash>
17
17
```
18
18
19
-
If you need different clients to see different subsets of data (for example, per-tenant or per-workspace isolation), do **not** give each client a different table. Instead, use a single shared schema and scope the data with a column such as `tenant_id` or `workspace_id`, then enforce isolation server-side with [Row-Level Security](./row-level-security.md).
19
+
If you need different clients to see different subsets of data (for example, per-tenant or per-workspace isolation), do **not** give each client a different table. Instead, use a single shared schema and scope the data with a column such as `tenant_id` or `workspace_id`, then enforce isolation server-side with [RLS Overview](./rls-overview.md).
0 commit comments