Ruby SDK for the fast, file-backed, scalable JSON token engine
⚠️ Version 1.0.0-beta — production testing phase
API is stable. Feedback is welcome before the final 1.0.0 release
Fast B-tree–backed token store for stateful user sessions
Provides authentication and authorization across multiple processes
Optimized for vertical scaling on a single server
Installation
With Bundler:
bundle add crudjt --preOr via RubyGems:
gem install crudjt --preHow to use
- One process starts the master
- All other processes connect to it
Start CRUDJT master (once)
Start the CRUDJT master when your application boots
Only one process can do this for a single token storage
The master process manages sessions and coordination
All functions can also be used directly from it
For containerized deployments, see: Start CRUDJT master in Docker
Generate a new secret key (terminal)
export CRUDJT_SECRET_KEY=$(openssl rand -base64 48)Start master (ruby)
require 'crudjt'
CRUDJT::Config.start_master(
secret_key: ENV.fetch('CRUDJT_SECRET_KEY'),
store_jt_path: 'path/to/local/storage', # optional
grpc_host: '127.0.0.1', # default
grpc_port: 50051 # default
)Important: Use the same secret_key across all sessions. If the key changes, previously stored tokens cannot be decrypted and will return nil or false
Start CRUDJT master in Docker
Create a docker-compose.yml file:
services:
crudjt-server:
image: coffeemainer/crudjt-server:beta
restart: unless-stopped
ports:
- "${CRUDJT_CLIENT_PORT:-50051}:50051"
volumes:
- "${STORE_JT:-./store_jt}:/app/store_jt"
- "${CRUDJT_SECRETS:-./crudjt_secrets}:/app/secrets"
environment:
CRUDJT_DOCKER_HOST: 0.0.0.0
CRUDJT_DOCKER_PORT: 50051Start the server:
docker-compose up -dEnsure the secrets directory contains your secret key file at ./crudjt_secrets/secret_key.txt
For configuration details and image versions, see the CRUDJT Server on Docker Hub
Connect to an existing CRUDJT master
Use this in all other processes
Typical examples:
- multiple local processes
- background jobs
- forked processes
require 'crudjt'
CRUDJT::Config.connect_to_master(
grpc_host: '127.0.0.1', # default
grpc_port: 50051 # default
)Process layout
App boot
├─ Process A → start_master
├─ Process B → connect_to_master
└─ Process C → connect_to_master
C
data = { user_id: 42, role: 11 } # required
ttl = 3600 * 24 * 30 # optional: token lifetime (seconds)
# Optional: read limit
# Each read decrements the counter
# When it reaches zero — the token is deleted
silence_read = 10
token = CRUDJT.create(data, ttl: ttl, silence_read: silence_read)
# token == 'HBmKFXoXgJ46mCqer1WXyQ'# To disable token expiration or read limits, pass `nil`
CRUDJT.create({ user_id: 42, role: 11 }, ttl: nil, silence_read: nil)R
result = CRUDJT.read('HBmKFXoXgJ46mCqer1WXyQ')
# result == {'metadata' => {'ttl' => 101001, 'silence_read' => 9}, 'data' => {'user_id' => 42, 'role' => 11}}# When expired or not found token
result = CRUDJT.read('HBmKFXoXgJ46mCqer1WXyQ')
# result == nilU
data = { user_id: 42, role: 8 }
# `nil` disables limits
ttl = 600
silence_read = 100
result = CRUDJT.update('HBmKFXoXgJ46mCqer1WXyQ', data, ttl: ttl, silence_read: silence_read)
# result == true# When expired or not found token
CRUDJT.update('HBmKFXoXgJ46mCqer1WXyQ', { user_id: 42, role: 8 })
# result == falseD
result = CRUDJT.delete('HBmKFXoXgJ46mCqer1WXyQ')
# result == true# When expired or not found token
result = CRUDJT.delete('HBmKFXoXgJ46mCqer1WXyQ')
# result == falsePerformance
Metrics will be published after 1.0.0-beta GitHub Actions builds
Storage (File-backed)
Disk footprint
Metrics will be published after 1.0.0-beta GitHub Actions builds
Path Lookup Order
Stored tokens are placed in the file system according to the following order
- Explicitly set via
CRUDJT::Config.start_master(store_jt_path: 'custom/path/to/file_system_db') - Default system location
-
Linux:
/var/lib/store_jt -
macOS:
/usr/local/var/store_jt -
Windows:
C:\Program Files\store_jt
-
Linux:
- Project root directory (fallback)
Storage Characteristics
- CRUDJT automatically removing expired tokens after start and every 24 hours without blocking the main thread
- Storage automatically fsyncs every 500ms, meanwhile tokens are available from cache
Multi-process Coordination
For multi-process scenarios, CRUDJT uses gRPC over an insecure local port for same-host communication only. It is not intended for inter-machine or internet-facing usage
Limits
The library has the following limits and requirements
- Ruby version: tested with 2.7
- Supported platforms: Linux, macOS (x86_64 / arm64). Windows (experimental, x86_64 / arm64)
- Maximum json size per token: 256 bytes
-
secret_keyformat: must be Base64 -
secret_keysize: must be 32, 48, or 64 bytes
Contact & Support
- Custom integrations / new features / collaboration: support@crudjt.com
- Library support & bug reports: open an issue
Lincense
CRUDJT is released under the MIT License
💘 Shoot your g . ? Love me out via Patreon Sponsors!