Font isolation per render job in InDesign Server

Why to read this article

If you are using InDesign Server on Censhare Cloud or run InDesign Server in a multi-tenant environment, this article applies to you. Font conflicts in shared environments can silently cause incorrect layouts and wrong PDF output. These issues are difficult to diagnose. Font isolation helps you to prevent this.

Overview

The Censhare Render Client supports per-job font isolation for Adobe InDesign Server. The feature prevents cross-tenant font conflicts in shared rendering environments. These are typically Censhare Cloud deployments where a single InDesign Server instance renders jobs for multiple tenants from a shared font pool.

Why font isolation is required

InDesign resolves fonts primarily by PostScript name, not by file name. If two tenants maintain different versions of the same font that share the same PostScript name in a shared pool, InDesign might load an arbitrary version when opening a document. This produces layout deviations and incorrect PDF output.

Example:

Fonts/
  tenantA/
    fontB-v1      (PostScript name: "FontB-Regular")
  tenantB/
    fontB-v2      (PostScript name: "FontB-Regular")

If both directories are connected to InDesign as a single global font pool, a tenantA job may accidentally render with tenantB's font version.

How font isolation solves the problem

Font isolation uses Adobe's native "Document Fonts" mechanism: If a folder named Document Fonts exists next to an InDesign document, InDesign loads fonts from that folder before falling back to globally installed fonts.

The Censhare Render Client creates a fresh, job-specific Document Fonts folder for every render job and populates it with hardlinks to the correct tenant's fonts only. Font resolution becomes tenant-specific, deterministic, and independent of the shared global pool.

How it works

For every render job:

  1. The command sequence arrives at the Censhare Render Client. If SetupDocumentFontsCommand is not already present in the sequence, it is automatically inserted as the first command. If multiple SetupDocumentFontsCommand instances are present, only the first runs; each subsequent instance is skipped with a warning in the log.

  2. The tenant ID is resolved from the OS username (via configurable regex).

  3. The tenant font index (font-index.xml) is checked for freshness and rebuilt if stale.

  4. A job-specific working directory is created under <working-directory>/<job-uuid>/, and a Document Fonts subfolder is created inside it.

  5. Fonts are hardlinked into Document Fonts:

    • Link-all mode (small font pools): all tenant fonts are linked.

    • Detection mode (large font pools): The Censhare Render Client opens each participating document, extracts the PostScript names actually used, and links only those fonts.

  6. InDesign opens the document from the working directory. It finds the job-specific Document Fonts folder next to the document and uses it for font resolution.

  7. After the job completes, the working directory (including the hardlink folder) is deleted. Original fonts in the tenant pool remain untouched.

Prerequisites

  • Censhare Render Client uses Adobe InDesign Server for rendering.

  • One Censhare Render Client per tenant, running under a dedicated OS user account per tenant. This is how the feature identifies the tenant: It uses the OS username of the Censhare Render Client process. In the Censhare Cloud platform this is the standard deployment model. On-premise installations do not necessarily follow this pattern. In that case, the feature can still be used, but the deployment must be configured: Each Censhare Render Client instance runs under an OS account whose name can be mapped to the correct tenant directory, directly or via the configured regex. For more information, see Tenant ID Resolution.

  • A shared tenant font pool reachable on the local filesystem of the Censhare Render Client host: either locally stored or a locally mounted file share.

  • Tenant subdirectory naming: the tenant-specific subdirectory inside font-base-directory must either match the OS user name: The login name of the Render Client account can match directly. Or, it can be derivable from it via the configured regex expression. See Tenant ID Resolution for the exact mechanics.

  • The working directory and the tenant font directory must reside on the same filesystem volume. Reason: Hardlinks cannot span volumes.

  • Required file permissions on the Censhare Render Client host:

    • Traverse/read on font-base-directory . This is required to reach the tenant subdirectory.

    • Read and write on the tenant's own subdirectory (recursively).

    • Read and write on the working directory.

Tenant font pool layout

The tenant font pool is a shared directory containing one subdirectory per tenant. Each tenant directory holds the tenant's font files plus an auto-generated index file.

The directory structure:

<font-base-directory>/
  tenantA/
    font-index.xml          (auto-generated; do not edit)
    font-index.xml.bak      (transient — exists only during a rebuild)
    Helvetica/
      HelveticaNeue-Bold.otf
      HelveticaNeue-Regular.otf
    Minion/
      MinionPro-Regular.otf
  tenantB/
    font-index.xml
    ...

Supported font file formats

All file-extension matching is case-insensitive. Font files are discovered recursively.

Extension

Format

.ttf

TrueType

.otf

OpenType (CFF)

.ttc

TrueType Collection

.otc

OpenType Collection

.pfa

PostScript Type 1 (ASCII)

.pfb

PostScript Type 1 (Binary)

Nested directories

Tenant subdirectories may use arbitrarily deep, freely chosen folder structures. Fonts do not need to be stored flat, and no particular layout is required. The Censhare Render Client discovers font files recursively and does not care how they are grouped. Administrators can organize each tenant's fonts according to their own conventions (by family, by foundry, by project, etc.).

The relative structure below each tenant directory is mirrored 1:1 inside the per-job Document Fonts folder. Two fonts with the same base file name in different subdirectories therefore do not collide.

Index and backup files

  • font-index.xml is created and maintained automatically by the Censhare Render Client. Do not edit or delete it manually. Whenever the contents of the tenant font directory change, the Censhare Render Client detects the change on the next job and rebuilds the index automatically. Changes can be that fonts are added, removed, renamed, moved between subdirectories, or modified. Censhare Render Client uses fingerprints of relative paths, file sizes, and modification timestamps to detect changes.
    Administrators do not need to delete the index after updating the tenant font pool. If the file is nevertheless missing, the rebuild still happens automatically. But, it takes time (roughly a few seconds per 1,000 fonts) and this time is added to the runtime of the first affected job.

  • font-index.xml.bak is transient: It appears only while a rebuild is in progress. On rebuild success, it is deleted. If the rebuild fails, it is renamed back to font-index.xml. This way, the previous index remains usable.

Configuration

The Font isolation is configured in the Censhare Render Client preferences file (javarender-preferences.xml) that is stored on Censhare Server.

Two XML tags are part of the configuration:

  • <render-client> defines general render-job settings that are independent of font handling.

  • <document-fonts> defines settings for the per-job font isolation feature.

For a minimal required configuration, see Minimal configuration.

XML tag: render-client

The following attributes can be set, for example:

<render-client working-directory="D:\RenderWork"/>

Attribute

Description

working-directory

Local working directory for render jobs.

Each job creates its own subdirectory: <working-directory>/<job-uuid>/.

If the attribute is empty or absent, java.io.tmpdir is used as a fallback. A leading ~ is expanded to the current user's home directory, for example ~/RenderWork.

Example entry:

<render-client working-directory="D:\RenderWork"/>

XML tag: document-fonts

The following attributes can be set, for example:

<document-fonts
    enabled="true"
    font-base-directory="\\fileserver\Fonts"
    font-detection-threshold="30"
    tenant-id-pattern="(.*)"
    tenant-id-replacement="$1"
    index-creation-base-timeout-ms="60000"
    index-creation-per-font-timeout-ms="20"
    index-wait-grace-ms="10000"/>

Attribute

Default

Description

enabled

false

Switches font isolation on or off.

By default, it is set to false! Administrators must explicitly enable font isolation by setting enabled="true".

This applies to both fresh installations and upgrades: if the <document-fonts> XML tag is missing entirely from an existing javarender-preferences.xml, the feature is not enabled.

To enable it, the XML tag must be added with enabled="true".

font-base-directory

(empty)

Root directory of the shared tenant font pool. When font-base-directory is empty, the feature is inactive for all jobs.

tenant-id-pattern

(.*)

The regex is applied to the OS username to derive the tenant directory name.

tenant-id-replacement

$1

Stores the replacement string of the regex match: $1, $2, ... reference capture groups.

font-detection-threshold

30

Tenant font count at or above which the detection mode is used. Below this value, the link-all mode is used.

index-creation-base-timeout-ms

60000

Fixed base timeframe (ms) of the index rebuild timeout.

index-creation-per-font-timeout-ms

20

Per-font timeframe (ms) of the index rebuild timeout. Calculation of the total timeout for creation xxx = base + (fontCount × perFont).

index-wait-grace-ms

10000

Extra grace timeframe (ms) that is added on top of the creation-timeout formula when a job waits for a concurrent rebuild.

Requirements to activate font isolation

To use font isolation, the following conditions must be fulfilled:

  1. enabled="true" is set explicitly in the <document-fonts> XML tag.

  2. font-base-directory attribute is set and exists on the filesystem.

  3. The resolved tenant font directory (<font-base-directory>/<tenant-id>) exists.

If condition 1 is not met, the feature is silently inactive: Jobs use the global font pool exactly as before. Reasons can be:

  • The enabled attribute missing or set to false.

  • The <document-fonts> XML tag itself is missing.

If condition 1 is met but condition 2 or 3 is not, the job fails immediately with a clear error message. This is intentional: once an administrator has opted in with enabled="true", the configuration is treated as a strict contract. A silent fallback to the global font pool would mask tenant-isolation misconfiguration, for example wrong path, missing tenant subdirectory, or unmounted share. The admin would not be informed that the font isolation is not activated.

If you want jobs to run without font isolation, set enabled="false" explicitly.

Minimal configuration

If you just want to turn the feature on, only a small number of attributes must be set. Everything else can stay at its default settings:

XML
<render-client
    working-directory="D:\RenderWork"/>

<document-fonts
    enabled="true"
    font-base-directory="\\fileserver\Fonts"/>

Required XML tags and attributes:

  • render-client working-directory XML tag:

    • working-directory attribute

  • document-fonts XML tag

    • enabled attribute

    • font-base-directory attribute

Conditionally required:

  • document-fonts tag:

    • document-fonts tenant-id-pattern/tenant-id-replacement attributes

    • These attributes are only required if the tenant subdirectory name does not match the OS username of the Censhare Render Client account directly. For more information, see Tenant ID Resolution.

Tenant ID resolution

The Censhare Render Client identifies the tenant from the OS username of its own process and maps it to a tenant subdirectory under font-base-directory.

This assumes that each Censhare Render Client instance runs under an OS account which name corresponds to exactly one tenant. In the Censhare Cloud platform, this is the standard deployment model: one Censhare Render Client per tenant, each started using a dedicated OS user.

On-premise setups are free to organize things differently. This might require aligning account naming, or adjusting OS username mapping in the tenant-id-pattern / tenant-id-replacement attributes in the XML configuration file .

If a Censhare Render Client serves multiple tenants using a single OS account, the tenant identity cannot be distinguished from the username alone: Per-job font isolation cannot be applied reliably.

The tenant directory name is derived from the OS username:

  1. Apply the configured regex pattern supplied intenant-id-pattern

  2. Substitute the result by using the pattern supplied in tenant-id-replacement.

The following examples show how this can be used:

  1. Example: Identity mapping (default)

    OS username           = tenantA
    tenant-id-pattern     = (.*)
    tenant-id-replacement = $1
    → tenant directory    = <font-base-directory>/tenantA
    
  2. Example: Stripping a prefix from the username:

    OS username           = svc_tenantA
    tenant-id-pattern     = ^svc_(.*)
    tenant-id-replacement = $1
    → tenant directory    = <font-base-directory>/tenantA
    
  3. Example: adding a prefix to the folder name
    The reverse direction also works: tenant-id-replacement may contain literal text in addition to the capture-group reference.

    OS username           = tenantA
    tenant-id-pattern     = (.*)
    tenant-id-replacement = fonts-$1
    → tenant directory    = <font-base-directory>/fonts-tenantA
    

    If tenant-id-pattern is syntactically invalid, a warning is logged and the Censhare Render Client falls back to the identity mapping ((.*) / $1).

Operating modes

Two modes exist, selected by the font-detection-threshold attribute.

Applies when the tenant's font count is below the font-detection-threshold.

  • All tenant fonts are hardlinked into the Document Fonts folder.

  • No document is opened just for font detection.

  • Faster setup

  • Best for small font pools

Detection mode

Applies when the tenant's font count is at or above the font-detection-threshold.

  1. The Censhare Render Client scans the command sequence for all OpenCommand entries, deduplicates the documents to inspect, and opens each one temporarily.

  2. For each document, the bundled ExtendScript GetDocumentFonts.jsx is executed on the InDesign Server to extract the PostScript names actually used by the document.

  3. Detected PostScript names are aggregated across all documents, resolved against the tenant font index, and only the required fonts are linked.

  4. Documents opened just for detection are closed immediately after the script result has been collected.

Choosing the threshold

The threshold defines the switch-over point between link-all and detection mode. For most deployments the default 30 works well:

  • Small pools stay in link-all mode: cheap and no detection overhead

  • Large pools automatically end up in detection mode which scales.

The threshold value only matters when a tenant's font count is close to the boundary. For pools that are clearly below or well above 30, changing it has no effect.

Font index

Per-tenant index

Each tenant directory contains its own font-index.xml. There is no global index across tenants.

Format

The index uses XML. It groups candidate font files by PostScript name and stores per-candidate metadata: family, subfamily, full name, format, SHA-256). Candidate paths are stored relative to the tenant font root.

<font-index version="5" fingerprint="...">
  <font ps-name="HelveticaNeueLTStd-BdEx">
    <candidate path="CAC/HelveticaNeueLTStd-BdEx.otf"
               family="Helvetica Neue LT Std" subfamily="BdEx"
               full-name="Helvetica Neue LT Std BdEx"
               format="OTF" sha256="..."/>
    <candidate path="CAM/HelveticaNeueLTStd-BdEx.otf"
               family="Helvetica Neue LT Std" subfamily="BdEx"
               full-name="Helvetica Neue LT Std BdEx"
               format="OTF" sha256="..."/>
  </font>
</font-index>

Ambiguous PostScript names

If multiple font files share the same PostScript name, all of them are kept as candidates in deterministic order. At resolution time the first candidate is selected, and a warning may be logged during index creation so the ambiguity is visible in diagnostics.

Admin action

Review such warnings and clean up the tenant pool. Duplicate PostScript names represent an ambiguous pool and should be resolved at the source.

As a more direct alternative to searching the log file, the tenant's font-index.xml can be opened in a text or XML editor: any <font> element that contains more than one <candidate> child indicates a PostScript-name collision for that entry. This can be a faster way to audit a tenant pool than log analysis, especially for administrators who are comfortable reading XML.

Staleness detection

At the start of every job the Censhare Render Client verifies the index against the current state of the tenant directory. A rebuild is triggered when any of the following conditions is true:

  • font-index.xml is missing or corrupt.

  • The stored fingerprint (relative path + size + modification time of every font file) differs from the recomputed fingerprint. The fingerprint is computed this way: relative path + size + modification time of every font file.

  • Any font file is newer than font-index.xml.

Concurrency

A per-tenant lock serializes all index reads and rebuilds. Concurrent jobs for the same tenant either share a freshly built index or wait for the in-progress rebuild to complete.

Typical runtime

Index creation time is proportional to the font count and file sizes. The SHA-256 is computed per file. Expect a few seconds per 1,000 fonts on typical hardware.

Hardlinks, volumes, and permissions

Fonts are linked into Document Fonts via java.nio.file.Files.createLink(). No copies are created. A hardlink creates a second directory entry pointing to the same inode:

  • No disk space is consumed per job.

  • All jobs for a tenant share the same physical font files.

Same-volume requirement

Hardlinks cannot span filesystem volumes. The Censhare Render Client verifies at setup time that the working directory and the tenant font directory are on the same volume.

If not:

  • A job that needs font isolation fails immediately with the error message:

    Document Fonts: working directory {0} and tenant font directory {1} are on different filesystem volumes, hardlinks require both paths to be on the same volume
    
  • Jobs that do not need font isolation are unaffected. This is the case if the feature is disabled via enabled="false".

Admin action

Place the working directory on the same volume as the tenant font pool.

Job working directory and cleanup

  • Each job runs inside <working-directory>/<job-uuid>/.

  • InDesign documents for the job are placed inside this directory, not directly in java.io.tmpdir. This way, InDesign finds the adjacent Document Fonts folder.

  • After the job completes, the working directory is deleted recursively. Hardlinks are removed. The original font files in the tenant pool are not touched.

No explicit cleanup is required from the administrator during normal operation.

Logging and troubleshooting

The table below shows the English log messages related to the font isolation feature. Placeholders such as {0} / {1} are filled in at runtime with the actual tenant ID or path. Translations for other languages are available in client.properties.

Log message (EN)

Severity

Meaning

Suggested action

Setting up Document Fonts for tenant {0}

Info

Setup is running; {0} is the resolved tenant ID.

None.

For information only.

Document Fonts: font-base-directory is not configured

Error (job fails)

Feature is enabled but font-base-directory is not set.

Set font-base-directory in javarender-preferences.xml, or set enabled="false" if the feature should not be used.

Document Fonts: font-base-directory does not exist: {0}

Error (job fails)

The configured path does not exist; {0} is that path.

Verify the mount / path; create the directory; or set enabled="false".

Document Fonts: tenant font directory does not exist: {0}

Error (job fails)

The resolved tenant directory does not exist; {0} is its path.

Create the tenant directory, adjust tenant-id-pattern / tenant-id-replacement, or set enabled="false".

Document Fonts: working directory {0} and tenant font directory {1} are on different filesystem volumes, hardlinks require both paths to be on the same volume

Error (job fails)

Working directory and tenant directory are on different volumes; hardlinks impossible.

Move the working directory to the same volume as the tenant font pool.

Document Fonts: tenant font directory {0} is not writable, the font index cannot be maintained

Error (job fails)

The OS account under which the Censhare Render Client runs has no write permission on the tenant font directory. font-index.xml cannot be created or updated.

Grant write permission on the tenant's own subdirectory.

Document Fonts: working directory {0} is not writable, the job working directory cannot be created

Error (job fails)

The OS account has no write permission on the configured working-directory. The per-job subfolder cannot be created.

Grant write permission on the working directory.

Additional failure modes

Condition

Severity

Behavior

Suggested action

Index rebuild timeout

Error (logged)

Rebuild aborted and previous index is restored from backup.

Increase index-creation-base-timeout-ms and/orindex-creation-per-font-timeout-ms, or reduce the number of fonts in the tenant pool.

Index wait timeout

Error (job fails)

Job cannot obtain a consistent index within the wait timeout.

Raise index-wait-grace-ms, or reduce concurrent load against the same tenant.

Detection-mode script failure

Error (job fails)

Opening a document, running GetDocumentFonts.jsx, or parsing the result failed.

Check the InDesign Server log.

Verify the affected document is intact.

There is no automatic fallback to link-all mode.

Ambiguous PostScript name warning

Warning may be logged during index creation

Multiple font files share the same PostScript name. The first candidate is used.

Remove duplicates from the tenant font pool.

Rollout recommendation

For the initial rollout:

  • Keep the existing global InDesign font folder connected. This preserves the previous resolution path as a fallback while per-job isolation is introduced in production.

  • Add or update the <document-fonts> element in javarender-preferences.xml and set enabled="true" explicitly. The feature is off by default and does not activate itself on upgrade. The minimum set of attributes to configure and the full attribute reference are described, see Configuration.

  • Monitor logs and rendering output.

After the new mechanism has been validated in regular operation:

  • Remove the global font folder from InDesign Server.

  • From that point on, font resolution relies entirely on the dynamically populated Document Fonts folder — full per-job, per-tenant isolation.

Per-Job overrides (for developers and integrators)

This section is intended for solution developers, partners, and customers who build their own render pipelines against the Censhare Render Client.

Administrators can skip the following section if they only want to configure javarender-preferences.xml.

When a custom server-side component builds the command sequence that is sent to the Censhare Render Client, two attributes on the root <cmd> element can override the global configuration for that specific job.

Attribute

Type

Effect

tenant-id

string

Overrides the tenant directory name derived from the OS username.

Useful when the server has explicit knowledge of the tenant identity for a job and should not rely on the OS account mapping.

document-fonts-enabled

boolean

Overrides the global enabled setting for this job.

Allows the server to selectively enable or disable font isolation per job.

Precedence:

  1. per-job attributes

  2. javarender-preferences.xml

  3. defaults.

All other <document-fonts> settings (thresholds, timeouts, base directory, regex) are global and cannot be overridden per job.

Example command sequence

A command sequence that applies to a specific tenant and keeps font isolation enabled for this job:

<cmd tenant-id="customer-acme" document-fonts-enabled="true">
    <SetupDocumentFontsCommand/>
    <OpenCommand document-ref="..."/>
    <!-- further commands ... -->
</cmd>

Notes:

  • SetupDocumentFontsCommand does not have to be included explicitly. The Censhare Render Client auto-inserts it as the first command if it is missing. Optionally, it can be included explicitly. This is only useful in special cases, for example to reserve a specific position in the sequence.

  • If tenant-id is omitted, the Censhare Render Client derives the tenant ID from the OS username via the configured regex, exactly as documented in Tenant ID Resolution.

  • If document-fonts-enabled is omitted, the global value from <document-fonts> applies.