🛟

libsql-serverのセルフホスティング

2024/12/18に公開

LitestreamのようなSQLiteファイルのレプリケーション用途でlibsqlを使いたいので、libsql-serverのセルフホスティングについて調査した。

libsql-serverとは

  • libsqlというSQLiteのフォークプロジェクトのサーバー実装
  • Tursoの基礎技術をオープンソース化したもの
  • クライアント/サーバー型のSQLiteデータベースを作ることができる

https://docs.turso.tech/libsql

サーバー起動コマンド

Dockerイメージが提供されている。

docker run --name some-sqld  -p 8080:8080 -ti \
    -e SQLD_NODE=primary \
    --platform linux/amd64 \
    ghcr.io/tursodatabase/libsql-server:latest

           _     _
 ___  __ _| | __| |
/ __|/ _` | |/ _` |
\__ \ (_| | | (_| |
|___/\__, |_|\__,_|
        |_|

Welcome to sqld!

version: 0.24.30
commit SHA: 58b016ab72eea7fc0118009fb03195449f202edc
build date: 2024-12-17

This software is in BETA version.
If you encounter any bug, please open an issue at https://github.com/tursodatabase/libsql/issues

config:
        - mode: primary (0.0.0.0:5001)
        - database path: iku.db
        - extensions path: <disabled>
        - listening for HTTP requests on: 0.0.0.0:8080
        - grpc_tls: no
2024-12-18T10:28:43.642626Z  INFO sqld: listening for incoming user HTTP connection on 0.0.0.0:8080
2024-12-18T10:28:43.644701Z  INFO sqld: listening for incoming gRPC connection on 0.0.0.0:5001
2024-12-18T10:28:43.703993Z  INFO restore: libsql_server::namespace::meta_store: restoring meta store
2024-12-18T10:28:43.705025Z  INFO restore: libsql_server::namespace::meta_store: meta store restore completed
2024-12-18T10:28:43.708396Z  INFO libsql_server: Server sending heartbeat to URL <not supplied> every 30s
2024-12-18T10:28:43.725623Z  INFO libsql_server::rpc: serving internal rpc server without tls

libSQLに対応したクライアントを使って接続することができる。GUIツールのリストが以下にある

https://docs.turso.tech/local-development#connecting-a-gui

クライアント接続

Node.jsからはnpmで公開されているlibsql-clientを利用して接続することができる。

url: "http://localhost:8080"を指定して接続する。
実行のたびにランダムな名前を取得してデータベースに保存するサンプルコードは以下の通り。

index.mjs
import { createClient } from "@libsql/client";

const client = createClient({
    url: "http://localhost:8080",
});

async function getRandomName() {
    const response = await fetch('https://randomuser.me/api/');
    const data = await response.json();
    return `${data.results[0].name.first} ${data.results[0].name.last}`;
}

await client.batch(
    [
        "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)",
        {
            sql: "INSERT INTO users(name) VALUES (?)",
            args: [await getRandomName()],
        },
    ],
    "write",
);

const users = await client.execute("SELECT * FROM users");
console.log(users);

リードレプリカ

クライアント作成オプションでurlをローカルのファイルパスにして、syncUrlを指定することでリードレプリカを作成することができる。

index.mjs
const client = createClient({
-    url: "http://localhost:8080",
+    url: "file:local.db",
+    syncUrl: "http://localhost:8080/",
});

local.dbファイルが作成され、データベースの内容がWALで同期される。
読み込み専用のデータベースとして利用することができる。

まとめ

libsql-serverを使用することで、SQLiteデータベースをクライアント/サーバー型で運用できる

このあとは

  • S3 bottomless replicationでデータベースのバックアップを取る
  • libSQLに対応したORM(Prisma, Drizzle)を使ってアプリケーションを作成する
  • エンドポイントを公開する場合は認証を設定する

参考

Discussion