Configuration
- Undefined type
This document describes the settings specific to RestFrontage and the GraphicStream libraries that it initializes.
Standard ASP.NET Core topics, such as Logging, AllowedHosts or the choice of hosting environment, are not detailed. They are the appanage of the underlying system to ASP.Net and IIS.
A key present in appsettings.json does not necessarily have an effect. Inactive or ignored settings are explicitly reported in this document.
1. Overview
| Section | Status | Role |
|---|---|---|
Database |
Required | Chooses SQL Server LocalDB, SQLite, or remote SQL Server and names the local business and security databases. |
ConnectionStrings |
Required in remote SQL Server mode | Configures business, security, server, and licensing basics. |
LogsSettings |
Required | Configures the GraphicStream logger and log destination. |
IOSettings |
Required in practice | Configures media and file storage. |
Application |
Required | Configures server identity, tokens, empty passwords, warm-up, and task loop. |
Application:OpenAI |
Conditional | Configures AI functions using Azure OpenAI Assistants. |
Environment |
Optional | Displays a banner to visually identify the environment. |
SecurityDomainSynchronization |
Optional | Regulates the synchronization of the security domain between instances. |
Recovery |
Recommended | Protects the recovery console independent of the security base. |
ApiKey |
Conditional | Declares API keys associated with Immersive users. |
Saml |
Conditional | Configures SAML authentication with FID. |
OpenID |
Conditional | Configures OpenID token validation with the FID. |
Session |
Optional | Activates the server session only when the section contains at least one parameter. An absent or empty section maintains sessionless operation. |
IPX |
Inactive | The section IPX:Export of the provided file is not read by any component. |
2. Selecting the Database Mode
RestFrontage enforces this priority:
Database:EnableLocalDB = trueselects SQL Server LocalDB;- otherwise,
Database:EnableSqlite = trueselects SQLite; - otherwise, RestFrontage uses the SQL Server strings of
ConnectionStrings.
If both indicators are valid true, LocalDB wins and the SQLite parameter is ignored.
2.1 Remote SQL Server or SQL Server Express
Recommended minimum requirements for a full deployment:
{
"Database": {
"EnableLocalDB": false,
"EnableSqlite": false
},
"ConnectionStrings": {
"ImmersiveModelContainer": "<chaine SQL de la base metier>",
"SecurityModelContainer": "<chaine SQL de la base de securite>",
"ServerDatabaseContext": "<chaine SQL des donnees serveur>",
"LicenseModelContainer": "<chaine SQL des licences>"
}
}
| Key | Required | Use and Fall |
|---|---|---|
ImmersiveModelContainer |
Yes | Immersive business data. Also serves as a fallback to ServerDatabaseContext. |
SecurityModelContainer |
Yes | Users, groups, rights, and security domain. Also serves as a fallback for LicenseModelContainer. |
ServerDatabaseContext |
No | Server tasks and internal AI data. IPX history and work sessions also use this connection. With no value or if not specified, the business base is used. |
LicenseModelContainer |
No | Installed licenses. With no value or if not specified, the security base is used. |
In SQL Server mode, access to the business, security, server, license, and IPX history enables up to five retries on transient SQL errors, with a maximum delay of ten seconds between retries.
The log database is not configured in ConnectionStrings. It uses exclusively LogsSettings:ConnectionString.
2.2 SQLite
{
"Database": {
"EnableLocalDB": false,
"EnableSqlite": true,
"ImmersiveSqlite": "Immersive.sqlite",
"ImmersiveSecuritySqlite": "ImmersiveSecurity.sqlite"
},
"LogsSettings": {
"ConnectionString": "ImmersiveLogs.sqlite"
}
}
| Key | Role |
|---|---|
ImmersiveSqlite |
Business database and storage of IPX history. |
ImmersiveSecuritySqlite |
Security base. |
LogsSettings:ConnectionString contains the name or relative path of the SQLite log file here. Both the logger and the lookup context use the same file.
The SQLite paths are resolved relative to the folder containing the RestFrontage executable and the files must already exist. The current code does not create the missing SQLite files.
In SQLite mode, contexts ServerDatabaseContext and LicenseSecurityModel are not saved. The functions that depend on them therefore do not have their full storage.
2.3 SQL Server LocalDB
{
"Database": {
"EnableLocalDB": true,
"EnableSqlite": false,
"ImmersiveDatabaseName": "Immersive",
"ImmersiveSecurityDatabaseName": "ImmersiveSecurity",
"ImmersiveBacPacName": "Immersive.bacpac",
"ImmersiveSecurityBacPacName": "ImmersiveSecurity.bacpac",
"ImmersiveLogBacPacName": "ImmersiveLogs.bacpac"
},
"LogsSettings": {
"ConnectionString": "ImmersiveLogs"
}
}
| Key | Required | Role |
|---|---|---|
ImmersiveDatabaseName |
Yes | File Name <nom>.mdf and the business base. |
ImmersiveSecurityDatabaseName |
Yes | The name of the file and the security database. |
ImmersiveBacPacName |
No | BACPAC initial of the business base. |
ImmersiveSecurityBacPacName |
No | BACPAC of the safety base. |
ImmersiveLogBacPacName |
No | BACPAC database of newspapers whose name is given by LogsSettings:ConnectionString. |
LogsSettings:ConnectionString contains the logical name of the LocalDB log database here, without extension .mdf not a full SQL string. In the example, RestFrontage opens or creates ImmersiveLogs.mdf, and then the logger and the lookup context reuse the LocalDB string that was actually obtained.
MDF files are placed in the subfolder Data located next to the assemblies. When creating a database, a BACPAC is searched under Assets/Bacpac.
This mode requires SQL Server LocalDB on the machine. As in SQLite mode, the current code does not save ServerDatabaseContext nor LicenseSecurityModel.
2.4 A single destination for logs
The destination of the logs is always defined by LogsSettings:ConnectionString. RestFrontage automatically interprets its value according to the mode chosen under Database :
| Fashion | Expected value in LogsSettings:ConnectionString |
Resolution Completed |
|---|---|---|
| Remote SQL Server | The full SQL Server connection string. | The string is used as is. |
| SQL Server LocalDB | Logical name of the database, for example ImmersiveLogs. |
RestFrontage opens or creates the file <nom>.mdf, and then constructs the LocalDB string. |
| SQLite | For example, the relative name or path of the file ImmersiveLogs.sqlite. |
RestFrontage checks the file next to the executable and builds the SQLite connection. |
This resolution is common to both uses: the batch logger that writes the messages and the context LogsContext who consults them. They can therefore no longer point involuntarily to two different bases.
In LocalDB, do not populate a full SQL string in LogsSettings:ConnectionString, but only the logical name of the database. In SQLite, the file must already exist.
3. GraphicStream Logs – LogsSettings
The GraphicStream logger writes the logs in the background so that it does not open a connection for each message. When a message is produced, it is placed in a queue in memory. At regular intervals, the logger picks up a group of messages from this queue and inserts it into the selected database.
The settings in this section define four elements: the destination, the identification of the producer tool, the capacity of the queue, and how messages are grouped and then retained.
{
"LogsSettings": {
"ProviderIdentifier": 10,
"IncludeScopes": true,
"IsEnabled": true,
"ContainerName": "Log",
"ConnectionString": "<chaine SQL de la base des journaux>",
"FlushPeriod": "00:00:01",
"BackgroundQueueSize": 1000,
"BatchSize": null,
"TableSizeLimit": 10240
}
}
| Key | Default | Real effect and parameterization tips |
|---|---|---|
ConnectionString |
none | The unique destination of the logger and the consultation context. In remote SQL Server, fill in a complete SQL string; in LocalDB, the logical name of the database; in SQLite, the relative name or path of the file. The value is independent of the section ConnectionStrings. |
ContainerName |
Log |
The name of the table receiving the logs. The recommended value is Log, which corresponds to the schema provided by GraphicStream. |
ProviderIdentifier |
0 |
Allows you to differentiate between the different tools that inject into the Log, to share the same log database across multiple GraphicStream tools, such as multiple RestFrontage and/or Hubs. |
IncludeScopes |
true |
Allows the reading of structured information placed in the logging scopes. The logger recognizes in particular Channel, which classifies the message into a channel, and Data, which adds additional data. Without a channel provided, the message is stored in the channel Generic. |
IsEnabled |
true |
Enables the GraphicStream log provider. À false, its processing queue is stopped, and new messages are not logged by this provider. This setting does not necessarily disable any other log destinations that may be configured. |
FlushPeriod |
00:00:01 |
The amount of time to wait between two write cycles. With one second, pending messages are sent to the database approximately every second. A shorter value reduces the time it takes to appear in the database but increases the frequency of hits; a longer value groups more writes but delays their visibility. The duration must be strictly positive. |
BackgroundQueueSize |
1000 |
The maximum number of messages that can wait in memory before they are processed. When the bounded queue is full, the producer waits for a place to become available, so a value that is too low can slow down requests during an influx of logs. null Creates a limitless queue, at the cost of potentially higher memory consumption. Use a strictly positive value. 0 is accepted by the option class but does not allow the queue to be built at runtime. |
BatchSize |
null |
The maximum number of messages that are removed from the queue and inserted in a cycle. null processes all available messages. A positive value limits the size of each batch; if the queue contains more messages, the rest waits for subsequent cycles. A value that is too low can cause a delay when a lot of logs are produced. |
TableSizeLimit |
10240 |
The maximum number of rows kept. After a batch is written, the logger deletes the oldest entries, according to their date, to fall below this limit. null deactivates this automatic purge. A value entered must be strictly positive. |
Example of how to work with the above values: up to 1,000 messages can wait in the queue; approximately every second, all available messages are written in batches since BatchSize is worth null ; After writing, the oldest logs are deleted if the table exceeds 10,240 rows.
With the SQL Server provider, the current mechanism for purging TableSizeLimit explicitly targets the table Log. If ContainerName has a different name, new messages are sent to that other table, but the purge continues to be Log. The SQLite provider purges the specified table. It is still recommended to keep ContainerName à Log.
Storage should not be manually chosen for RestFrontage. The application forces it to SQL for remote SQL Server and LocalDB, or SQLite when Database:EnableSqlite is enabled. Any value Storage present in the JSON is therefore replaced by this calculated choice.
FileSizeLimit, RetainedFileCountLimit, FileName and Extension exist in the option class, but are not used by the SQL Server and SQLite providers selected by RestFrontage.
The levels under Logging and Logging:GraphicStreamLogs:LogLevel are part of standard log filtering and are not detailed here.
4. File Storage – IOSettings
{
"IOSettings": {
"Storage": "AzureBlob",
"ConnectionString": "<secret ou chemin selon le mode>",
"ContainerName": "immersivecontent"
}
}
Storage |
ConnectionString |
ContainerName |
|---|---|---|
AzureBlob |
The connection string of the Azure Storage account. | Container Name: Blob. |
FileSystem |
The root folder of the storage. | Subfolder added to the root. |
HostEnvironment |
Ignored. | A subfolder of the RestFrontage root directory. |
SQL |
The SQL Server connection string. | The name of the table that includes the path and binary content. |
A change requires a restart to be applied consistently.
Pros HostEnvironment, all operations use the same root: ContentRootPath, that is, the root directory of RestFrontage. The existence test, read, write, list, and delete are all targeting <ContentRootPath>/<ContainerName>/<chemin> ; ConnectionString is ignored in this mode.
5. General RestFrontage Settings – Application
{
"Application": {
"Name": "RestFrontage PROD",
"AllowBlankPassword": false,
"PreWarmOrganizations": [ "Organisation A" ],
"TokenLifetime": "08:00:00",
"JWTSecurityKey": "<secret aleatoire d'au moins 32 octets>",
"TaskManagerLoopIdleTime": 60
}
}
| Key | Default | Real effect |
|---|---|---|
Name |
null |
Name returned by the system API; visible fallback: ImmersiveRest Server. |
AllowBlankPassword |
false |
Allows authentication with a blank password and influences initialization auditing. Leave to false in production. |
PreWarmOrganizations |
null |
The names of organizations whose caches are preloaded at startup. An empty array retains on-demand loading. |
TokenLifetime |
08:00:00 |
Duration of JWTs emitted by RestFrontage. |
JWTSecurityKey |
None reliable | HMAC secret used to sign and validate JWTs. It must exceed 256 bits, remain the same between instances, and never be committed. Changing it invalidates existing tokens. |
TaskManagerLoopIdleTime |
60 |
Pause, in seconds, between two passes in the server task loop. Use a strictly positive value. |
The section Application Must exist: The linked application is then requested as a required service during initialization.
In production, AllowBlankPassword must remain at false and JWTSecurityKey must be a random secret of at least 32 bytes, identical on all instances.
6. Azure OpenAI – Application:OpenAI
{
"Application": {
"OpenAI": {
"Endpoint": "https://<ressource>.openai.azure.com",
"ApiKey": "<secret>",
"AssistantName": "asst_<identifiant>",
"APIVersion": "2024-05-01-preview"
}
}
}
| Key | Mandatory for AI | Role |
|---|---|---|
Endpoint |
Yes | The URL of the Azure OpenAI resource. The final slash is removed by the service. |
ApiKey |
Yes | Value sent in the header api-key. |
AssistantName |
Yes | Despite its name, this value must be the technical identifier of the wizard, for example asst_.... |
APIVersion |
No | Azure OpenAI API version; default 2024-05-01-preview. |
The absence of this subsection does not prevent startup; the error is thrown the first time an AI function is called that requires these values.
7. Visual identification - Environment
{
"Environment": {
"Name": "PROD",
"BackgroundColor": "#B00020",
"ForegroundColor": "#FFFFFF",
"Size": 6
}
}
| Key | Default | Role |
|---|---|---|
Name |
empty | Text displayed on the reception desk and in the breadcrumb trail. Without a name, the welcome badge is hidden. |
BackgroundColor |
#333 |
The background CSS color of the environment guide. |
ForegroundColor |
white |
CSS color of the text. |
Size |
7 |
Bootstrap Class Suffix fs-{Size} in breadcrumbs. Use a valid Bootstrap value of 1 à 6. |
This section describes a RestFrontage visual cue; it is separate from the hosting environment name ASP.NET Core.
8. Security Synchronization – SecurityDomainSynchronization
{
"SecurityDomainSynchronization": {
"VersionCheckInterval": "00:00:01"
}
}
VersionCheckInterval is the interval between two reads of the distributed version of the security domain. When another instance publishes a new version, RestFrontage reloads its local domain.
The default value is one second. A zero or negative duration is replaced by a second.
All instances sharing the same databases must use a consistent interval. A very short value reduces propagation delay but increases distributed cache hits.
9. Recovery Console – Recovery
{
"Recovery": {
"AccessKey": "<secret long et aleatoire>"
}
}
AccessKey protects the page /Setup/Tools, designed to remain accessible even when the security base fails. Without a key, the console cannot be unlocked. After validation, access is retained in a signed cookie for 30 minutes.
The dedicated environment variable IMMERSIVE_RECOVERY_KEY takes precedence over Recovery:AccessKey and must be prioritized in production.
Case of Recovery Overloads
A Recovery Overhead is a fallback configuration value that temporarily replaces the normal value with the same name. It is used to repair a server with a misconfigured connection, logs, or storage, without directly modifying the file appsettings.json original.
The console /Setup/Tools saves these values in the optional file appsettings.Recovery.json, placed in the root directory of RestFrontage. For example, if this file contains a new value for ConnectionStrings:ImmersiveModelContainer, this value replaces the value of appsettings.json at the next boot. Other keys that are not in the recovery file continue to come from the normal configuration.
The console can create or complete the following sections:
- The four recognized chains of
ConnectionStrings; LogsSettings;IOSettings.
The recovery file therefore functions as a partial layer overlaid on top of the existing configuration:
appsettings.jsonand other usual configuration files provide normal values;appsettings.Recovery.jsonReplaces only the keys it contains.- Environment variables and launch arguments still take precedence over both files.
Example:
{
"ConnectionStrings": {
"ImmersiveModelContainer": "<chaine SQL de remplacement>"
},
"IOSettings": {
"Storage": "FileSystem",
"ConnectionString": "D:\\ImmersiveData",
"ContainerName": "Content"
}
}
In this example, only the business base and the IOSettings are overloaded. The security baseline, licenses, logs, and all other settings maintain their normal values.
After a save, the console's diagnostic buttons can test the new values with temporary objects. In contrast, the services actually used by RestFrontage—database contexts, logger, and file service—are built at startup. Therefore, RestFrontage must be restarted for the overhead to be used by the application.
The appsettings.Recovery.json can contain secrets and should not be versioned. An overload remains active on each restart as long as its key remains in that file. Correcting the normal configuration then does not automatically reverse an old overload: the corresponding key must also be removed from the recovery file.
10. API Key Authentication - ApiKey
{
"ApiKey": [
{
"App": "Forge",
"Key": "<secret>",
"User": "AN=ServiceForge, OU=Users, DC=Immersive, DC=GraphicStream, DC=fr",
"From": "2026-01-01T00:00:00Z",
"To": "2027-01-01T00:00:00Z"
}
]
}
| Key | Rule |
|---|---|
App |
Expected value in the header x-app-name. The comparison ignores case. An empty value disables the input. |
Key |
Expected value in x-api-key. The comparison is case-sensitive. An empty value disables the input. |
User |
The exact distinguished name of an existing user in the security database. This user becomes the identity of the query. |
From |
Beginning of validity included. |
To |
Purpose excluded from validity. |
Use ISO 8601 dates with time zone, ideally in UTC with the suffix Z. The duration of the internal JWT created for the request is limited to the time remaining before To.
11. SAML - Saml
{
"Saml": {
"FidUrl": "https://<fid>",
"FidSsoPath": "/<chemin-sso>",
"FidSloPath": "/<chemin-slo>",
"EntityId": "<identifiant RestFrontage declare dans la FID>",
"LoginUrl": "https://<restfrontage>/api/Saml/Login",
"LogoutUrl": "https://<restfrontage>/api/Saml/Logout"
}
}
| Key | Role |
|---|---|
FidUrl |
The base URL of the identity federation. |
FidSsoPath |
Path added to FidUrl to construct the SAML connection request. |
FidSloPath |
Path added to FidUrl to construct the SAML logout request. |
EntityId |
The sender declared in SAML requests. |
LoginUrl |
Absolute connection return URL, placed in AssertionConsumerServiceURL. |
LogoutUrl |
Absolute logout return URL. |
12. OpenID – OpenID
{
"OpenID": {
"FidUrl": "https://<fid>/",
"FidAppId": "<client-id>",
"FidAppSecret": "<secret>"
}
}
| Key | Real effect |
|---|---|
FidUrl |
Base URL used to invoke relative paths tokeninfo and userinfo. Keep a final slash. |
FidAppId |
Must match the client_id Returned by tokeninfo. |
FidAppSecret |
Is loaded into the service, but is not currently sent in any OpenID controller calls. |
13. Session
The server session is now Optional. RestFrontage activates it only if the Session contains at least one parameter: Session services are then registered and session middleware is added after routing.
If the section is missing or empty, RestFrontage does not register any session service and does not add the corresponding middleware. This means that the operation remains the same as before conditional activation.
{
"Session": {
"IdleTimeout": "01:00:00",
"Cookie": {
"Name": "Immersive.Server.Session",
"HttpOnly": true,
"SameSite": "Strict",
"SecurePolicy": "Always"
}
}
}
| Key | Role |
|---|---|
IdleTimeout |
The maximum amount of time that session data is idle. An activity using the session extends this time. |
Cookie:Name |
The name of the technical cookie containing the session ID. |
Cookie:HttpOnly |
Prevents the browser's JavaScript from reading the session cookie. Keep true. |
Cookie:SameSite |
Controls the sending of the cookie when browsing from another site. Strict is the most restrictive setting. |
Cookie:SecurePolicy |
With Always, the cookie is only sent over HTTPS. |
Session uses the IDistributedCache already stored by RestFrontage. The cookie does not contain session data: it only contains an identifier that can be used to retrieve this data in the distributed cache.
Activate Session does not override existing authentication. The session cookie set here is separate from the authentication cookie RestFrontage.Auth, which remains set to eight hours. The session middleware creates the session cookie only when a component actually uses HttpContext.Session.
To explicitly keep the historical operation without a session, delete the section entirely or leave it blank:
{
"Session": {}
}
The recognized keys are:
Session:IdleTimeout;Session:Cookie:Name;Session:Cookie:HttpOnly;Session:Cookie:SameSite;Session:Cookie:SecurePolicy.
14. Secrets Management
The appsettings file contains values that can be real SQL passwords, an Azure Storage account key, an Azure OpenAI key, and a JWT key. They are purposely not reproduced in this documentation.
If these values are active or have been committed, they must be renewed regularly. At a minimum, the following must be outsourced:
ConnectionStrings__ImmersiveModelContainer;ConnectionStrings__SecurityModelContainer;ConnectionStrings__ServerDatabaseContext;ConnectionStrings__LicenseModelContainer;LogsSettings__ConnectionString;IOSettings__ConnectionString;Application__JWTSecurityKey;Application__OpenAI__ApiKey;OpenID__FidAppSecret;ApiKey__0__Key, and then the following indexes;IMMERSIVE_RECOVERY_KEY.
Versioned files should retain only non-functional override values.
15. Sample Cleaned Production
This example groups together the useful RestFrontage settings without the standard Core ASP.NET topics:
{
"Database": {
"EnableLocalDB": false,
"EnableSqlite": false
},
"ConnectionStrings": {
"ImmersiveModelContainer": "<injecte hors du fichier>",
"SecurityModelContainer": "<injecte hors du fichier>",
"ServerDatabaseContext": "<injecte hors du fichier>",
"LicenseModelContainer": "<injecte hors du fichier>"
},
"Environment": {
"Name": "PROD",
"BackgroundColor": "#B00020",
"ForegroundColor": "#FFFFFF",
"Size": 6
},
"Recovery": {
"AccessKey": "<injecte via IMMERSIVE_RECOVERY_KEY>"
},
"SecurityDomainSynchronization": {
"VersionCheckInterval": "00:00:01"
},
"LogsSettings": {
"ProviderIdentifier": 10,
"IncludeScopes": true,
"IsEnabled": true,
"ContainerName": "Log",
"ConnectionString": "<injecte hors du fichier>"
},
"IOSettings": {
"Storage": "AzureBlob",
"ConnectionString": "<injecte hors du fichier>",
"ContainerName": "immersivecontent"
},
"Application": {
"Name": "RestFrontage PROD",
"AllowBlankPassword": false,
"PreWarmOrganizations": [],
"TokenLifetime": "08:00:00",
"JWTSecurityKey": "<injecte hors du fichier>",
"TaskManagerLoopIdleTime": 60,
"OpenAI": {
"Endpoint": "https://<ressource>.openai.azure.com",
"ApiKey": "<injecte hors du fichier>",
"AssistantName": "asst_<identifiant>",
"APIVersion": "2024-05-01-preview"
}
},
"ApiKey": [],
"Saml": {
"FidUrl": "https://<fid>",
"FidSsoPath": "/<chemin-sso>",
"FidSloPath": "/<chemin-slo>",
"EntityId": "<entity-id>",
"LoginUrl": "https://<restfrontage>/api/Saml/Login",
"LogoutUrl": "https://<restfrontage>/api/Saml/Logout"
},
"OpenID": {
"FidUrl": "https://<fid>/",
"FidAppId": "<client-id>",
"FidAppSecret": "<injecte hors du fichier>"
}
}
Subsections OpenAI, ApiKey, Saml and OpenID can be omitted when the corresponding functions are not used.
16. Pre-commissioning inspection
- Only one basic mode is enabled.
- The channels have exactly the expected names.
- The log database is configured in
LogsSettings:ConnectionString. -
JWTSecurityKeyis random, long enough, and the same across all instances. -
AllowBlankPasswordis worthfalsein production. - No real secrets are stored in a versioned file.
- Organizations from
PreWarmOrganizationsreally exist. - API keys have an application, a key, an existing user, and a valid time period.
- SAML contains both paths well
FidSsoPathandFidSloPath. - Values
???were overridden before enabling SAML or OpenID. - The section
Sessionis absent or empty if no server session is desired; otherwise its cookie is set to HTTPS. - RestFrontage was restarted after a change in connection, storage, logs, or JWT secret.