Configuration
All properties bind under the cortex prefix.
ontologies, shapes, and rules each accept a list of
classpath:/file: resources, merged in order.
Core
| Property | Default | Description |
|---|---|---|
cortex.persistent | false | Persist approved assertions to a TDB2 store on disk. When false, held in an in-memory TDB2 dataset. Either way the inference closure and full-text index are always an in-memory cache, rebuilt on every startup. |
cortex.assertionsLocation | .cortex/db | Directory of the TDB2 store, used only when cortex.persistent=true. |
cortex.ontologies | classpath:ontology.ttl | The ontologies the graph is built on (Turtle), merged in order. |
cortex.shapes | classpath:ontology.shapes | The SHACL shapes ingested assertions are validated against, merged in order. |
cortex.rules | classpath:ontology.rules | The Jena rules used for inference, concatenated in order. |
cortex.search.viewHalfLife | 30d | How long it takes a view's contribution to search ranking to halve. Results are ranked by textual relevance, then weighted by how often each resource has been deliberately opened. Set 0 to disable decay and weight by the raw lifetime count instead. The weight is bounded either way, so popularity reorders comparable results rather than overriding relevance. |
cortex.web.enabled | true | Register the web UI controllers. Set false for the graph without the UI. |
cortex.mcp.enabled | true | Register the MCP tools and resources. Set false for the graph without an MCP server. |
cortex.persistent=true, the TDB2 store
is opened with TDB2Factory.connectDataset, which does not support two JVMs opening
the same directory. Run one instance per persistent store directory.
S3 client
| Property | Default | Description |
|---|---|---|
cortex.s3.enabled | false | Register the S3Client bean. Independent of backup and restore, though both require it. |
cortex.s3.endpoint | unset | The S3 endpoint, e.g. http://localhost:9000 for MinIO. When unset, the AWS endpoint for the region is used. |
cortex.s3.bucket | unset | The bucket backups are uploaded to. Required when backups are enabled. |
cortex.s3.region | us-east-1 | The region to sign for. Required by the SDK even against S3-compatible stores that ignore it. |
cortex.s3.auth | default | default (AWS credential chain), static (the key/secret below), or anonymous (no credentials). |
cortex.s3.accessKeyId | unset | Access key. Required when auth=static. |
cortex.s3.secretAccessKey | unset | Secret key. Required when auth=static. |
cortex.s3.pathStyleAccess | false | Address buckets as a path segment (endpoint/bucket/key) rather than a subdomain. MinIO and most S3-compatible stores need this. |
cortex.s3.proxy.endpoint | unset | HTTP proxy to reach S3 through. Setting it is what enables the proxy — there is no separate flag. |
cortex.s3.proxy.username / password | unset | Proxy credentials, when it requires authentication. |
cortex.s3.proxy.nonProxyHosts | unset | Hosts to reach directly, bypassing the proxy. |
cortex.s3.proxy.useSystemPropertyValues | false | Fall back to the http(s).proxyHost JVM properties. The AWS SDK defaults this to true; Cortex does not. |
cortex.s3.proxy.useEnvironmentVariableValues | false | Fall back to HTTP_PROXY/HTTPS_PROXY/NO_PROXY. The AWS SDK defaults this to true; Cortex does not. |
HTTPS_PROXY
would otherwise silently route uploads through a proxy named nowhere in cortex.s3.*.
Cortex defaults both discovery flags to false. Set them to true if you
want the SDK's ambient discovery.
Scheduled backups
A Quartz job periodically snapshots the whole assertions dataset — approved
assertions, every staged branch, and the provenance graph — via TDB2's own
DatabaseMgr.backup (gzipped N-Quads, taken inside a read transaction, so it does
not lock out ingestion or approval) and uploads it to S3. This is the real backup mechanism;
/export is not.
| Property | Default | Description |
|---|---|---|
cortex.backup.enabled | false | Register the scheduled backup job. |
cortex.backup.interval | 24h | How often a backup is taken. The first runs one interval after startup, not at startup. |
cortex.backup.keyPrefix | cortex/ | Prepended to the backup file name to form the S3 object key. Include a trailing / to group under a folder. |
cortex.backup.onShutdown | true | Take a final backup as the application shuts down, blocking shutdown until it has uploaded. Applies only when backups are enabled. |
Backups are off by default, so the starter does not bring their dependencies. Add:
implementation(platform("software.amazon.awssdk:bom:2.46.7"))
implementation("software.amazon.awssdk:s3")
implementation("software.amazon.awssdk:apache-client")
implementation("org.springframework.boot:spring-boot-starter-quartz")
apache-client is not optional: the s3 artifact ships only the async
Netty HTTP client, so without it the synchronous S3Client fails to build. Then
configure it — this targets a local MinIO with no authentication:
cortex:
persistent: true
backup:
enabled: true
interval: 6h
s3:
enabled: true
endpoint: http://localhost:9000
bucket: cortex-backups
region: us-east-1
auth: anonymous
path-style-access: true
cortex.persistent=true. A TDB2 backup is an admin
operation on an on-disk store; enabling backups without persistence — or with a missing bucket,
missing static credentials, a non-positive interval, or the dependencies above — fails at
startup rather than booting an app that reports healthy and never backs anything up.
Local backup files accumulate under
<cortex.assertionsLocation>/Backups/ and are never deleted — the upload is a
copy, not a move, so a bucket misconfiguration can never destroy data. Pruning is left to the
volume, or to an S3 lifecycle rule.
Backup on shutdown
Backups are scheduled, so a restart would otherwise discard every approval made since
the last one — up to a full cortex.backup.interval, 24 hours by default. Cortex
therefore takes one final backup as the application shuts down and blocks shutdown until
it has uploaded. It is on whenever backups are enabled; set
cortex.backup.onShutdown=false to turn it off without giving up scheduled
backups.
The final backup runs after the web server has stopped accepting requests and after the scheduler has quiesced — including waiting out a scheduled backup that happens to be in flight — so it snapshots a store nothing is still writing to. It is an ordinary backup under the same key prefix, so a restore picks it up as the most recent object with no extra configuration.
SIGKILL
after a grace period, size that period against how long a backup of your store actually takes.
Restore on startup
The inverse of a backup: on boot, download the most recent backup from S3 and load it into the store before the application serves traffic, so an instance whose local disk was replaced comes up with its data. The inference closure and index rebuild from the restored assertions as usual.
| Property | Default | Description |
|---|---|---|
cortex.restore.enabled | false | Download the latest backup under cortex.restore.keyPrefix and load it at startup. |
cortex.restore.keyPrefix | cortex/ | The S3 key prefix to look for backups under. Set it to match cortex.backup.keyPrefix if you customize that. |
Restore needs software.amazon.awssdk:s3 and apache-client plus an
enabled S3 client (Quartz is not needed — restore uses no scheduler):
cortex:
persistent: true
restore:
enabled: true
s3:
enabled: true
endpoint: http://localhost:9000
bucket: cortex-backups
region: us-east-1
auth: anonymous
path-style-access: true
SIGKILL able to lose work. An empty
bucket (a first-ever deploy) is not an
error — it logs and starts empty; every other misconfiguration fails the context. Leave it
false if S3 is not your source of truth.
The switch is independent of cortex.backup.enabled: an instance may restore from
another's uploads without scheduling backups of its own, or do both.