Configuration
Overview
Your node's configuration lives in two layers:
- Bootstrap configuration in
config.json. It locates persistent state and defines enough policy to start or unlock the node. In the standard container installation it is stored in the data volume at/data/unolock-node/config.json. - Runtime configuration, stored in the encrypted database and loaded after unlock.
Changes you make in the admin console's Settings view that need a restart are staged and promoted on the next start.
This page covers the settings most operators need. For the full reference, see configuration.md in the repository. The source schema is src/config/schema.ts.
Configuration groups
| Group | Contains |
|---|---|
node |
Stable node ID, data directory, environment |
network |
Mode, listener, external URL, origins, RP ID, TLS paths |
federation |
Lookup listener, Tor SOCKS endpoint, bootstrap peers |
registration |
Closed or code-based Safe registration |
client |
Hosted asset root and allowed external clients |
storage |
Archive root, SQLCipher path, provider, key protection, remote peer API |
features |
Receive Address and federation capability gates |
cluster |
WAL cycle cadence, checkpoint thresholds, receive limits and free-space reserve |
security |
Startup unlock policy and bounded rate limits |
Network modes
| Mode | Use |
|---|---|
disabledLocalOnly |
Loopback development and bootstrap only |
bootstrapRemote |
Temporary first-run remote setup |
reverseProxy |
Production node behind an HTTPS reverse proxy |
manualTls |
Node process uses operator certificate files directly |
Remote use requires an HTTPS external base URL, a matching WebAuthn RP ID and explicit allowed client origins. Remote HTTP and non-loopback internal lookup listeners are rejected.
Change a setting through the admin console
- Sign in to
https://node.example.com/adminand unlock the node. - Open Settings, record the current value, and enter the new one.
- Save the pending configuration.
-
Restart the node in a maintenance window:
sudo docker restart unolock-node -
Sign in, choose Unlock Node, and repeat the Setup and Diagnostics checks.
Container settings
The launcher packaging/docker/run-node.sh sets these values when it creates a container. Rerunning the launcher does not change an existing container. Record any custom settings so you can reapply them when you upgrade.
| Setting | Purpose |
|---|---|
--domain |
Permanent node hostname, for example node.example.com |
--image or UNOLOCK_IMAGE |
Image to run |
--engine or UNOLOCK_CONTAINER_ENGINE |
Container engine (docker) |
--name or UNOLOCK_CONTAINER_NAME |
Container name (default unolock-node) |
--volume or UNOLOCK_VOLUME_NAME |
Persistent volume (default unolock-node-data) |
UNOLOCK_EMAIL |
Optional ACME contact email for automatic certificates |
UNOLOCK_CERT, UNOLOCK_KEY, UNOLOCK_CA_CHAIN |
Operator-managed TLS: container paths to the full-chain PEM, private key PEM and optional intermediate chain |
UNOLOCK_WEBAUTHN_RP_ID |
Permanent WebAuthn RP domain retained across failover |
UNOLOCK_ALLOWED_CLIENT_ORIGINS |
Comma-separated exact HTTPS origins, including a standby or recovery origin |
For example, to set the ACME contact email when creating the container:
sudo env \
UNOLOCK_EMAIL=operator@example.com \
sh packaging/docker/run-node.sh --domain node.example.com
The launcher stores the validated domain, so ordinary restarts do not need the environment variables again.
To check configuration and DNS without building or starting anything:
sudo sh packaging/docker/run-node.sh --domain node.example.com --check
Use your own HTTPS certificate
The default installation obtains and renews its HTTPS certificate automatically. Use this only if you already manage certificates yourself.
-
Place readable PEM files inside the persistent node volume:
sudo docker volume create unolock-node-data sudo docker run --rm \ --entrypoint /bin/sh \ -v unolock-node-data:/data \ -v "$PWD/tls:/input:ro" \ "$UNOLOCK_IMAGE" \ -eu -c ' umask 077 mkdir -p /data/unolock-node/tls cp /input/*.pem /data/unolock-node/tls/ chown -R 10001:10001 /data/unolock-node/tls ' -
Create the container with the container paths:
export UNOLOCK_CERT=/data/unolock-node/tls/fullchain.pem export UNOLOCK_KEY=/data/unolock-node/tls/private-key.pem export UNOLOCK_CA_CHAIN=/data/unolock-node/tls/intermediate-chain.pem # optional sudo env UNOLOCK_CERT="$UNOLOCK_CERT" \ UNOLOCK_KEY="$UNOLOCK_KEY" \ UNOLOCK_CA_CHAIN="$UNOLOCK_CA_CHAIN" \ sh packaging/docker/run-node.sh --domain node.example.com
The launcher passes container paths. It does not mount arbitrary host paths. The certificate must cover the permanent node domain. Protect the private key outside the encrypted-data backup.
WebAuthn identity and recovery origins
Admin and Safe credentials use the same configured WebAuthn RP ID and exact origin allowlist. Restore a node behind its permanent public origin, such as https://node.example.com. Moving to a different host behind that origin does not change the WebAuthn identity.
If you need a separate recovery origin while DNS converges, place it below the permanent RP domain:
WebAuthn RP ID: node.example.com
Primary origin: https://node.example.com
Recovery origin: https://recovery.node.example.com
Configure the exact HTTPS origins on the recovery host while keeping the original RP ID:
sudo env \
UNOLOCK_WEBAUTHN_RP_ID=node.example.com \
UNOLOCK_ALLOWED_CLIENT_ORIGINS=https://node.example.com,https://recovery.node.example.com \
sh packaging/docker/run-node.sh --domain recovery.node.example.com
The recovery origin needs a valid certificate. Do not expose the restored node until the former node is fenced. Do not change the RP ID during recovery: credentials registered to the original RP ID cannot be used on an unrelated replacement domain.
This preserves WebAuthn identity. It does not enable replication or promotion. See Active/Standby and Failover.
Federation bootstrap peers
New nodes use the public UnoLock Production and Test federation onion services as bootstrap peers. These are entry points for peer discovery, not a dependency on one operator.
- Replace or clear
federation.bootstrapPeersthrough node administration, or - set
UNOLOCK_FEDERATION_BOOTSTRAP_PEERSto a comma-separated list of HTTP v3 onion URLs. Usenonefor an empty override.
Explicit peer lists, including empty lists and disabled entries, stay authoritative across restarts and upgrades. Defaults are never merged back into them. See Federation.
Attachment transfer storage
The config key storage.relayStoragePercent corresponds to Attachment transfer storage limit (%) in Settings. Restart the node to apply a change.
- The default is 20% of the total capacity of the filesystem that holds the archive root, not 20% of free space.
- Integer values from 0 through 100 are accepted. 0 disables new relay and message-attachment reservations.
- Message attachments uploaded through a Safe or UnoLock Drop share this budget with federation relays. Committed Safe data is not limited by it.
- Each admission reserves three ciphertext copies, with a minimum of 64 KiB per copy. A 5 GiB attachment needs slightly more than 15 GiB of temporary budget. Increase the percentage if the default is smaller than that.
- Lowering the percentage does not delete data or cancel admitted transfers. It prevents new reservations until usage fits again.
- Abandoned relay sessions expire after seven days. Ordinary message-upload reservations follow a 14-day idle cleanup.
- UnoLock Drop allows at most 20 pending files per Receive Address, within that address's attachment limit.
Windows client origin
Builds with the Windows client setting expose Allow the packaged Windows client in Settings. The equivalent configuration, merged with existing client settings, is:
"client": { "windows": { "enabled": true } }
It permits the packaged request origin https://tauri.localhost for API CORS only. It does not add that origin to Safe or Administrator WebAuthn trust. This setting defaults off. Save and restart after enabling it.
Key protection and unlock policy
Production nodes use tpm, admin-unlock or admin-unlock-tpm key protection, according to deployment posture. dev is for local testing only, and production startup rejects it.
The startup unlock policy is one of admin-required, tpm-unattended (where explicitly configured and supported), or unlocked (development posture only). See Restarts and Unlocking.
Cluster runtime defaults
These values apply only after an active member has been initialized and paired. They do not enable cluster mode by themselves.
| Field | Default | Purpose |
|---|---|---|
pollIntervalMs |
5,000 | Check whether age or size requires a WAL-cycle cut |
maxCycleAgeMs |
30,000 | Maximum ordinary interval between non-empty WAL cycles |
maxWalBytes |
16 MiB | Cut a cycle when the live WAL reaches this size |
maxRetainedCyclesBeforeCheckpoint |
64 | Rotate to a new verified baseline after this many retained cycles |
maxRetainedWalBytesBeforeCheckpoint |
1 GiB | Rotate to a new baseline when retained WAL bytes reach this amount |
maximumBaselineBytes |
1 TiB | Standby receive limit for an encrypted baseline |
maximumWalCycleBytes |
4 GiB | Standby receive limit for one immutable WAL cycle |
maximumArchiveObjectBytes |
64 GiB | Standby receive limit for one encrypted archive object |
minimumFreeBytes |
1 GiB | Free-space reserve kept available for replication and recovery |
maxWalBytes cannot exceed maximumWalCycleBytes.
Keep secrets out of reports
Do not publish or place in issue reports:
- protected node secret bundles or wrapping material;
- TLS or Tor private keys;
- database keys;
- admin credentials or registration codes;
- federation access proofs or transfer URLs;
- raw bootstrap peer lists from a private federation.
Admin status views may report whether a secret is configured, never its value.
FAQs
Where is config.json?
In the standard container installation it is at /data/unolock-node/config.json inside the unolock-node-data volume.
Why didn't my Settings change take effect?
Settings that need a restart are staged as pending configuration. Restart the node, sign in and unlock to apply and verify them.
Does rerunning the launcher change my container's settings?
No. Launcher options apply when a container is created. Record custom settings and reapply them when you replace the container during an upgrade.
Can I change my node's hostname?
No. Do not change the permanent URL or WebAuthn RP ID on a configured node. Admin and Safe passkeys depend on it.
Is a configuration accepted by an older document still valid?
Only if the current schema accepts it. Configuration rejected by src/config/schema.ts is not supported.