Nginx SQLite Module (ngx_http_sqlite_module) is a standalone dynamic module for building small, configured HTTP APIs directly inside Nginx. Instead of letting clients send arbitrary SQL, each route declares its SQL in Nginx config and accepts only the bound parameters the operation explicitly allows.

It is useful when an application needs lightweight local persistence, status endpoints, feature flags, device metadata, or small admin APIs without adding a separate app server for every simple read/write path.

Example Uses

  • HTTP auth: Store users, API keys, session metadata, or hashed credentials locally and verify submitted secrets with configured SQLite operations.
  • Hit tracking: Count requests, record route access, track downloads, or log lightweight event data without shipping every small metric to an external service.
  • Simple stats: Expose counters, rollups, recent activity, health rows, feature-flag state, or operational snapshots as JSON endpoints.
  • Basic dashboards: Back small internal status pages, device panels, admin tools, or self-hosted control surfaces directly from SQLite.

Key Features

  • Config-owned SQL operations: A location can become a named SQLite operation with a specific HTTP method, SQL statement or batch, response mode, and parameter list.
  • Bound query and JSON params: Inputs come from declared arg: query values or json: request-body paths, then bind to named SQL params so request data cannot become SQL text.
  • Typed parameter transforms: Built-in transforms handle raw text, positive and nonnegative integers, boolean-as-integer values, SQL NULL, defaults, and Argon2id hashing for secrets.
  • Flexible JSON responses: Routes can return a single JSON object, JSON rows, or status-only responses, with support for raw JSON columns through sqlite_json_value.
  • Operational guardrails: The module supports bearer-token protection, selected anonymous routes, read-only validation, body and response size limits, busy timeouts, warmup, and JSON error envelopes.
  • Batch and migration tooling: Multi-statement operations can be declared inline or loaded from a file, and the repository includes an ordered SQLite migration runner.
  • Third-party C hook API: Other same-worker Nginx modules can opt into named, hookable operations without receiving raw SQL access or direct sqlite3 handles.
  • Self-contained test harness: Docker Compose builds the dynamic module, loads example routes, applies example migrations, serves OpenAPI docs, and includes smoke-test and benchmark scripts.

How It Works

  1. Build or install the dynamic module, then load ngx_http_sqlite_module.so from Nginx config.
  2. Declare shared defaults such as sqlite_db, sqlite_bearer_token, response mode, timeouts, and warmup behavior at server or location scope.
  3. Add a route with sqlite;, sqlite_operation, sqlite_method, sqlite_sql or sqlite_batch, and one or more sqlite_param declarations.
  4. On each request, the module validates method/auth/body limits, extracts declared params, binds them to a prepared SQLite statement, and renders the configured JSON or status response.
NGINX
1
2
3
4
5
6
7
8
9
10
11
12
13
sqlite_db "/var/lib/app/app.sqlite";
sqlite_bearer_token "change-me";
sqlite_response json;

location = /api/ready {
sqlite;

sqlite_operation ready;
sqlite_method GET;
sqlite_sql "SELECT 'ready' AS status";
sqlite_read_only on;
sqlite_allow_anon on;
}

Why This Project Matters

This project sits in a practical middle ground: it is not trying to turn Nginx into a full application framework, and it is not a raw database proxy. The useful part is the constraint. Operators define the SQL, the accepted inputs, the response shape, and the access rules in configuration, while clients can only provide values for declared bindings.

That makes it a good fit for self-contained services, embedded dashboards, internal tooling, local-first APIs, or small infrastructure endpoints where running another service would be more moving parts than the job needs.

The hook API also makes the module useful as local persistence infrastructure for other Nginx modules. A third-party module can call a named operation in the same worker process, get structured rows or rendered JSON back, and still avoid owning raw SQL execution itself.

Stack

  • C and the Nginx module API for the dynamic HTTP module
  • SQLite for local embedded storage and prepared statements
  • Argon2id for password or API-key hashing helpers
  • Make + POSIX shell for Linux install, build, status, and uninstall flows
  • Docker Compose for the example server, OpenAPI reference, smoke tests, and benchmarks

If you need a tiny HTTP surface over SQLite and want the SQL to stay firmly in server configuration, Nginx SQLite Module is the compact, operator-controlled version of that idea.