Configuration
TKeeper loads configuration using a layered merge model. Multiple sources can provide values for the same keys; higher-priority sources override lower-priority ones.
Supported file syntaxes:
- HOCON (
.conf) - JSON (
.json) - Java properties (
.properties)
Configuration precedence
Final configuration is assembled in this order (highest priority first):
- System properties (
-D...) - External configuration (from
keeper.config.location/KEEPER_CONFIG_LOCATION) - Profile configuration (
application-<profile>.*from classpath) - Base configuration (
application.*from classpath) - Reference configuration (
reference.*from classpath)
If the same key is present in multiple sources, the value from the higher-priority source wins.
Selecting a profile
A profile enables loading an additional classpath resource named application-<profile>.*.
Set the profile via:
- System property:
-Dkeeper.profile=<profile> - Environment variable:
KEEPER_PROFILE=<profile>
Example:
-Dkeeper.profile=prod
This loads application-prod.conf (or .json / .properties) from the classpath (if present) and merges it according to the precedence rules above.
Supplying external configuration
External configuration can be supplied via:
- System property:
-Dkeeper.config.location=<locations> - Environment variable:
KEEPER_CONFIG_LOCATION=<locations>
<locations> is a comma-separated list. Each location is loaded and merged (later locations act as fallback for earlier ones).
Supported location forms
-
Classpath resource
-Dkeeper.config.location=classpath:application-prod -
HTTP/HTTPS URL
-Dkeeper.config.location=https://example.com/tkeeper/application.conf -
File path
-Dkeeper.config.location=/etc/tkeeper/application.conf -
Directory path
-Dkeeper.config.location=/etc/tkeeper
If a directory is provided, TKeeper searches for one of the following files inside it (first match wins):
application.confapplication.jsonapplication.properties
If no candidate file exists, startup fails.
Multiple locations
-Dkeeper.config.location=/etc/tkeeper,https://example.com/overrides.conf
Developer configuration (DevConfig)
DevConfig is an optional developer-mode configuration that supplies:
- a static token (
keeper.dev.token) - a permissions list (
keeper.dev.permissions)
DevConfig is loaded only when:
keeper.dev.enabled = trueis set in the main configuration, and- the system property
keeper.dev.config.locationis provided.
Enable DevConfig
-Dkeeper.dev.enabled=true \
-Dkeeper.dev.config.location=/etc/tkeeper/dev.conf
Dev config location forms
keeper.dev.config.location supports the same location forms as external configuration:
- classpath:...
- http(s)://...
- file path
- directory path
If a directory is provided, TKeeper searches for one of the following files inside it (first match wins):
dev.confdev.jsondev.properties
DevConfig structure
Example dev.conf:
keeper {
dev {
token = "dev-token-change-me"
permissions = [
"tkeeper.key.sample-key.sign",
...
]
}
}
Key configuration blocks
This section summarizes the main configuration keys used by TKeeper.
auth
If auth is missing entirely, TKeeper defaults to:
auth.type = "dev"
Default:
auth {
type = ${?KEEPER_AUTH_TYPE}
type = "dev"
}
boot
boot.token (or KEEPER_BOOT_TOKEN) is a cluster-wide bootstrap secret used during keeper-to-keeper startup and reconnects.
Requirements:
- The boot token MUST be identical on all keepers in the same cluster.
- The token is used for bootstrapping trust between peers: during startup/restart a keeper uses it to pin and verify the peer’s internal public key.
- If keepers use different boot tokens, peers will fail to establish trusted internal connectivity.
Configuration:
boot {
token = ${?KEEPER_BOOT_TOKEN}
}
keeper
Common operational settings:
keeper {
database {
path = ${?KEEPER_DATABASE_PATH}
path = "data/keeper"
}
audit {
enabled = ${?KEEPER_AUDIT_ENABLED}
enabled = false
}
}
Note
Keeper will create folder defined by path you specified.
keeper.providers (seal provider selection)
Select the provider:
keeper {
providers {
selected = ${?KEEPER_SEAL_SELECTED}
selected = "shamir"
}
}
Provider-specific configuration must be present for the selected provider. For example, for shamir:
keeper {
providers {
selected = "shamir"
shamir {
total = ${?KEEPER_SEAL_SHAMIR_TOTAL}
total = 3
threshold = ${?KEEPER_SEAL_SHAMIR_THRESHOLD}
threshold = 2
}
}
}
keeper.server (public and internal servers)
TKeeper exposes two servers:
keeper.server.publickeeper.server.internal
Public server is used for inbound connections FROM CLIENTS, while internal server is used for KEEPER-TO-KEEPER communication.
Each supports:
host,portidle-timeoutmax-request-length- optional
tls { ... }
Example:
keeper {
server {
public {
host = ${?KEEPER_HOST}
host = "localhost" # default
port = ${?KEEPER_PORT}
port = 8080 # default
idle-timeout = ${?KEEPER_IDLE_TIMEOUT}
idle-timeout = 30s # default
max-request-length = ${?KEEPER_MAX_REQUEST_LENGTH}
max-request-length = 10485760 # default
tls {
enabled = ${?KEEPER_TLS_ENABLED}
enabled = false # default
key-store-path = ${?KEEPER_TLS_KEY_STORE_PATH}
key-store-password = ${?KEEPER_TLS_KEY_STORE_PASSWORD}
key-store-type = ${?KEEPER_TLS_KEY_STORE_TYPE}
certificate-chain-path = ${?KEEPER_TLS_CERT_CHAIN_PATH}
private-key-path = ${?KEEPER_TLS_PRIVATE_KEY_PATH}
private-key-password = ${?KEEPER_TLS_PRIVATE_KEY_PASSWORD}
}
}
internal {
host = ${?KEEPER_INTERNAL_HOST}
host = "localhost" # default
port = ${?KEEPER_INTERNAL_PORT}
port = 9090 # default
idle-timeout = ${?KEEPER_INTERNAL_IDLE_TIMEOUT}
idle-timeout = 30s # default
max-request-length = ${?KEEPER_INTERNAL_MAX_REQUEST_LENGTH}
max-request-length = 10485760 # default
tls {
enabled = ${?KEEPER_INTERNAL_TLS_ENABLED}
enabled = false # default
}
}
}
}
keeper.peers (cluster topology)
keeper.peers defines how this node reaches other keepers in the cluster. Each entry must point to the internal server URL of a peer (keeper-to-keeper traffic), not the public client-facing server.
Rules:
- Every keeper in the cluster must have a unique
id. internal-urlmust reference the peer’s internal listener (keeper.server.internal), including its port.- This list includes all other peers excluding local node.
Example:
keeper {
# .... your other config ...
peers = [
{ id = 1, internal-url = "http://localhost:9091" },
{ id = 2, internal-url = "http://localhost:9092" }
]
}
keeper.client (outbound TLS)
Client TLS settings (used for outbound connections where applicable):
keeper {
client {
tls = ${?KEEPER_CLIENT_TLS}
tls = false
trust-store-path = ${?KEEPER_CLIENT_TRUST_STORE_PATH}
trust-store-password = ${?KEEPER_CLIENT_TRUST_STORE_PASSWORD}
}
}
keeper.csp
Configures the Content-Security-Policy (or Content-Security-Policy-Report-Only) response header for the built-in UI (/ui/**).
This configuration is secure by default.
Example:
keeper {
csp {
report-only = false
default-src = ["'self'"]
base-uri = ["'self'"]
object-src = ["'none'"]
frame-ancestors = ["'none'"]
script-src = ["'self'"]
style-src = ["'self'"]
img-src = ["'self'", "data:"]
font-src = ["'self'", "data:"]
connect-src = ["'self'"]
form-action = ["'self'"]
connect-extra = []
form-action-extra = []
img-extra = []
oidc-auto-connect = true
}
}
How values are built
- Each directive is configured as a list of tokens. At runtime, tokens are joined with a single space.
- Example:
["'self'", "data:"]→img-src 'self' data: *-extralists are appended to the corresponding directive:connect-extra→ appended toconnect-srcform-action-extra→ appended toform-actionimg-extra→ appended toimg-src- If
report-only = true, the server emitsContent-Security-Policy-Report-Only. Otherwise it emitsContent-Security-Policy.
Options
-
report-only(boolean, default:false)
Emit the policy in report-only mode (browser reports violations, does not block). -
default-src(list, default: ["'self'"])
Fallback source list for resource types without a specific directive. -
base-uri(list, default: ["'self'"])
Restricts the document base URL (<base>). -
object-src(list, default: ["'none'"])
Disables plug-in content. -
frame-ancestors(list, default: ["'none'"])
Prevents embedding the UI into frames/iframes (clickjacking protection). -
script-src(list, default: ["'self'"])
Script source policy. -
style-src(list, default: ["'self'"])
Stylesheet source policy. -
img-src(list, default: ["'self'", "data:"])
Image source policy.data:is allowed for embedded images/icons. -
font-src(list, default: ["'self'", "data:"])
Font source policy. Keepdata:only if you intentionally embed fonts. -
connect-src(list, default: ["'self'"])
Network targets forfetch/XHR/EventSource/WebSocket (if used). -
form-action(list, default: ["'self'"])
Allowed form submission targets. -
connect-extra(list, default: [])
Additional sources appended toconnect-src. -
form-action-extra(list, default: [])
Additional sources appended toform-action. -
img-extra(list, default: [])
Additional sources appended toimg-src. -
oidc-auto-connect(boolean, default:true)
Enables automatic CSP allowances required by the UI OIDC flow. See Auth section.
Minimal startup example
Using an external config file plus environment-provided boot token:
export KEEPER_BOOT_TOKEN="..."
export KEEPER_CONFIG_LOCATION="/etc/tkeeper/application.conf"
java -jar tkeeper.jar
If you need system-property overrides:
java \
-Dkeeper.config.location=/etc/tkeeper/application.conf \
-jar tkeeper.jar