LuckDB: A Lightweight JSON Document Database in Rust with Encryption
LuckDB is a lightweight, in-memory JSON document database written in Rust with built-in AES-256 encryption and configuration management. It provides a simple yet powerful API for storing, querying, and manipulating JSON documents with support for indexing, aggregation, persistence, and secure client-server mode.
Table of Contents
Features
- Document Storage: Store JSON documents with automatic ID generation
- AES-256 Encryption: Built-in encryption for data at rest with secure key management
- Configuration Management: Flexible configuration system with TOML file support
- Rich Querying: Support for complex queries with multiple operators
- Indexing: Create indexes for improved query performance
- Aggregation Pipeline: Transform and analyze data with aggregation stages
- Update Operations: Flexible document updates with various operators
- Persistence: Save and load data from disk with optional encryption
- Secure Client-Server Mode: Networked access with authentication and encryption
- Bulk Operations: Efficient bulk write operations
- Geospatial Queries: Basic support for geospatial queries
- Platform-specific Storage Paths: Automatic handling of storage paths across operating systems
- Configuration File Support: TOML-based configuration with validation
- Command-Line Interface: Professional CLI tool for server management and deployment
Installation
As a Library
Add LuckDB to your Cargo.toml:
[]
= "0.1.3"
CLI Server Tool
The LuckDB CLI server tool is included as part of the project. Build it from source:
# Clone the repository
# Build the CLI tool
# The CLI binary will be available at:
# Linux/macOS: target/release/luckdb-server-cli
# Windows: target/release/luckdb-server-cli.exe
Alternatively, use the convenience scripts:
# Linux/macOS
# Windows
Quick Start
Library Usage
Basic Usage
use ;
use json;
Encrypted Storage
use ;
// Create configuration with encryption
let config = with_storage_path
.with_encryption;
let mut client = with_config?;
// All data will be encrypted when saved to disk
client.save?;
Server Mode with Authentication
use ;
// Configure server with authentication and encryption
let server_config = with_storage_path
.with_auth
.with_encryption;
let mut server = with_config?;
server.start?;
Configuration File
Create a config.toml file to configure LuckDB:
[]
# Storage path for database files (optional)
= "./data"
# Enable AES-256 encryption (default: false)
= true
# Encryption password for data protection
= "your_secure_password_here"
# Authentication for client-server mode (optional)
= "admin"
= "your_auth_password_here"
# Server address for client-server mode (optional)
= "127.0.0.1:27017"
# Auto-save interval in seconds (optional, None = manual only)
= 300
# Maximum number of backup files to keep (default: 5)
= 10
Then load the configuration:
use ;
// Load configuration from file
let config = load_from_file?;
let mut client = with_config?;
// Or use the convenience method
let mut client = with_config_file?;
CLI Server Quick Start
Start a Development Server
# Quick development server (in-memory, debug logging)
# Development server with file persistence
# Development server with encryption
Start a Production Server
# Create production configuration
# Edit the configuration with your secure passwords
# Edit prod.toml to set real encryption and auth passwords
# Start server with configuration
Start Server with Authentication
# Quick server with authentication
# Server with encryption and authentication
Server Management Commands
# View help
# Generate configuration files
# Check version
API Reference
Client
The Client is the entry point to LuckDB. It manages multiple databases with configurable storage and encryption.
// Basic in-memory client
let mut client = new;
// With configuration
let config = with_storage_path
.with_encryption;
let mut client = with_config?;
// From configuration file
let mut client = with_config_file?;
Methods
new() -> Client: Create a basic in-memory clientwith_config(config: DatabaseConfig) -> Result<Client>: Create client with configurationwith_config_file(path: P) -> Result<Client>: Create client from TOML configuration filewith_encryption(password: S) -> Result<Self>: Enable encryption on existing clientdb(&mut self, name: &str) -> &mut Database: Get or create a databaselist_database_names(&self) -> Vec<String>: List all databasesdrop_database(&mut self, name: &str) -> Result<()>: Drop a databasesave(&self) -> Result<()>: Save all data to disk (encrypted if configured)load(&mut self) -> Result<()>: Load data from disk (decrypt if needed)config(&self) -> &DatabaseConfig: Get current configurationupdate_config(&mut self, config: DatabaseConfig) -> Result<()>: Update configuration
Database
A Database contains multiple collections.
let db = client.db;
Methods
collection(&mut self, name: &str) -> &mut Collection: Get or create a collectionlist_collection_names(&self) -> Vec<String>: List all collectionscreate_collection(&mut self, name: &str, options: Option<CreateCollectionOptions>) -> Result<()>: Create a collection with optionsdrop_collection(&mut self, name: &str) -> Result<()>: Drop a collectionstats(&self) -> Result<DatabaseStats>: Get database statisticsrun_command(&mut self, command: &Document) -> Result<Document>: Run a database command
Collection
A Collection stores JSON documents.
let collection = db.collection;
Methods
insert(&mut self, doc: Document) -> Result<DocId>: Insert a documentinsert_many(&mut self, docs: Vec<Document>) -> Result<Vec<DocId>>: Insert multiple documentsfind(&self, query: Query, options: Option<FindOptions>) -> Result<Vec<(DocId, Document)>>: Find documents matching a queryfind_one(&self, query: Query, options: Option<FindOptions>) -> Result<(DocId, Document)>: Find a single documentupdate_one(&mut self, query: Query, update: UpdateDocument, upsert: bool) -> Result<usize>: Update the first matching documentupdate_many(&mut self, query: Query, update: UpdateDocument) -> Result<usize>: Update all matching documentsreplace_one(&mut self, query: Query, replacement: Document, upsert: bool) -> Result<usize>: Replace the first matching documentdelete_one(&mut self, query: Query) -> Result<usize>: Delete the first matching documentdelete_many(&mut self, query: Query) -> Result<usize>: Delete all matching documentscount_documents(&self, query: Query) -> Result<usize>: Count documents matching a querycreate_index(&mut self, index: Index) -> Result<()>: Create an indexdrop_index(&mut self, name: &str) -> Result<()>: Drop an indexlist_indexes(&self) -> Result<Vec<Index>>: List all indexesaggregate(&self, pipeline: Vec<AggregationStage>) -> Result<Vec<Document>>: Run an aggregation pipelinedistinct(&self, field: &str, query: Option<Query>) -> Result<Vec<Value>>: Get distinct values for a fieldbulk_write(&mut self, operations: Vec<BulkWriteOperation>, options: Option<BulkWriteOptions>) -> Result<BulkWriteResult>: Execute bulk write operations
Configuration
The DatabaseConfig struct provides comprehensive configuration options for LuckDB.
use DatabaseConfig;
// Default configuration
let config = new;
// With storage path
let config = with_storage_path;
// With encryption
let config = with_encryption;
// With authentication
let config = new
.with_auth
.with_storage_path;
// Save/load configuration
config.save_to_file?;
let loaded_config = load_from_file?;
Configuration Options
storage_path: Option<PathBuf>: Path for database file storage (can be directory or specific file)encryption_enabled: bool: Enable/disable AES-256 encryption (default: false)encryption_password: Option<String>: Password for encryption key derivationserver_address: Option<String>: Server address for client-server modeauth_username: Option<String>: Authentication usernameauth_password: Option<String>: Authentication passwordauto_save_interval_seconds: Option<u64>: Auto-save interval in seconds (None = manual only)max_backup_files: usize: Maximum number of backup files to keep (default: 5)
Configuration Methods
new() -> DatabaseConfig: Create default configurationwith_storage_path(path: P) -> DatabaseConfig: Set storage pathwith_encryption(password: S) -> DatabaseConfig: Enable encryption with passwordwith_auth<U: Into<String>, P: Into<String>>(username, password) -> DatabaseConfig: Set authenticationwith_server_mode<S: Into<String>>(address: S) -> DatabaseConfig: Set server addresssave_to_file<P: AsRef<Path>>(&self, path: P) -> Result<()>: Save config to TOML fileload_from_file<P: AsRef<Path>>(path: P) -> Result<Self>: Load config from TOML filevalidate(&self) -> Result<()>: Validate configuration settingsis_encryption_configured(&self) -> bool: Check if encryption is properly configuredis_auth_configured(&self) -> bool: Check if authentication is configuredget_or_create_storage_path(&self) -> Result<PathBuf>: Get storage path, create parent dirs if needed
Encryption
LuckDB provides built-in AES-256 encryption for secure data persistence.
use ;
// Create encryption key from password
let key = from_password;
// Encrypt data
let encrypted = encrypt_string?;
// Decrypt data
let decrypted = decrypt_string?;
Encryption Features
- AES-256-CBC mode: Strong encryption standard
- PBKDF2-like key derivation: Secure password-based key generation
- HMAC authentication: Data integrity verification
- Random IV generation: Unique encryption for each save
- Base64 encoding: Safe storage format
Server
The Server provides networked access to LuckDB with authentication and encryption.
use ;
// Create server with configuration
let config = with_storage_path
.with_auth
.with_encryption;
let mut server = with_config?;
// Start server
server.start?;
Server Features
- TCP-based networking: Standard network protocol
- Authentication: Username/password based access control
- Encryption: Data stored encrypted on server
- Thread-per-connection: Concurrent client handling
- Command protocol: Text-based commands for easy integration
Documents
Documents are JSON values represented by serde_json::Value.
use json;
let doc = json!;
Each document automatically gets an _id field of type DocId when inserted.
Queries
Queries are built using the Query struct and its methods.
use ;
use json;
// Simple equality query
let query = new.eq;
// Complex query with multiple conditions
let query = new
.eq
.gt
.in_;
// Using logical operators
let query1 = new.eq;
let query2 = new.eq;
let query = new.or;
Query Operators
eq(key, value): Field equals valuene(key, value): Field not equal to valuegt(key, value): Field greater than valuegte(key, value): Field greater than or equal to valuelt(key, value): Field less than valuelte(key, value): Field less than or equal to valuein_(key, values): Field in array of valuesnin(key, values): Field not in array of valuesexists(key, exists): Field exists (or not)regex(key, pattern): Field matches regex patternand(queries): Logical AND of queriesor(queries): Logical OR of queriesnor(queries): Logical NOR of queriesnot(query): Logical NOT of queryall(key, values): Array contains all valueselem_match(key, query): Array element matches querysize(key, size): Array has specified sizenear(key, point, max_distance): Geospatial near querywithin(key, shape): Geospatial within queryintersects(key, shape): Geospatial intersects query
Updates
Update operations are built using the UpdateDocument struct.
use UpdateDocument;
use json;
let update = new
.set
.inc
.push;
Update Operators
set(key, value): Set field to valueunset(key): Remove fieldinc(key, value): Increment field by valuemul(key, value): Multiply field by valuerename(old_key, new_key): Rename fieldset_on_insert(key, value): Set field on insertmin(key, value): Set field to minimum of current and valuemax(key, value): Set field to maximum of current and valuecurrent_date(key, type_spec): Set field to current datepush(key, value): Push value to array fieldpush_all(key, values): Push all values to array fieldadd_to_set(key, value): Add value to array if not presentpop(key, pos): Remove first or last element of arraypull(key, condition): Remove elements matching conditionpull_all(key, values): Remove all specified values from arraybit(key, operation): Bitwise operation
Indexes
Indexes improve query performance.
use ;
// Create a simple index
let index = new;
collection.create_index?;
// Create a compound index
let index = new;
collection.create_index?;
// Create a unique index
let index = new
.unique;
collection.create_index?;
Aggregation
Aggregation pipelines transform and analyze data.
use ;
use json;
let pipeline = vec!;
let results = collection.aggregate?;
Examples
Basic CRUD Operations
use ;
use json;
Advanced Querying
use ;
use json;
Indexing
use ;
use json;
Aggregation Pipeline
use ;
use json;
Persistence
use ;
use json;
Configuration File Management
use ;
Server CLI Tool
LuckDB includes a comprehensive command-line interface for running production-ready servers with advanced configuration options, logging, and signal handling.
Installation
Build the CLI tool as part of the LuckDB project:
# The CLI binary will be at:
# Linux/macOS: target/release/luckdb-server-cli
# Windows: target/release/luckdb-server-cli.exe
Quick Start
# Start server with default settings
# Start server with encryption and authentication
# Start server with configuration file
# Development mode (in-memory, debug logging)
Configuration Files
Generate configuration templates for different environments:
# Create production configuration
# Create development configuration
# Create test configuration
CLI Options
| Option | Description | Example |
|---|---|---|
--config |
Path to TOML configuration file | --config config.toml |
--address |
Server bind address | --address 127.0.0.1 |
--port |
Server port | --port 27017 |
--storage |
Storage path for database files | --storage ./data |
--encrypt |
Enable AES-256 encryption | --encrypt |
--password |
Encryption password | --password "secure_pass" |
--auth |
Enable authentication | --auth |
--username |
Authentication username | --username admin |
--auth-password |
Authentication password | --auth-password "auth_pass" |
--log-level |
Log level (error, warn, info, debug, trace) | --log-level info |
--log-file |
Log file path | --log-file server.log |
--dev |
Development mode | --dev |
--auto-save |
Auto-save interval in seconds | --auto-save 300 |
Production Deployment
For production deployments, use a configuration file:
# 1. Create production configuration
# 2. Edit configuration with secure passwords
# 3. Set appropriate file permissions
# 4. Start server
Configuration File Format
[]
# Production storage path
= "/var/lib/luckdb/data"
# Always enable encryption in production
= true
= "CHANGE_ME_IN_PRODUCTION"
# Authentication
= "admin"
= "CHANGE_ME_IN_PRODUCTION"
# Server address
= "127.0.0.1:27017"
# Auto-save every 5 minutes
= 300
# Maximum backup files
= 30
# Logging
= "info"
= "/var/log/luckdb/server.log"
Environment Variables
All configuration options can be overridden with environment variables:
Signal Handling
The CLI tool supports graceful shutdown:
- Ctrl+C: Graceful shutdown
- Double Ctrl+C: Force shutdown
Features
- Comprehensive Configuration: TOML files, command-line arguments, and environment variables
- Security: AES-256 encryption, authentication, and secure defaults
- Production Ready: Structured logging, signal handling, and performance options
- Multi-Environment Support: Development, testing, and production configurations
- Validation: Configuration validation with helpful error messages
For detailed documentation, see CLI_README.md.
Advanced Encryption
use ;
Client-Server Mode
use ;
use SocketAddr;
Note: This is just a basic example to give you an idea of how to use LuckDB. In a real-world application, you may want to add more error handling and security features.
use ;
use SocketAddr;
use PathBuf;
License
LuckDB is licensed under the MIT License. See LICENSE for details.