Running SQLite Apps on Docker and Kubernetes with Litestream

Aug 31, 2026 01:05 AM - 1 hour ago 2

OpenRun is an open-source, self-hosted GitOps level for deploying web apps and soul devices connected Docker, Podman, aliases Kubernetes. It provides authentication, authorization, auditing, and RBAC without requiring changes to the application.

OpenRun now has built-in Litestream support for SQLite apps. App databases are continuously replicated to AWS S3 aliases S3-compatible entity retention specified arsenic Cloudflare R2, MinIO and SeaweedFS. Restore is automatic: erstwhile OpenRun detects an quiet aliases recreated app volume, it restores the database from the replica earlier starting the app. The aforesaid setup useful connected a azygous node pinch Docker/Podman and connected Kubernetes.

The consequence is that exertion developers usage SQLite usually without having to instal Litestream, configure entity storage, modify their instrumentality image, aliases instrumentality reconstruct logic.

Background

SQLite is simply a awesome fresh for soul devices and mini web apps: the database is file-backed, sounds are fast, and location is nary abstracted database server to operate. Litestream continuously replicates SQLite changes to entity storage, providing durable off-node backups and point-in-time recovery.

Without level integration, however, you still request to deploy Litestream alongside the app, configure the replica, and grip database restoration during startup.

OpenRun moves that operational activity into the platform. Litestream settings are defined erstwhile successful the server configuration, while OpenRun manages replication and restoration extracurricular the app container. The app image stays unchanged, and caller SQLite apps tin usage replication without immoderate Litestream-specific setup.

Deploying a SQLite App

Define Litestream erstwhile successful the OpenRun server configuration:

openrun.toml

[litestream.mainbackup] bucket = "openrun-backups" region = "us-east-1" access_key_id = '{{secret_from "env" "LITESTREAM_KEY_ID"}}' secret_access_key = '{{secret_from "env" "LITESTREAM_KEY"}}'

Then create a SQLite work that references it and hindrance apps to the service:

openrun work create sqlite/main --is-default --config litestream_config=mainbackup openrun app create --bind sqlite --approve github.com/example/notes-app /notes

The aforesaid app tin beryllium defined declaratively. Put the meaning successful an use record alongside your different configuration successful Git:

apps.star

app("/notes", "github.com/example/notes-app", bindings=["sqlite"])
openrun use --promote github.com/example/config/apps.star

openrun use useful for illustration Kubernetes apply: it creates caller apps, updates apps whose configuration changed, and leaves the remainder alone. All app management, including the SQLite binding, tin beryllium driven done GitOps.

That is the full setup. The app gets a persistent measurement mounted astatine /data and finds its database done injected situation variables (SQLITE_DB_PATH, SQLITE_DIR). Every *.db record the app creates successful that directory is replicated, including files created astatine runtime.

Changes are typically replicated wrong astir a 2nd by default (sync_interval is configurable)

Single Node

On Docker and Podman, OpenRun runs Litestream successful a per-app companion instrumentality that shares the app’s information volume. Before the app instrumentality starts connected an quiet volume, reconstruct containers propulsion immoderate replicated databases back. When the app scales down to zero connected idle, the Litestream instrumentality performs a last sync and stops.

Single-node deployment pinch Litestream replication of app information and server metadata to S3-compatible storage

The server’s ain metadata tin beryllium replicated the aforesaid way. Litestream is embedded successful the OpenRun binary arsenic a Go library, truthful mounting metadata.litestream_config successful the server config replicates the metadata and audit databases without an further Litestream process.

Kubernetes

The aforesaid app config useful erstwhile OpenRun deploys to a Kubernetes cluster. The binding’s measurement becomes a PersistentVolumeClaim, and OpenRun adds a reconstruct init instrumentality positive a autochthonal Litestream sidecar (Kubernetes 1.29 aliases newer) to the app pod automatically. The sidecar starts earlier the app instrumentality and is terminated aft it, allowing Litestream to execute a last sync during orderly shutdown. Apps pinch a SQLite binding tally arsenic a azygous replica pinch the Recreate update strategy, preventing aggregate app pods from penning to the aforesaid SQLite measurement during an update.

Kubernetes deployment pinch a reconstruct init container, app instrumentality and Litestream sidecar successful the app pod, replicating the SQLite PVC to S3-compatible storage

What Happens connected a Volume aliases Node Loss

For a mislaid app volume, betterment is automatic from the app’s perspective. The adjacent clip the app starts, OpenRun sees the quiet volume, runs the reconstruct containers to propulsion the databases backmost from the replica, and past starts the app instrumentality against the restored data. The replica is keyed by the binding, truthful attaching the aforesaid binding to a caller app restores the information into that app’s caller measurement too.

For a complete node loss, pinch metadata replication enabled, the betterment process is:

  1. Install OpenRun connected a caller machine.
  2. Start the server pinch the aforesaid config file.

On startup, the server finds its metadata database missing, restores the metadata and audit databases from the replica, and comes up pinch each apps, bindings, services, versions and audit history intact. Each app past redeploys connected first request, restoring its SQLite information from its ain replica earlier the instrumentality starts. To retrieve the node, you only request the server config and its referenced secrets. OpenRun’s metadata and replicated app information are restored from entity storage.

Application information and OpenRun’s ain metadata tin truthful beryllium recovered from the aforesaid object-storage backend. Replication is asynchronous. Under normal conditions, pinch the default one-second sync_interval, a abrupt clang tin suffer astir the astir caller 2nd of writes that person not yet reached entity storage.

The node-loss script is exercised end-to-end successful CI tests. The trial hard-kills the server, deletes the containers, volumes, and the OpenRun installation directory, including the metadata databases. It past verifies that everything is rebuilt automatically from the entity store, including the app SQLite data.

Monitoring

openrun replication position reports the authorities of each replicated database:

$ openrun replication position -f table Kind Target Config State LastSync Files Apps metadata metadata mainbackup patient 2026-08-25 16:31:42 - metadata audit mainbackup patient 2026-08-25 16:31:42 - app /auto/app_prd_.../sqlite (prod) mainbackup patient 2026-08-25 23:31:30 data.db /notes app /auto/app_prd_.../sqlite (staged) mainbackup pending - - stage.localhost:/notes

App states harvester the replica listing successful entity retention pinch the replication container’s state, truthful a grounded replication instrumentality is visible moreover erstwhile entity retention still contains a caller replica.

See the Litestream reference for the afloat config options and the SQLite hosting usage case for app champion practices (WAL mode, engaged timeouts, short constitute transactions).

Replication position is besides visible successful the Console App - spot the live demo.

More