FlureeLabs

Configuration

Fluree server is configured via a configuration file, command-line flags, and environment variables.

Configuration Methods

Configuration File (TOML, JSON, or JSON-LD)

The server reads configuration from .fluree/config.toml (or .fluree/config.jsonld) — the same file used by the Fluree CLI. Server settings live under the [server] section (or "server" key in JSON/JSON-LD). The server walks up from the current working directory looking for .fluree/config.toml or .fluree/config.jsonld, falling back to the global Fluree config directory ($FLUREE_HOME, or the platform config directory — see table below).

Global Directory Layout

When $FLUREE_HOME is set, both config and data share that single directory. When it is not set, the platform's config and data directories are used:

ContentLinuxmacOSWindows
Config (config.toml)~/.config/fluree~/Library/Application Support/fluree%LOCALAPPDATA%\fluree
Data (storage/, active)~/.local/share/fluree~/Library/Application Support/fluree%LOCALAPPDATA%\fluree

On Linux, config and data directories are separated per the XDG Base Directory specification. On macOS and Windows both resolve to the same directory. When directories are split, fluree init --global writes an absolute storage_path into config.toml so the server can locate the data directory regardless of working directory.

# Use default config file discovery
fluree-server

# Override config file path
fluree-server --config /etc/fluree/config.toml

# Activate a profile
fluree-server --profile prod

Example config.toml:

[server]
listen_addr = "0.0.0.0:8090"
storage_path = "/var/lib/fluree"
log_level = "info"
# cache_max_mb = 4096  # global cache budget (MB); default: tiered fraction of RAM (30% <4GB, 40% 4-8GB, 50% ≥8GB)

[server.indexing]
enabled = true
reindex_min_bytes = 100000
# reindex_max_bytes defaults to 20% of system RAM; override only if needed:
# reindex_max_bytes = 536870912  # 512 MB

[server.auth.data]
mode = "required"
trusted_issuers = ["did:key:z6Mk..."]

JSON is also supported (detected by .json file extension):

{
  "server": {
    "listen_addr": "0.0.0.0:8090",
    "storage_path": "/var/lib/fluree",
    "indexing": { "enabled": true }
  }
}

JSON-LD Format

JSON-LD config files (.jsonld extension) add a @context that maps config keys to the Fluree config vocabulary (https://ns.flur.ee/config#), making the file valid JSON-LD. Generate one with:

fluree init --format jsonld

Example .fluree/config.jsonld:

{
  "@context": {
    "@vocab": "https://ns.flur.ee/config#"
  },
  "_comment": "Fluree Configuration — JSON-LD format.",
  "server": {
    "listen_addr": "0.0.0.0:8090",
    "storage_path": ".fluree/storage",
    "log_level": "info",
    "indexing": {
      "enabled": true,
      "reindex_min_bytes": 100000
    }
  },
  "profiles": {
    "prod": {
      "server": {
        "log_level": "warn"
      }
    }
  }
}

The @context is validated at load time (using the JSON-LD parser) but does not affect config value resolution — serde ignores unknown keys like @context and _comment. If both config.toml and config.jsonld exist in the same directory, TOML takes precedence and a warning is logged.

Profiles

Profiles allow environment-specific overrides. Define them in [profiles.<name>.server] and activate with --profile <name>:

[server]
log_level = "info"

[profiles.dev.server]
log_level = "debug"

[profiles.prod.server]
log_level = "warn"
[profiles.prod.server.indexing]
enabled = true
[profiles.prod.server.auth.data]
mode = "required"

Profile values are deep-merged onto [server] — only the fields present in the profile are overridden.

Command-Line Flags

fluree-server \
  --listen-addr 0.0.0.0:8090 \
  --storage-path /var/lib/fluree \
  --log-level info

Environment Variables

All CLI flags have corresponding environment variables with FLUREE_ prefix:

export FLUREE_LISTEN_ADDR=0.0.0.0:8090
export FLUREE_STORAGE_PATH=/var/lib/fluree
export FLUREE_LOG_LEVEL=info

fluree-server

Precedence

Configuration precedence (highest to lowest):

  1. Command-line flags
  2. Environment variables
  3. Profile overrides ([profiles.<name>.server])
  4. Config file ([server])
  5. Built-in defaults

Error Handling

If --config or --profile is specified and the configuration cannot be loaded (file not found, parse error, missing profile), the server exits with an error. This prevents silent misconfiguration in production.

If the config file is auto-discovered (no explicit --config) and cannot be parsed, the server logs a warning and continues with CLI/env/default values only.

Server Configuration

Listen Address

Address and port to bind to:

FlagEnv VarDefault
--listen-addrFLUREE_LISTEN_ADDR0.0.0.0:8090
fluree-server --listen-addr 0.0.0.0:9090

Storage Path

Path for file-based storage. If not specified, defaults to .fluree/storage relative to the working directory (the same location used by fluree init):

FlagEnv VarDefault
--storage-pathFLUREE_STORAGE_PATH.fluree/storage
# Explicit storage path (e.g. production)
fluree-server --storage-path /var/lib/fluree

# Default: uses .fluree/storage in the working directory
fluree-server

Connection Configuration (S3, DynamoDB, etc.)

For storage backends beyond local files — S3, DynamoDB nameservice, split commit/index storage, encryption — use a JSON-LD connection config file:

FlagEnv VarDefault
--connection-configFLUREE_CONNECTION_CONFIGNone

When set, the server builds its storage and nameservice from the connection config file instead of using --storage-path. The file uses the same JSON-LD format as the Fluree API connection config.

# S3 + DynamoDB via connection config
fluree server run --connection-config /etc/fluree/connection.jsonld

# Or via environment variable
FLUREE_CONNECTION_CONFIG=/etc/fluree/connection.jsonld fluree server run

Example connection config (connection.jsonld):

{
  "@context": {
    "@base": "https://ns.flur.ee/config/connection/",
    "@vocab": "https://ns.flur.ee/system#"
  },
  "@graph": [
    {
      "@id": "commitStorage",
      "@type": "Storage",
      "s3Bucket": "fluree-commits",
      "s3Prefix": "fluree-data/"
    },
    {
      "@id": "indexStorage",
      "@type": "Storage",
      "s3Bucket": "fluree-indexes--use1-az4--x-s3"
    },
    {
      "@id": "publisher",
      "@type": "Publisher",
      "dynamodbTable": "fluree-nameservice",
      "dynamodbRegion": "us-east-1"
    },
    {
      "@id": "conn",
      "@type": "Connection",
      "commitStorage": { "@id": "commitStorage" },
      "indexStorage": { "@id": "indexStorage" },
      "primaryPublisher": { "@id": "publisher" }
    }
  ]
}

Behavior notes:

  • --connection-config and --storage-path are mutually exclusive. If both are set, --connection-config takes precedence (a warning is logged).
  • Server-level settings (--cache-max-mb, --indexing-enabled, --reindex-min-bytes, --reindex-max-bytes) override any equivalent values from the connection config.
  • --indexing-enabled defaults to true. Pass --indexing-enabled=false only when a separate peer/indexer process owns index maintenance for the same storage.
  • AWS credentials and region are resolved via the standard AWS SDK chain (env vars, instance profile, ~/.aws/config, etc.) — they are not part of the connection config.
  • The connection config can use envVar indirection for sensitive fields like S3 bucket names or encryption keys (see ConfigurationValue).

Config file equivalent:

[server]
connection_config = "/etc/fluree/connection.jsonld"

Capabilities by Backend

Not all nameservice backends support all features. The server checks capabilities at runtime:

FeatureFile (local)DynamoDBStorage-backed
Query / transactYesYesYes
Event subscriptionsYesNoNo
Default context (read)YesYesYes
Default context (write)YesYesNo

If a capability is not available, the server returns an appropriate error (e.g., 501 for event subscriptions with DynamoDB).

CORS

Enable Cross-Origin Resource Sharing:

FlagEnv VarDefault
--cors-enabledFLUREE_CORS_ENABLEDtrue

When enabled, allows requests from any origin.

Body Limit

Maximum request body size in bytes:

FlagEnv VarDefault
--body-limitFLUREE_BODY_LIMIT52428800 (50MB)

Log Level

Logging verbosity:

FlagEnv VarDefault
--log-levelFLUREE_LOG_LEVELinfo

Options: trace, debug, info, warn, error

Cache Size

Global cache budget (MB):

FlagEnv VarDefault
--cache-max-mbFLUREE_CACHE_MAX_MB30/40/50% of RAM (tiered: <4GB / 4-8GB / ≥8GB)

Background Indexing

Enable background indexing and configure novelty backpressure thresholds:

FlagEnv VarDefaultDescription
--indexing-enabledFLUREE_INDEXING_ENABLEDtrueEnable background indexing (set false only when an external indexer process owns this storage)
--reindex-min-bytesFLUREE_REINDEX_MIN_BYTES100000Soft threshold (triggers background indexing)
--reindex-max-bytesFLUREE_REINDEX_MAX_BYTES20% of system RAM (256 MB fallback)Hard threshold (blocks commits until reindexed)

Config file equivalent:

[server.indexing]
enabled = true
reindex_min_bytes = 100000         # 100 KB — soft trigger
# reindex_max_bytes = 536870912    # 512 MB — defaults to 20% of system RAM if omitted

Server Role Configuration

Server Role

Operating mode: transaction server or query peer:

FlagEnv VarDefault
--server-roleFLUREE_SERVER_ROLEtransaction

Options:

  • transaction: Write-enabled, produces events stream
  • peer: Read-only, subscribes to transaction server

Transaction Server URL (Peer Mode)

Base URL of the transaction server (required in peer mode):

FlagEnv Var
--tx-server-urlFLUREE_TX_SERVER_URL
fluree-server \
  --server-role peer \
  --tx-server-url http://tx.internal:8090

Authentication Configuration

Replication vs Query Access

Fluree enforces a hard boundary between replication-scoped and query-scoped access:

  • Replication (fluree.storage.*): Raw commit and index block transfer for peer sync and CLI fetch/pull/push. These operations bypass dataset policy (data must be bit-identical). Replication tokens are operator/service-account credentials — never issue them to end users.
  • Query (fluree.ledger.read/write.*): Application-level data access through the query engine with full dataset policy enforcement. Query tokens are appropriate for end users and application service accounts.

A user holding only query-scoped tokens cannot clone or pull a ledger. They can fluree track a remote ledger (forwarding queries/transactions to the server) but cannot replicate its storage locally.

Events Endpoint Authentication

Protect the /v1/fluree/events SSE endpoint:

FlagEnv VarDefault
--events-auth-modeFLUREE_EVENTS_AUTH_MODEnone
--events-auth-audienceFLUREE_EVENTS_AUTH_AUDIENCENone
--events-auth-trusted-issuerFLUREE_EVENTS_AUTH_TRUSTED_ISSUERSNone

Modes:

  • none: No authentication
  • optional: Accept tokens but don't require them
  • required: Require valid Bearer token

Supports both Ed25519 (embedded JWK) and OIDC/JWKS (RS256) tokens when the oidc feature is enabled and --jwks-issuer is configured. For OIDC tokens, issuer trust is implicit — only tokens signed by keys from configured JWKS endpoints will verify. For Ed25519 tokens, the issuer must appear in --events-auth-trusted-issuer.

# Ed25519 tokens only
fluree-server \
  --events-auth-mode required \
  --events-auth-trusted-issuer did:key:z6Mk...

# OIDC + Ed25519 (both work simultaneously)
fluree-server \
  --events-auth-mode required \
  --jwks-issuer "https://auth.example.com=https://auth.example.com/.well-known/jwks.json" \
  --events-auth-trusted-issuer did:key:z6Mk...

Data API Authentication

Protect query/transaction endpoints (including /v1/fluree/query/{ledger...}, /v1/fluree/insert/{ledger...}, /v1/fluree/upsert/{ledger...}, /v1/fluree/update/{ledger...}, /v1/fluree/info/{ledger...}, and /v1/fluree/exists/{ledger...}):

FlagEnv VarDefault
--data-auth-modeFLUREE_DATA_AUTH_MODEnone
--data-auth-audienceFLUREE_DATA_AUTH_AUDIENCENone
--data-auth-trusted-issuerFLUREE_DATA_AUTH_TRUSTED_ISSUERSNone
--data-auth-default-policy-classFLUREE_DATA_AUTH_DEFAULT_POLICY_CLASSNone

Modes:

  • none: No authentication (default)
  • optional: Accept tokens but don't require them (development only)
  • required: Require either a valid Bearer token or a signed request (JWS/VC)

Bearer token scopes:

  • Read: fluree.ledger.read.all=true or fluree.ledger.read.ledgers=[...]
  • Write: fluree.ledger.write.all=true or fluree.ledger.write.ledgers=[...]

Back-compat: fluree.storage.* claims imply read scope for data endpoints.

fluree-server \
  --data-auth-mode required \
  --data-auth-trusted-issuer did:key:z6Mk...

OIDC / JWKS Token Verification

When the oidc feature is enabled, the server can verify JWT tokens signed by external identity providers (e.g., Fluree Cloud Service) using JWKS (JSON Web Key Set) endpoints. This is in addition to the existing embedded-JWK (Ed25519 did:key) verification path.

Dual-path dispatch: The server inspects each Bearer token's header:

  • Embedded JWK (Ed25519): Uses the existing verify_jws() path — no JWKS needed.
  • kid header (RS256): Uses OIDC/JWKS path — fetches the signing key from the issuer's JWKS endpoint.

Both paths coexist; no configuration change is needed for existing Ed25519 tokens.

FlagEnv VarDefaultDescription
--jwks-issuerFLUREE_JWKS_ISSUERSNoneOIDC issuer to trust (repeatable)
--jwks-cache-ttlFLUREE_JWKS_CACHE_TTL300JWKS cache TTL in seconds

The --jwks-issuer flag takes the format <issuer_url>=<jwks_url>:

fluree-server \
  --data-auth-mode required \
  --jwks-issuer "https://solo.example.com=https://solo.example.com/.well-known/jwks.json"

For multiple issuers, repeat the flag or use comma separation in the env var:

# CLI flags (repeatable)
fluree-server \
  --jwks-issuer "https://issuer1.example.com=https://issuer1.example.com/.well-known/jwks.json" \
  --jwks-issuer "https://issuer2.example.com=https://issuer2.example.com/.well-known/jwks.json"

# Environment variable (comma-separated)
export FLUREE_JWKS_ISSUERS="https://issuer1.example.com=https://issuer1.example.com/.well-known/jwks.json,https://issuer2.example.com=https://issuer2.example.com/.well-known/jwks.json"

Behavior details:

  • JWKS endpoints are fetched at startup (warm()) but the server starts even if they're unreachable.
  • Keys are cached and refreshed when a kid miss occurs (rate-limited to one refresh per issuer every 10 seconds).
  • The token's iss claim must exactly match a configured issuer URL — unconfigured issuers are rejected immediately with a clear error.
  • Data API, events, admin, and storage proxy endpoints all support JWKS verification. A single --jwks-issuer flag enables OIDC tokens across all endpoint groups. MCP auth continues to use the existing Ed25519 path only.

Connection-Scoped SPARQL Scope Enforcement

When a Bearer token is present for connection-scoped SPARQL queries (/v1/fluree/query with Content-Type: application/sparql-query), the server enforces ledger scope:

  • FROM / FROM NAMED clauses are parsed to extract ledger IDs (name:branch).
  • Each ledger ID is checked against the token's read scope (fluree.ledger.read.all or fluree.ledger.read.ledgers).
  • Out-of-scope ledgers return 404 (no existence leak).
  • If no FROM clause is present, the query proceeds normally (the engine handles missing dataset errors).

Admin Endpoint Authentication

Protect /v1/fluree/create, /v1/fluree/drop, /v1/fluree/reindex, branch administration, and Iceberg mapping endpoints:

FlagEnv VarDefault
--admin-auth-modeFLUREE_ADMIN_AUTH_MODEnone
--admin-auth-trusted-issuerFLUREE_ADMIN_AUTH_TRUSTED_ISSUERSNone

Modes:

  • none: No authentication (development)
  • required: Require valid Bearer token (production)

Supports both Ed25519 (embedded JWK) and OIDC/JWKS (RS256) tokens when the oidc feature is enabled and --jwks-issuer is configured. For OIDC tokens, issuer trust is implicit — only tokens signed by keys from configured JWKS endpoints will verify. For Ed25519 tokens, the issuer must appear in --admin-auth-trusted-issuer or the fallback --events-auth-trusted-issuer.

# Ed25519 tokens only
fluree-server \
  --admin-auth-mode required \
  --admin-auth-trusted-issuer did:key:z6Mk...

# OIDC (trust comes from --jwks-issuer, no did:key issuers needed)
fluree-server \
  --admin-auth-mode required \
  --jwks-issuer "https://auth.example.com=https://auth.example.com/.well-known/jwks.json"

If no admin-specific issuers are configured, falls back to --events-auth-trusted-issuer.

MCP Endpoint Authentication

Protect the /mcp Model Context Protocol endpoint:

FlagEnv VarDefault
--mcp-enabledFLUREE_MCP_ENABLEDfalse
--mcp-auth-trusted-issuerFLUREE_MCP_AUTH_TRUSTED_ISSUERSNone
fluree-server \
  --mcp-enabled \
  --mcp-auth-trusted-issuer did:key:z6Mk...

Peer Mode Configuration

Peer Subscription

Configure what the peer subscribes to:

FlagDescription
--peer-subscribe-allSubscribe to all ledgers and graph sources
--peer-ledger <ledger-id>Subscribe to specific ledger (repeatable)
--peer-graph-source <ledger-id>Subscribe to specific graph source (repeatable)
fluree-server \
  --server-role peer \
  --tx-server-url http://tx:8090 \
  --peer-subscribe-all

Or subscribe to specific resources:

fluree-server \
  --server-role peer \
  --tx-server-url http://tx:8090 \
  --peer-ledger books:main \
  --peer-ledger users:main

Peer Events Configuration

FlagEnv VarDescription
--peer-events-urlFLUREE_PEER_EVENTS_URLCustom events URL (default: {tx_server_url}/v1/fluree/events)
--peer-events-tokenFLUREE_PEER_EVENTS_TOKENBearer token for events (supports @filepath)

Peer Reconnection

FlagDefaultDescription
--peer-reconnect-initial-ms1000Initial reconnect delay
--peer-reconnect-max-ms30000Maximum reconnect delay
--peer-reconnect-multiplier2.0Backoff multiplier

Peer Storage Access

FlagEnv VarDefault
--storage-access-modeFLUREE_STORAGE_ACCESS_MODEshared

Options:

  • shared: Direct storage access (requires --storage-path or --connection-config)
  • proxy: Proxy reads through transaction server

For proxy mode:

FlagEnv Var
--storage-proxy-tokenFLUREE_STORAGE_PROXY_TOKEN
--storage-proxy-token-fileFLUREE_STORAGE_PROXY_TOKEN_FILE

Storage Proxy Configuration (Transaction Server)

Storage proxy provides replication-scoped access to raw storage for peer servers and CLI replication commands (fetch/pull/push). Tokens must carry fluree.storage.* claims — query-scoped tokens (fluree.ledger.read/write.*) are not sufficient. See Replication vs Query Access above.

Enable storage proxy endpoints for peers without direct storage access:

FlagEnv VarDefault
--storage-proxy-enabledFLUREE_STORAGE_PROXY_ENABLEDfalse
--storage-proxy-trusted-issuerFLUREE_STORAGE_PROXY_TRUSTED_ISSUERSNone
--storage-proxy-default-identityFLUREE_STORAGE_PROXY_DEFAULT_IDENTITYNone
--storage-proxy-default-policy-classFLUREE_STORAGE_PROXY_DEFAULT_POLICY_CLASSNone
--storage-proxy-debug-headersFLUREE_STORAGE_PROXY_DEBUG_HEADERSfalse
# Ed25519 trust (did:key):
fluree-server \
  --storage-proxy-enabled \
  --storage-proxy-trusted-issuer did:key:z6Mk...

# OIDC/JWKS trust (same --jwks-issuer flag used by other endpoints):
fluree-server \
  --storage-proxy-enabled \
  --jwks-issuer "https://solo.example.com=https://solo.example.com/.well-known/jwks.json"

JWKS support: When --jwks-issuer is configured, storage proxy endpoints accept RS256 OIDC tokens in addition to Ed25519 JWS tokens. The --jwks-issuer flag is shared with data, admin, and events endpoints — a single flag enables OIDC across all endpoint groups.

Complete Configuration Examples

Development (Memory Storage)

fluree-server \
  --log-level debug

Single Server (File Storage)

fluree-server \
  --storage-path /var/lib/fluree \
  --indexing-enabled \
  --log-level info

Production with Admin Auth

fluree-server \
  --storage-path /var/lib/fluree \
  --indexing-enabled \
  --admin-auth-mode required \
  --admin-auth-trusted-issuer did:key:z6Mk... \
  --log-level info

Transaction Server with Events Auth

fluree-server \
  --storage-path /var/lib/fluree \
  --events-auth-mode required \
  --events-auth-trusted-issuer did:key:z6Mk... \
  --storage-proxy-enabled \
  --admin-auth-mode required

Production with OIDC (All Endpoints)

fluree-server \
  --storage-path /var/lib/fluree \
  --indexing-enabled \
  --jwks-issuer "https://auth.example.com=https://auth.example.com/.well-known/jwks.json" \
  --data-auth-mode required \
  --events-auth-mode required \
  --admin-auth-mode required \
  --storage-proxy-enabled

Query Peer (Shared Storage)

fluree-server \
  --server-role peer \
  --tx-server-url http://tx.internal:8090 \
  --storage-path /var/lib/fluree \
  --peer-subscribe-all \
  --peer-events-token @/etc/fluree/peer-token.jwt

Query Peer (Proxy Storage)

fluree-server \
  --server-role peer \
  --tx-server-url http://tx.internal:8090 \
  --storage-access-mode proxy \
  --storage-proxy-token @/etc/fluree/storage-proxy.jwt \
  --peer-subscribe-all \
  --peer-events-token @/etc/fluree/peer-token.jwt

S3 + DynamoDB (Connection Config)

fluree server run \
  --connection-config /etc/fluree/connection.jsonld \
  --indexing-enabled \
  --reindex-min-bytes 100000 \
  --reindex-max-bytes 5000000 \
  --cache-max-mb 4096

With a config file:

[server]
connection_config = "/etc/fluree/connection.jsonld"
cache_max_mb = 4096

[server.indexing]
enabled = true
reindex_min_bytes = 100000
reindex_max_bytes = 5000000

[server.auth.data]
mode = "required"
trusted_issuers = ["did:key:z6Mk..."]

S3 Peer (Shared Storage via Connection Config)

fluree server run \
  --server-role peer \
  --tx-server-url http://tx.internal:8090 \
  --connection-config /etc/fluree/connection.jsonld \
  --peer-subscribe-all \
  --peer-events-token @/etc/fluree/peer-token.jwt

Environment Variables Reference

VariableDescriptionDefault
FLUREE_HOMEGlobal Fluree directory (unified config + data)Platform dirs (see Global Directory Layout)
FLUREE_CONFIGConfig file path.fluree/config.{toml,jsonld} (auto-discovered)
FLUREE_PROFILEConfiguration profile nameNone
FLUREE_LISTEN_ADDRServer address:port0.0.0.0:8090
FLUREE_STORAGE_PATHFile storage path.fluree/storage
FLUREE_CONNECTION_CONFIGJSON-LD connection config file pathNone
FLUREE_CORS_ENABLEDEnable CORStrue
FLUREE_INDEXING_ENABLEDEnable background indexingtrue
FLUREE_REINDEX_MIN_BYTESSoft reindex threshold (bytes)100000
FLUREE_REINDEX_MAX_BYTESHard reindex threshold (bytes)20% of system RAM (256 MB fallback)
FLUREE_CACHE_MAX_MBGlobal cache budget (MB)30/40/50% of RAM (tiered: <4GB / 4-8GB / ≥8GB)
FLUREE_BODY_LIMITMax request body bytes52428800
FLUREE_LOG_LEVELLog levelinfo
FLUREE_SERVER_ROLEServer roletransaction
FLUREE_TX_SERVER_URLTransaction server URLNone
FLUREE_EVENTS_AUTH_MODEEvents auth modenone
FLUREE_EVENTS_AUTH_TRUSTED_ISSUERSEvents trusted issuersNone
FLUREE_DATA_AUTH_MODEData API auth modenone
FLUREE_DATA_AUTH_AUDIENCEData API expected audienceNone
FLUREE_DATA_AUTH_TRUSTED_ISSUERSData API trusted issuersNone
FLUREE_DATA_AUTH_DEFAULT_POLICY_CLASSData API default policy classNone
FLUREE_ADMIN_AUTH_MODEAdmin auth modenone
FLUREE_ADMIN_AUTH_TRUSTED_ISSUERSAdmin trusted issuersNone
FLUREE_MCP_ENABLEDEnable MCP endpointfalse
FLUREE_MCP_AUTH_TRUSTED_ISSUERSMCP trusted issuersNone
FLUREE_STORAGE_ACCESS_MODEPeer storage modeshared
FLUREE_STORAGE_PROXY_ENABLEDEnable storage proxyfalse

Command-Line Reference

fluree-server --help

Best Practices

1. Keep Secrets Out of Config Files

Tokens and credentials should not be stored as plaintext in config files (which may be committed to version control or readable by other processes). Three options, in order of preference:

Environment variables (recommended for production):

export FLUREE_PEER_EVENTS_TOKEN=$(cat /etc/fluree/token.jwt)
export FLUREE_STORAGE_PROXY_TOKEN=$(cat /etc/fluree/proxy-token.jwt)

@filepath references in config files or CLI flags (reads the file at startup):

[server.peer]
events_token = "@/etc/fluree/peer-token.jwt"
storage_proxy_token = "@/etc/fluree/proxy-token.jwt"
--peer-events-token @/etc/fluree/token.jwt

Direct values (development only): If a secret-bearing field contains a literal token in the config file, the server logs a warning at startup recommending @filepath or env vars.

The following config file fields support @filepath resolution:

Config file keyEnv var alternative
peer.events_tokenFLUREE_PEER_EVENTS_TOKEN
peer.storage_proxy_tokenFLUREE_STORAGE_PROXY_TOKEN

2. Enable Admin Auth in Production

Always protect admin endpoints in production:

fluree-server \
  --admin-auth-mode required \
  --admin-auth-trusted-issuer did:key:z6Mk...

3. Use File Storage for Persistence

Memory storage is lost on restart:

# Development only
fluree-server

# Production
fluree-server --storage-path /var/lib/fluree

4. Monitor Logs

Use structured logging for production:

fluree-server --log-level info 2>&1 | jq .

Remote Connections

Remote connections enable SPARQL SERVICE federation against other Fluree instances. A remote connection maps a name to a server URL and bearer token. Once registered, queries can reference any ledger on that server using SERVICE <fluree:remote:<name>/<ledger>> { ... }.

Rust API

Register remote connections on the FlureeBuilder:

let fluree = FlureeBuilder::file("./data")
    .remote_connection("acme", "https://acme-fluree.example.com", Some(token))
    .remote_connection("partner", "https://partner.example.com", None)
    .build()?;

Each call registers a named connection. The name is used in SPARQL queries:

SERVICE <fluree:remote:acme/customers:main> { ?s ?p ?o }
SERVICE <fluree:remote:partner/inventory:main> { ?item ex:sku ?sku }

Connection Parameters

ParameterDescription
nameAlias used in fluree:remote:<name>/... URIs
base_urlServer URL (e.g., https://acme-fluree.example.com). The query path /v1/fluree/query/{ledger} is appended automatically.
tokenOptional bearer token for authentication. Sent as Authorization: Bearer <token> on every request.

The default per-request timeout is 30 seconds. Requests that exceed this produce a query error (or empty results with SERVICE SILENT).

Security

Bearer tokens are stored in memory on the Fluree instance. They are never serialized to storage, included in nameservice records, or exposed through info/admin endpoints. If the token needs rotation, rebuild the Fluree instance with an updated token, or use set_remote_service() to inject a custom executor with token refresh logic.

Feature Flag

The HTTP transport for remote SERVICE requires the search-remote-client Cargo feature (which enables reqwest). Without this feature, remote connections can be registered but queries against them will fail at runtime. The feature is enabled by default in the server binary.

See SPARQL: Remote Fluree Federation for query syntax and examples.

Related Documentation