<div align="center">
<img src="../assets/logo.png" alt="MoltenDB Logo" width="300"/>
# moltendb-server
### ๐ The Network Layer Crate
**Axum HTTP server ยท TLS ยท JWT auth ยท CORS ยท Rate limiting ยท WebSocket ยท CLI config**
The runnable binary. Delegates all database logic to `moltendb-core`.
[](LICENSE.md)
[](https://www.rust-lang.org)
[](#testing)
</div>
---
## What is this crate?
`moltendb-server` is the runnable binary of MoltenDB. It owns everything related to the network layer and leaves all database logic to `moltendb-core`:
- **Axum HTTP server** with TLS termination (`axum-server` + `rustls`).
- **REST endpoints** โ `POST /set`, `POST /get`, `POST /update`, `POST /delete`, `POST /analytics` (โ ๏ธ analytics under development).
- **REST-style GET** โ `GET /:collection/:key` and `GET /:collection` (with query string filters).
- **WebSocket** โ `GET /ws` for real-time mutation notifications.
- **JWT auth middleware** โ all protected routes require a valid `Authorization: Bearer <token>` header.
- **Per-IP rate limiting** โ sliding-window rate limiter, configurable via CLI.
- **CORS** โ configurable allowed origins.
- **Request body size limit** โ oversized requests are rejected at the HTTP layer before application code sees them.
- **Graceful shutdown** โ drains in-flight requests and flushes the WAL before exit.
- **CLI configuration** โ all options are configurable via `clap` flags or environment variables.
---
## Quick start
### Install from source
```bash
cargo install --path moltendb-server
```
### Run
```bash
moltendb \
--db-path my_database.log \
--write-mode async \
--storage-mode tiered \
--jwt-secret my-awesome-secret \
--admin-user admin \
--admin-password admin123 \
--cors-origin "*"
```
Or with `cargo run` from the workspace root:
```bash
cargo run --package moltendb-server --bin moltendb -- \
--db-path my_database.log \
--write-mode async \
--storage-mode tiered \
--jwt-secret my-awesome-secret \
--admin-user admin \
--admin-password admin123 \
--cors-origin "*"
```
---
## CLI reference
| `--port` | `PORT` | `1538` | Port to listen on |
| `--db-path` | `DB_PATH` | `my_database.log` | Path to the WAL log file |
| `--cert` | `TLS_CERT` | `cert.pem` | TLS certificate PEM file |
| `--key` | `TLS_KEY` | `key.pem` | TLS private key PEM file |
| `--write-mode` | `WRITE_MODE` | `async` | `async` (high throughput) or `sync` (zero data loss) |
| `--storage-mode` | `STORAGE_MODE` | `standard` | `standard` or `tiered` (hot + cold log, recommended for 100k+ docs) |
| `--encryption-key` | `ENCRYPTION_KEY` | โ | At-rest encryption password (ChaCha20-Poly1305) |
| `--jwt-secret` | `JWT_SECRET` | **required** | JWT signing secret โ server refuses to start without it |
| `--admin-user` | `MOLTENDB_ADMIN_USER` | โ | Admin username seeded at startup |
| `--admin-password` | `MOLTENDB_ADMIN_PASSWORD` | โ | Admin password seeded at startup |
| `--cors-origin` | `CORS_ORIGIN` | `*` | Allowed CORS origin(s), comma-separated |
| `--rate-limit-requests` | `RATE_LIMIT_REQUESTS` | `100` | Max requests per IP per window |
| `--rate-limit-window` | `RATE_LIMIT_WINDOW_SECS` | `60` | Rate limit sliding window in seconds |
| `--max-body-size` | `MAX_BODY_SIZE` | `10485760` | Max request body size in bytes (default 10 MB) |
| `--hot-threshold` | `MOLTEN_HOT_THRESHOLD` | `50000` | Number of documents per collection kept in RAM before paging out to disk |
| `--disable-encryption` | โ | โ | Disable at-rest encryption |
---
## HTTP API
### Authentication
```http
POST /login
Content-Type: application/json
{ "username": "admin", "password": "admin123" }
```
Returns `{ "token": "<jwt>" }`. Include the token in all subsequent requests:
```http
Authorization: Bearer <jwt>
```
### Insert / upsert
```http
POST /set
Authorization: Bearer <jwt>
Content-Type: application/json
{
"collection": "users",
"data": {
"u1": { "name": "Alice", "role": "admin" },
"u2": { "name": "Bob", "role": "viewer" }
}
}
```
### Query
```http
POST /get
Authorization: Bearer <jwt>
Content-Type: application/json
{
"collection": "users",
"where": { "role": "admin" },
"fields": ["name", "role"],
"sort": [{ "field": "name", "order": "asc" }],
"count": 10,
"offset": 0
}
```
### Update (partial patch)
```http
POST /update
Authorization: Bearer <jwt>
Content-Type: application/json
{ "collection": "users", "data": { "u1": { "role": "superadmin" } } }
```
### Delete
```http
POST /delete
Authorization: Bearer <jwt>
Content-Type: application/json
{ "collection": "users", "keys": "u1" }
```
### REST-style GET
```http
GET /users/u1
GET /users
Authorization: Bearer <jwt>
```
### WebSocket
```
wss://localhost:1538/ws
```
Emits a JSON message for every mutation:
```json
{ "event": "change", "collection": "users", "key": "u1", "new_v": 2 }
```
---
## Testing
A full API walkthrough is available in [`tests/requests.http`](../tests/requests.http). Run it with any HTTP client that supports `.http` files (JetBrains HTTP Client, REST Client for VS Code, etc.).
---
## Making auth optional
`moltendb-auth` is compiled behind the `auth` Cargo feature, which is enabled by default. To bring your own auth layer, disable the default feature:
```toml
[dependencies]
moltendb-server = { version = "0.3.0-beta.2", default-features = false }
```
Then wrap the Axum router with your own `tower::Layer` before calling `serve()`. Without the `auth` feature the server starts without requiring `--jwt-secret` and all routes are unprotected.
---
## Part of the MoltenDB workspace
```
MoltenDB/
โโโ moltendb-core/ โ pure engine (DashMap, WAL, query evaluator)
โโโ moltendb-wasm/ โ browser adapter (wasm-bindgen glue, WorkerDb, OPFS)
โโโ moltendb-auth/ โ identity layer (JWT, Argon2, UserStore)
โโโ moltendb-server/ โ you are here
```
See the [root README](../README.md) for the full architecture overview and feature list.