Configuration Reference
This is the comprehensive configuration guide covering zero-config quickstart, storage backends, observability, and environment variables. For the raw schema field list, see Config File Schema.
Overview
Key resolution for verifiers
When verifying signed documents, JACS resolves the signer’s public key using a configurable order of sources. Set JACS_KEY_RESOLUTION (environment variable or in config) to a comma-separated list of sources: local (local key cache by publicKeyHash), dns (DNS TXT fingerprint validation), hai (HAI key service). Example: JACS_KEY_RESOLUTION=local,hai or local,dns,hai. The first source that yields verifiable key material is used. Use verify_standalone() with explicit keyResolution for one-off verification without loading a full config.
Zero-Config Path
If you just want to sign and verify without manual config setup, use quickstart(name, domain, ...):
import jacs.simple as jacs
info = jacs.quickstart(name="config-agent", domain="config.example.com")
print(info.config_path, info.public_key_path, info.private_key_path)
const jacs = require('@hai.ai/jacs/simple');
const info = await jacs.quickstart({
name: 'config-agent',
domain: 'config.example.com',
});
console.log(info.configPath, info.publicKeyPath, info.privateKeyPath);
jacs quickstart --name config-agent --domain config.example.com
quickstart(name, domain, ...) creates a persistent agent with keys on disk (default algorithm: pq2025). If ./jacs.config.json already exists, it loads it; otherwise it creates a new agent. Returned AgentInfo includes config/key paths (config_path/public_key_path/private_key_path in Python, configPath/publicKeyPath/privateKeyPath in Node) plus key directory metadata so you can locate key material immediately. Rust/CLI quickstart requires an explicit password source (JACS_PRIVATE_KEY_PASSWORD, or JACS_PASSWORD_FILE in CLI). Python/Node can auto-generate a password if needed; set JACS_SAVE_PASSWORD_FILE=true if you want that generated password persisted to ./jacs_keys/.jacs_password.
Minimal Configuration
For persistent agents, a config file needs only two fields (plus $schema):
{
"$schema": "https://hai.ai/schemas/jacs.config.schema.json",
"jacs_agent_id_and_version": "YOUR_AGENT_ID:YOUR_VERSION",
"jacs_agent_key_algorithm": "pq2025"
}
All other settings use sensible defaults (./jacs_data, ./jacs_keys, fs storage). Override only what you need.
Complete Example Configuration
{
"$schema": "https://hai.ai/schemas/jacs.config.schema.json",
"jacs_use_security": "false",
"jacs_data_directory": "./jacs_data",
"jacs_key_directory": "./jacs_keys",
"jacs_agent_private_key_filename": "jacs.private.pem.enc",
"jacs_agent_public_key_filename": "jacs.public.pem",
"jacs_agent_key_algorithm": "pq2025",
"jacs_default_storage": "fs",
"observability": {
"logs": {
"enabled": true,
"level": "info",
"destination": {
"type": "file",
"path": "./logs"
},
"headers": {
"Authorization": "Bearer token",
"X-API-Key": "secret"
}
},
"metrics": {
"enabled": true,
"destination": {
"type": "prometheus",
"endpoint": "http://localhost:9090/api/v1/write",
"headers": {
"Authorization": "Basic dXNlcjpwYXNz"
}
},
"export_interval_seconds": 60,
"headers": {
"X-Service": "jacs"
}
},
"tracing": {
"enabled": true,
"sampling": {
"ratio": 0.1,
"parent_based": true,
"rate_limit": 100
},
"resource": {
"service_name": "jacs",
"service_version": "0.4.0",
"environment": "production",
"attributes": {
"team": "platform",
"region": "us-west-2"
}
}
}
}
}
Observability Configuration
JACS supports comprehensive observability through configurable logging, metrics, and tracing. All observability features are optional and can be configured in the jacs.config.json file.
Logs Configuration
Controls how JACS generates and outputs log messages.
| Field | Type | Required | Description |
|---|---|---|---|
enabled | boolean | Yes | Whether logging is enabled |
level | string | Yes | Minimum log level: trace, debug, info, warn, error |
destination | object | Yes | Where logs are sent (see destinations below) |
headers | object | No | Additional headers for remote destinations |
Log Destinations
File Logging
{
"type": "file",
"path": "./logs"
}
Writes logs to rotating files in the specified directory.
Console Logging (stderr)
{
"type": "stderr"
}
Outputs logs to standard error stream.
OpenTelemetry Protocol (OTLP)
{
"type": "otlp",
"endpoint": "http://localhost:4317",
"headers": {
"Authorization": "Bearer token"
}
}
Sends logs to an OTLP-compatible endpoint (like Jaeger, Grafana Cloud).
Null (disabled)
{
"type": "null"
}
Discards all log output.
Metrics Configuration
Controls collection and export of application metrics.
| Field | Type | Required | Description |
|---|---|---|---|
enabled | boolean | Yes | Whether metrics collection is enabled |
destination | object | Yes | Where metrics are exported (see destinations below) |
export_interval_seconds | integer | No | How often to export metrics (default: 60) |
headers | object | No | Additional headers for remote destinations |
Metrics Destinations
Prometheus Remote Write
{
"type": "prometheus",
"endpoint": "http://localhost:9090/api/v1/write",
"headers": {
"Authorization": "Basic dXNlcjpwYXNz"
}
}
Exports metrics in Prometheus format to a remote write endpoint.
OpenTelemetry Protocol (OTLP)
{
"type": "otlp",
"endpoint": "http://localhost:4317",
"headers": {
"Authorization": "Bearer token"
}
}
Exports metrics to an OTLP-compatible endpoint.
File Export
{
"type": "file",
"path": "./metrics.txt"
}
Writes metrics to a local file.
Console Output (stdout)
{
"type": "stdout"
}
Prints metrics to standard output.
Tracing Configuration
Controls distributed tracing for request flows.
| Field | Type | Required | Description |
|---|---|---|---|
enabled | boolean | Yes | Whether tracing is enabled |
sampling | object | No | Sampling configuration (see below) |
resource | object | No | Service identification (see below) |
Sampling Configuration
Controls which traces are collected to manage overhead.
| Field | Type | Default | Description |
|---|---|---|---|
ratio | number | 1.0 | Fraction of traces to sample (0.0-1.0) |
parent_based | boolean | true | Whether to respect parent trace sampling decisions |
rate_limit | integer | none | Maximum traces per second |
Examples:
"ratio": 1.0- Sample all traces (100%)"ratio": 0.1- Sample 10% of traces"ratio": 0.01- Sample 1% of traces"rate_limit": 10- Maximum 10 traces per second
Resource Configuration
Identifies the service in distributed tracing systems.
| Field | Type | Required | Description |
|---|---|---|---|
service_name | string | Yes | Name of the service |
service_version | string | No | Version of the service |
environment | string | No | Environment (dev, staging, prod) |
attributes | object | No | Custom key-value attributes |
Authentication & Headers
For remote destinations (OTLP, Prometheus), you can specify authentication headers:
Bearer Token Authentication:
"headers": {
"Authorization": "Bearer your-token-here"
}
Basic Authentication:
"headers": {
"Authorization": "Basic dXNlcjpwYXNz"
}
API Key Authentication:
"headers": {
"X-API-Key": "your-api-key",
"X-Auth-Token": "your-auth-token"
}
Common Patterns
Development Configuration
"observability": {
"logs": {
"enabled": true,
"level": "debug",
"destination": { "type": "stderr" }
},
"metrics": {
"enabled": true,
"destination": { "type": "stdout" }
}
}
Production Configuration
"observability": {
"logs": {
"enabled": true,
"level": "info",
"destination": {
"type": "otlp",
"endpoint": "https://logs.example.com:4317",
"headers": {
"Authorization": "Bearer prod-token"
}
}
},
"metrics": {
"enabled": true,
"destination": {
"type": "prometheus",
"endpoint": "https://metrics.example.com/api/v1/write"
},
"export_interval_seconds": 30
},
"tracing": {
"enabled": true,
"sampling": {
"ratio": 0.05,
"rate_limit": 100
},
"resource": {
"service_name": "jacs",
"service_version": "0.4.0",
"environment": "production"
}
}
}
File-based Configuration
"observability": {
"logs": {
"enabled": true,
"level": "info",
"destination": {
"type": "file",
"path": "/var/log/jacs"
}
},
"metrics": {
"enabled": true,
"destination": {
"type": "file",
"path": "/var/log/jacs/metrics.txt"
},
"export_interval_seconds": 60
}
}
Environment Variable Integration
The observability configuration works alongside JACS's core configuration system.
Required Environment Variable
Only one environment variable is truly required:
JACS_PRIVATE_KEY_PASSWORD- Password for encrypting/decrypting private keys (required for cryptographic operations)
Configuration-Based Settings
All other JACS settings are configuration file fields that have sensible defaults:
jacs_data_directory- Where agent/document data is stored (default:./jacs_data)jacs_key_directory- Where cryptographic keys are stored (default:./jacs_keys)jacs_agent_key_algorithm- Cryptographic algorithm to use (default:pq2025)jacs_default_storage- Storage backend (default:fs)jacs_use_security/JACS_ENABLE_FILESYSTEM_QUARANTINE- Enable filesystem quarantine of executable files (default:false). The env varJACS_USE_SECURITYis deprecated; useJACS_ENABLE_FILESYSTEM_QUARANTINEinstead.
These can be overridden by environment variables if needed, but they are primarily configured through the jacs.config.json file.
The observability configuration is completely optional - JACS will work without any observability configuration.
Storage Configuration
The jacs_default_storage field determines where JACS stores agent data, documents, and keys. This is a critical configuration that affects how your data is persisted and accessed.
Available Storage Backends
| Backend | Value | Description | Use Case |
|---|---|---|---|
| Filesystem | "fs" | Signed JSON documents on local disk | Default, development, single-node deployments |
| Local Indexed SQLite | "rusqlite" | Signed documents in SQLite with FTS search | Local search, bindings, MCP |
| AWS S3 | "aws" | Amazon S3 object storage | Remote object storage |
| Memory | "memory" | In-memory object storage (non-persistent) | Testing, temporary data |
| Web Local | "local" | Browser local storage (WASM only) | Web applications |
For local indexed document search in JACS core, use "rusqlite". Additional database backends such as PostgreSQL, DuckDB, Redb, and SurrealDB live in separate crates and are not core jacs_default_storage values.
Backend-Specific Configuration
Filesystem Storage ("fs")
{
"jacs_default_storage": "fs",
"jacs_data_directory": "./jacs_data",
"jacs_key_directory": "./jacs_keys"
}
Requirements: None - works out of the box Data location: Local directories as specified in config Best for: Development, local testing, single-machine deployments
Local Indexed SQLite ("rusqlite")
{
"jacs_default_storage": "rusqlite",
"jacs_data_directory": "./jacs_data",
"jacs_key_directory": "./jacs_keys"
}
Requirements: Built with the default sqlite Cargo feature
Database path: <jacs_data_directory>/jacs_documents.sqlite3
Best for: Local full-text search, MCP/binding document operations, single-machine deployments that want indexed reads
AWS S3 Storage ("aws")
{
"jacs_default_storage": "aws"
}
Required Environment Variables:
JACS_ENABLE_AWS_BUCKET_NAME- S3 bucket nameAWS_ACCESS_KEY_ID- AWS access keyAWS_SECRET_ACCESS_KEY- AWS secret keyAWS_REGION- AWS region (optional, defaults to us-east-1)
Best for: Production deployments, distributed systems, cloud-native applications
Memory Storage ("memory")
{
"jacs_default_storage": "memory"
}
Requirements: None Data persistence: None - data is lost when application stops Best for: Unit testing, temporary operations, development scenarios
Storage Behavior
- Filesystem (
fs) stores signed documents as JSON files underjacs_data/documents/. - Rusqlite (
rusqlite) stores signed documents injacs_data/jacs_documents.sqlite3and is the indexedDocumentServicepath used by bindings and MCP. - Agent files and keys remain path-based assets under
jacs_data/andjacs_keys/. - Observability data (logs, metrics) can use separate storage via observability configuration.
DocumentService Guarantees
- Every
DocumentServiceread verifies the stored JACS document before returning it. - Every
create()andupdate()verifies the signed document before persisting it. - If an update payload changes a signed JACS document without re-signing it, the write fails.
- Visibility changes create a new signed version instead of mutating metadata in place.
Configuration Examples
Development Setup (Filesystem)
{
"jacs_default_storage": "fs",
"jacs_data_directory": "./dev_data",
"jacs_key_directory": "./dev_keys"
}
Production Setup (AWS S3)
{
"jacs_default_storage": "aws"
}
With environment variables:
export JACS_ENABLE_AWS_BUCKET_NAME="my-jacs-production-bucket"
export AWS_ACCESS_KEY_ID="AKIA..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_REGION="us-west-2"
Security Considerations
- AWS S3: Ensure proper IAM permissions for bucket access
- Rusqlite: Protect the local database file with the same filesystem permissions you use for other signed artifacts
- Filesystem: Ensure proper file system permissions for data and key directories
- Keys: Regardless of storage backend, always set
JACS_PRIVATE_KEY_PASSWORDfor key encryption
Migration Between Storage Backends
When changing storage backends, you'll need to:
- Export existing data from the current backend
- Update the
jacs_default_storageconfiguration - Set any required environment variables for the new backend
- Import data into the new backend
JACS doesn't automatically migrate data between storage backends - this must be done manually or via custom scripts.