Headless CMS Configuration

The Headless CMS configuration file controls how an HCMS satellite instance behaves.

This XML Schema also serve as a documentation

About Headless CMS configuration

The Headless CMS configuration file controls how an HCMS satellite instance connects to the Censhare backend, registers and stores schemas, serves the REST API, handles authentication, and manages clustering and caching. Every aspect of a running satellite instance is driven by this file.

The configuration file is stored at a Censhare asset of type module.satellite.osgi.configuration (Module/Satellite/Satellite OSGI/Satellite OSGI configuration). This asset is connected to a parent asset of type module.satellite.configuration (Module/Satellite/Satellite configuration). The file is usually named HeadlessCms.xml, but the name is not significant.

This reference is intended for:

  • Administrators: who set up, configure, and maintain HCMS satellite instances in their Censhare environment.

  • Solution developers: who adjust HCMS behavior for specific customer requirements, such as tuning clustering, authentication, or caching settings.

The sections below document every XML element, attribute, allowed value, and default in the configuration schema.

Prerequisites

Before working with the Headless CMS configuration file, make sure you are familiar with the following topics:

  • HCMS First Steps: covers the initial setup of an HCMS instance, including creating the configuration asset and connecting it to Censhare.

  • HCMS Command Line Interface Tool: the CLI tool is used to create and manage HCMS configuration assets, including the file described in this reference.

  • Installation options: describes the available deployment methods for HCMS, such as Docker-based, AWS, and manual Linux installation.

Element: config

Attributes:

@version [ required | fixed: 1 ]

Children:

  • all of these elements:

    • [1, 1] '→datastore'
      » Configuration of the datastore backend; required, because storing data is primary function of Headless CMS.

    • [1, 1] '→schemaregistry'

    • [0, 1] '→cluster'

    • [0, 1] '→webhooks'

    • [1, 1] '→hostmappings'
      » Reference to Web Server configuration.

    • [1, 1] '→api'
      » REST API configuration.

    • [1, 1] '→auth'
      » Authentication and authorisation configuration. Details are described in Headless CMS documentation.

    • [0, 1] '→image'
      » Image Cache configuration; copied from ImageCacheService configuration.

    • [0, 1] '→cache'
      » Configuration of some caches.

Inner element: config/cache

Configuration of some caches.

Children:

  • all of these elements:

    • [0, 1] '→media-link'

Attributes:

@size [ required ] ↦ positiveInteger
@expiration [ required ] ↦ positiveInteger

Element: datastore

Attributes:

@name [ required ] ↦ string
Datastore used by the Headless CMS: must be instanceid of existing datastore configuration.
@default-domainstring
Default domain (1st domain) of newly created assets.
@default-domain2string
Default domain2 (second domain) of newly created assets.
@update-as-new-version [ default: true ] ↦ boolean
Should each update create new asset version or not?
This flag can be specified as part of schema, this value is used only when there is no such declaration present.

WARNING: Enable only when connected to Censhare server version 2019.2 or newer. In older versions, this feature does not always work correctly!

Element: schemaregistry

Attributes:

@resourcekey [ required ] ↦ string
Value of the "censhare:resource-key" feature, used to identify asset used as schema storage. This asset is automatically created if it does not exist yet.

All Headless CMS instances usually have their own unique value to ensure that they have their own set of schemas. It is generally possible to use a special setup with shared schema storage. In that case, all satellites must either use the same output channel, or the storage asset must be prepared in advance with all output channels set.

@outputchannel [ required ] ↦ string
Output channel assigned to all newly created assets (schema storage and all created entities). This value must be present in datastore configuration!
@namespacestring
Prefix used for all created masterdata entities (asset types, features, relation types, etc).
Should be in the form of dot-path (missing dot at the end is automatically added).
The real prefix is also extended by schema name, to avoid conflicts between them.

Default value is "hcms.". Set a different value when one server is used as a backend for several Headless CMS instances.

@no-new-masterdata [ default: true ] ↦ boolean
Setting this attribute to true is the same as adding "cs:$no_new_masterdata": true to all schemas:
no new masterdata records are created, ever.

Default is true: masterdata creation is not allowed.

@update-as-new-version [ default: true ] ↦ boolean
Should each schema change create new version of the internal storage?
Disabled by default.

Note that server versions older than 2019.2 contain a bug in the implementation so it should not be enabled.

@init-wait-time [ default: 300 ] ↦ nonNegativeInteger
How long should the initialization wait for schema repository content (in seconds). Default is 5 minutes.
Zero value disable the wait completely.

@semi-hidden-regexstring
Regular expression for schema name. Matching schemas are hidden from lists (entity/ and schema/ endpoints) and the GraphQL schema, but all other endpoints work as usual (so with correct permissions, it is possible to get the schema, all entities, etc).

@unauthorized-list [ default: compatibility ] ↦ string
Behavior of the entity list endpoint invoked without necessary authorization. In older version, it returned empty list. Added in 4.3, older versions always use "compatibility". Optional. Values: "compatibility", "empty", "401", "404".

Element: cluster

Configuration of HCMS cluster and cluster daemons. Cluster is disabled by default and enabled when this element is present.

In an HCMS cluster, there is always one "leader" that runs all the daemons. If this leader stops or crashes, another cluster member takes over this role and runs all the daemons.

Attributes:

@control [ default: asset ] ↦ { disabled | asset | singleton }
Type of the cluster management: asset-based (default) or singleton (each satellite is its own single cluster).
@control-keystring
Value of the "censhare:resource-key" feature, used to identify asset used for cluster control. This asset is automatically created if it does not exist yet.

Optional. If missing, the key is created from the schema repository resource key. An empty value completely disables clustering, just like a missing "cluster" element or type "disabled".

@heartbeat-seconds [ default: 60 ] ↦ positiveInteger
Base heartbeat interval, in seconds. The first heartbeat of each satellite is spread by a random jitter, see @heartbeat-jitter-seconds. Default value is 60, one minute. Lower values are possible, but not recommended. Minimum is 10s.

@heartbeat-jitter-seconds [ default: 60 ] ↦ nonNegativeInteger
Maximum random delay added to the first heartbeat of each satellite, in seconds. It de-phases satellites that start together, so they avoid simultaneous updates of the cluster control asset. Added in 5.3.

@heartbeat-attempts [ default: 5 ] ↦ positiveInteger
Number of write attempts per heartbeat before the satellite relinquishes leadership. Transient conflicts on the cluster control asset are retried within one heartbeat. Added in 5.3.

@heartbeat-backoff-base-millis [ default: 100 ] ↦ nonNegativeInteger
Base wait between heartbeat retries, in milliseconds. The wait grows with each attempt. Added in 5.3.

@heartbeat-backoff-jitter-millis [ default: 200 ] ↦ nonNegativeInteger
Maximum random value added to each retry wait, in milliseconds. It stops two satellites from retrying in lock-step. Added in 5.3.

How not to misconfigure the cluster heartbeat:

  • Whole numbers only: Values must be whole numbers. A "heartbeat-seconds" value below the 10s minimum is clamped to 10s and logged as BAD CONFIGURATION! … clamped …. The configuration is still accepted.

  • Version compatibility: The "heartbeat-jitter-seconds", "heartbeat-attempts", "heartbeat-backoff-base-millis", and "heartbeat-backoff-jitter-millis" attributes only exist from version 5.3 onward. On an older satellite build, they are rejected by schema validation with cvc-complex-type.3.2.2: Attribute '…' is not allowed.

  • Silent cluster failure: A rejected cluster configuration stops cluster control on every satellite. The config reload cancels the running heartbeat daemon before the new config is validated. An invalid value or an unknown attribute leaves the cluster with no leader and no running daemons. The satellite health endpoint still reports OK.

  • Always verify after changes: Keep a known-good "cluster" element to revert to. After every change, confirm that a leader is elected. To do this, open the Cluster Control asset: it shows <cluster leader="…"> and its tcn value keeps rising.

Children:

  • all of these elements:

    • [0, 1] '→notifications'

Element: notifications

Attributes:

@subscription-asset-typestring
Asset type of subscription notification assets. Optional; when missing or empty, subscription notifications are found only by key prefix and
new ones are created with "module." asset type.

@subscription-key-prefixstring
Prefix of the resource key, used to identify subscription asset. Optional; by default, it's derived from the schema registry key.
@delay [ default: 300 ] ↦ string
Maximum delay between change and notification, in milliseconds. This delay is used to gather all changes in this time interval and send them as a batch.
@min-snapshot-interval [ default: 5 ] ↦ string
Minimal interval between persistent datastore snapshots, in minutes.
Higher value means higher chance that notifications will be repeated on restart or redeploy;
lower value means more storage traffic to/from server.

@max-errors [ default: 5 ] ↦ string
Number of failed invocations before the subscription queue is suspended.
While suspended, no more attempts to deliver notifications are made.
The suspended state is not indefinite, but it lasts only 'errors-recheck-interval' minutes (5 by default).

The value must be at least 1. The maximum value is not limited.

@errors-recheck-interval [ default: 5 ] ↦ string
Maximum duration of "suspended" state, in minutes. Subscription is suspended after 'max-errors' (default 5) failures, but after this time interval it is tried again.
Only values in range of 1 to 1440 (24 hours) are accepted.

@storageanyURI
Where to store persistent data (snapshots); by default (missing attribute), everything is stored in assets.
The only supported value for now is "file:" schema with directory path. The directory is automatically created, if needed.

Element: webhooks

Webhooks notifications: optional configuration of base url, http client and the HMAC security.

Attributes:

@connection-timeout [ default: 500 ] ↦ int
@timeout [ default: 6000 ] ↦ int

Children:

  • sequence of these elements:

    • [0, 1] choice of these elements:

      • [1, 1] '→hmac'

    • [0, 1] '→base-url'

Inner element: webhooks/hmac

Attributes:

@secret [ required ] ↦ string
@size [ default: 256 ] ↦ { 256 | 512 }

Inner element: webhooks/base-url

content: anyURI

Element: api

Attributes:

@etag [ default: auto ] ↦ { none | long | packed | auto }
What kind of etag values are generated: "long" is the old-style (potentially too long for HTTP), "packed" is the compressed one (inefficient for single entities), "auto" chooses the best option, "none" disables the header completely.

@full-stacktraces [ default: false ] ↦ boolean
Enable or disable full stacktraces in error responses. Stacktrace can be very helpful for troubleshooting, but it is often considered security risk (due to possibility of data leak). Optional. Default is false.

@defaultPageSizeint
Default page size of listing endpoints, used when no limit query parameter is used. Optional. Default is 100.

@allowedOriginsstring
Value of the Access-Control-Allow-Origin header in response (CORS).
Set this to the caller domain depending on your application setup, or leave it empty to disable CORS completely. The special value "*" is suitable for development, but not for production (and cannot be combined with cookies).

@maxAgeint
Value of Access-Control-Max-Age header in CORS response. Negative value or zero disables this header. Not enabled by default.
Note: ignored when allowedOrigins is empty.

Children:

  • all of these elements:

    • [0, 1] '→request-logging'
      » Request logging configuration.

    • [0, 1] '→signed-link'
      » Use JWT keys signed by one of the HMAC algorithms, with shared secret (password).

    • [0, 1] '→http-client'
      » Http client used to download external content. This feature is rarely used and setting non-default values must be tied to proper server setup.

Inner element: api/request-logging

Request logging configuration.

Children:

  • sequence of these elements:

    • [1, n] choice of these elements:

      • [1, 1] '→log'
        » Logging by standard logging mechanism.

      • [1, 1] '→statistics'
        » Request logging configuration.

Inner element: api/request-logging/statistics

Request logging configuration.

Attributes:

@service [ required ] ↦ string
Service ID of the statistics service configuration (com.censhare.oc.statistics.StatisticsService).
@group [ required ] ↦ string
Group ID used to log statistics; must be defined in the given service configuration.
@strict [ default: false ] ↦ boolean
Strict mode: when enabled and the configured service/group is not available or invalid, each request fails.
@response-header [ default: false ] ↦ boolean
Report result in response header: enabling this flag adds status header in response (X-Cs-OCStatisticsLogger) with value in form of groupname=logged|unavailable|failed|skipped

Children:

  • sequence of these elements:

    • [0, n] '→condition'

Inner element: api/request-logging/statistics/condition

content: logFilterCondition

Inner element: api/request-logging/log

Logging by standard logging mechanism.

Attributes:

@level [ required ] ↦ positiveInteger
Log level as defined by java4 logging; 1000 = ERROR, 800 = INFO, 500 = DEBUG
@loggernormalizedString
Logger name; if missing, default class name is used.
@formatstring
Format string, with placeholders using curly bracers: {name} or {name:default} or {name:default:size} (use negative size to align left).

Children:

  • sequence of these elements:

    • [0, n] '→condition'

Inner element: api/request-logging/log/condition

content: logFilterCondition

Attributes:

@max-days [ default: 2 ] ↦ positiveInteger
Maximum validity of signed links, in days. All requests are silently capped by this value.

Children:

  • sequence of these elements:

    • [0, n] choice of these elements:

      • [1, 1] '→hmac'
        » Use JWT keys signed by one of the HMAC algorithms, with shared secret (password).

Inner element: api/signed-link/hmac

Use JWT keys signed by one of the HMAC algorithms, with shared secret (password).

Attributes:

@secret [ required ] ↦ string
Shared secret (password) used to sign JWT tokens. It is treated as UTF-8 byte sequence.

Inner element: api/http-client

Http client is used to download external content. This feature is rarely used and setting non-default values must be tied to proper server setup.

Attributes:

@connection-timeout [ default: 1000 ] ↦ positiveInteger
Connection timeout, in milliseconds. This value is important to avoid waiting for wrong url.

@read-timeout [ default: 5000 ] ↦ positiveInteger
Read timeout, in milliseconds. This value is used to detect broken connection.

@timeout [ default: 120000 ] ↦ positiveInteger
Total timeout, in milliseconds. Longer value is necessary to download larger file, but care must be taken to raise other timeouts for security reasons and timeouts of client libraries.

@max-size [ default: 200 ] ↦ positiveInteger
Maximum download file/content size in kb.

Element: hostmappings

Children:

  • sequence of these elements:

    • [1, n] '→hostmapping'
      » One or more web server instances (port, prefixes) serving this REST API.

Element: hostmapping

Attributes:

@name [ required ] ↦ string
Reference to the web server configuration, with optional prefix. Value can have two forms:

  • Just the name of the web server host configuration. Headless CMS will be available at the configured host, port and path /hcms/v2.0/

  • Name and prefix, separated by slash (name/prefix).
    Headless CMS will be available at the configured host, port and path /prefix/hcms/v2.0/

In any case, the Web Server Configuration must contain an appropriate "hostid name='name'" element.

Element: auth

Children:

  • [0, n] choice of these elements:

    • [0, 1] '→disable-security'
      » This (empty) element completely disables security checks: all requests have all roles.

    • [0, n] '→ip'

    • [0, n] '→basic'

    • [0, n] '→jwt'

Inner element: auth/disable-security

This (empty) element completely disables security checks: all requests have all roles!

Element: ip

IP-based role provider: intended to be used in combination with other providers, to allow full access from localhost.

Children:

  • sequence of these elements:

    • [1, n] '→range'
      » Range of IP addresses.

Inner element: ip/range

Range of IP addresses.

Attributes:

@start [ required ] ↦ string
Lower bound of the IP range, inclusive. Both IPv4 and IPv6 addresses are accepted.

@end [ required ] ↦ string
Upper bound of the IP range, inclusive. In other words: highest IP address that still match. Both IPv4 and IPv6 addresses are accepted.

Children:

  • sequence of these elements:

    • [1, n] '→role'
      » Role assigned to all requests from these IP addresses (there might be more than one).

Inner element: ip/range/role

content: token

Role assigned to all requests from these IP addresses (there might be more than one).

Element: basic

Simple http-basic authentication with passwords directly in configuration.

Only for development and testing, not recommended for production.

Children:

  • sequence of these elements:

    • [1, n] '→user'
      » Role assigned to request with this username and password (there might be more than one).

Inner element: basic/user

Attributes:

@name [ required ] ↦ string
Username. There is no validation, any string can be valid username (http clients, however, usually have some limitations).
@password [ required ] ↦ string
Password. Password can be any string, just like username.

Children:

  • sequence of these elements:

    • [0, n] '→role'
      » Role assigned to request with this username and password (there might be more than one).

Inner element: basic/user/role

content: token

Role assigned to request with this username and password (there might be more than one).

Element: jwt

JWT token containing "roles" claim

Attributes:

@roles-claim-name [ default: roles ] ↦ token
Name of the JWT claim that contain array of roles. Default is "roles".
@roles-claim-separatortoken (length: 1)
Separator used in "roles-claim-name" attribute to specify content of nested claims. Slash or dot characters are the most convenient, but any character can be used - remember that there is no escaping mechanism.
No separator is used by default, which means that whole claim is used as a string.

Children:

  • sequence of these elements:

    • [1, n] choice of these elements:

      • [1, 1] '→cookie'

      • [1, 1] '→hmac'
        » Use JTW keys signed by one of the HMAC algorithms, with shared secret (password).

      • [1, 1] '→pem'
        » Public key used to validate JWT tokens, in PEM format. Note that this is not a certificate, it is a PEM public key!

      • [1, 1] '→jwks'
        » Public key(s) published at HTTPS URL, typically open OpenID-compliant auth server.

      • [0, n] '→user-lookup'
        » Subject configuration: custom mapping of the "sub" claim to entity/asset. Necessary for OpenID-Connect integration

      • [1, 1] '→blacklist'
        » Blacklisted claim: any role in JWT that matches this value is completely ignored. By default, exact string match is used; regular expressions can be used instead.
        Note that this black is evaluated BEFORE automatic roles and this blacklisted role can be added by those rules!

      • [1, 1] '→role'
        » Role assigned to all requests with valid JWT token (when used without attributes), or all requests with specified claim.

Inner element: jwt/jwks

Public key(s) published at HTTPS URL, typically open OpenID-compliant auth server.

Attributes:

@url [ required ] ↦ anyURI
URL where the keys are published.
@cache-keys [ default: 3600 ] ↦ positiveInteger
Default cache duration for the keys, in seconds. Can be changed (but not disabled) by a corresponding HTTP header.
@cache-error [ default: 0 ] ↦ integer
How long should be any error (network, HTTP error code, parsing error) cached, before it is tried again; in seconds. Default is zero, which means that there is no cache - requests will be tried again and again until success.

Inner element: jwt/pem

Public key used to validate JWT tokens, in PEM format. Note that this is not a certificate, it is a PEM public key!

Children:

  • [1, n] choice of these elements:

    • [0, n] '→user-lookup'
      » Subject configuration: custom mapping of the "sub" claim to entity/asset. Necessary for OpenID-Connect integration

    • [0, n] '→blacklist'
      » Blacklisted claim: any role in JWT that matches this value is completely ignored. By default, exact string match is used; regular expressions can be used instead.
      Note that this black is evaluated BEFORE automatic roles and this blacklisted role can be added by those rules!

    • [0, n] '→role'
      » Role assigned to all requests with valid JWT token (when used without attributes), or all requests with specified claim.

Inner element: jwt/pem/role

content: jwt-role

Role assigned to all requests with valid JWT token (when used without attributes), or all requests with specified claim.

Inner element: jwt/pem/user-lookup

content: jwt-user-lookup

Subject configuration: custom mapping of the "sub" claim to entity/asset. Necessary for OpenID-Connect integration

Inner element: jwt/pem/blacklist

content: jwt-blacklist

Blacklisted claim: any role in JWT that matches this value is completely ignored. By default, exact string match is used; regular expressions can be used instead. Note that this black is evaluated BEFORE automatic roles and this blacklisted role can be added by those rules!

Inner element: jwt/hmac

Use JTW keys signed by one of the HMAC algorithms, with shared secret (password).

Attributes:

@secret [ required ] ↦ string
Shared secret (password) used to sign JWT tokens. It is treated as UTF-8 byte sequence.

Children:

  • [1, n] choice of these elements:

    • [0, n] '→user-lookup'
      » Subject configuration: custom mapping of the "sub" claim to entity/asset. Necessary for OpenID-Connect integration

    • [0, n] '→blacklist'
      » Blacklisted claim: any role in JWT that matches this value is completely ignored. By default, exact string match is used; regular expressions can be used instead.
      Note that this black is evaluated BEFORE automatic roles and this blacklisted role can be added by those rules!

    • [0, n] '→role'
      » Role assigned to all requests with valid JWT token (when used without attributes), or all requests with specified claim.

Inner element: jwt/hmac/role

content: jwt-role

Role assigned to all requests with valid JWT token (when used without attributes), or all requests with specified claim.

Inner element: jwt/hmac/user-lookup

content: jwt-user-lookup

Subject configuration: custom mapping of the "sub" claim to entity/asset. Necessary for OpenID-Connect integration

Inner element: jwt/hmac/blacklist

content: jwt-blacklist

Blacklisted claim: any role in JWT that matches this value is completely ignored. By default, exact string match is used; regular expressions can be used instead. Note that this black is evaluated BEFORE automatic roles and this blacklisted role can be added by those rules!

Inner element: jwt/blacklist

content: jwt-blacklist

Blacklisted claim: any role in JWT that matches this value is completely ignored. By default, exact string match is used; regular expressions can be used instead. Note that this black is evaluated BEFORE automatic roles and this blacklisted role can be added by those rules!

Inner element: jwt/user-lookup

content: jwt-user-lookup

Subject configuration: custom mapping of the "sub" claim to entity/asset. Necessary for OpenID-Connect integration

Inner element: jwt/role

content: jwt-role

Role assigned to all requests with valid JWT token (when used without attributes), or all requests with specified claim.

Configuration of cookie support: cookie is accepted in addition to Authorized header and set in response. It can be also set or removed by invoking special endpoints.

By default, cookie support is fully configured (with cookie named "access_token").

Attributes:

@namestring
Name of the authorization cookie, or empty string to disable cookie support completely. Default cookie name is "access_token".

@maxAgeint
Maximum age of the cookie, in seconds. Negative value and missing attribute means that cookies never expire.
@insecurestring
This attribute is used to disable the "secure" flag in cookies. Value is not actually ever used, the very presence is enough.

By default, all cookies are "secure" and thus never sent by browser over unencrypted "http".

@http-only [ default: false ] ↦ boolean
This attribute is used to enable the "HttpOnly" flag in cookies. Value can be both true or false, with default being false.

@same-site{ Lax | None | Strict }
SameSite flag for the new cookies; default is None, because this is REST API that is often requested from different domains.

Element: image

Attributes:

@storage-item [ default: preview ] ↦ string
@storage-path [ default: images ] ↦ string
@thread-pool-size [ default: 2 ] ↦ positiveInteger
@max-cache-size-in-mb [ required ] ↦ positiveInteger
@max-age-in-minutes [ required ] ↦ positiveInteger
@default-filetype [ default: png ] ↦ { jpg | png }
@auto-detect-type [ default: true ] ↦ boolean
@element-idx-compatibility-mode [ default: true ] ↦ boolean
@copy-metadata [ default: true ] ↦ boolean

Children:

  • all of these elements:

    • [0, 1] '→s3'
      » Obsolete region declaration; use s3-region instead, for OC compatibility.

Inner element: image/s3

Children:

  • sequence of these elements:

    • [0, 1] '→region'
      » Obsolete region declaration; use s3-region instead, for OC compatibility.

    • [0, n] '→s3-region'

Inner element: image/s3/region

content: s3-region

Obsolete region declaration; use s3-region instead, for OC compatibility.

Inner element: image/s3/s3-region

content: s3-region

  • Headless CMS Configuration: the baseline configuration reference for HCMS versions before 5.3.

  • HCMS First Steps: how to set up an HCMS instance from scratch, including creating and connecting the configuration asset.

  • HCMS Command Line Interface Tool: the CLI tool used to create and manage HCMS configuration assets.

  • Installation options: available deployment methods for HCMS, including Docker-based, AWS, and manual Linux installation.

  • HCMS REST Endpoints: reference for all REST API endpoints exposed by an HCMS satellite instance.

  • All about HCMS schemas: in-depth documentation on defining and managing schemas in HCMS, including the schema registry referenced in this configuration.

  • HCMS Authorization: details on roles, JWT, and OAuth integration that complement the auth element described in this reference.

  • HCMS Webhooks: how to configure and use webhooks for change notifications, extending the webhooks element in this configuration.

  • HCMS Release Notes: changelog for all HCMS versions, including the 5.3 changes documented in this reference.