Configuration
The portals are configured at container start time, not at build time, so the same image runs across environments without a rebuild.
Runtime config: app-config.json
Each portal ships an Angular runtime configuration file under its assets. AppConfigService
(@ft/common/services) loads assets/app-config.json before the application bootstraps and keeps
it in a static field, so a missing or malformed file stops start-up with
Could not load the config file.
Sources in this repository:
projects/support-center/src/assets/app-config.json
projects/management-console/src/assets/app-config.json
In the running container the same files are served from the Nginx document root — note the
browser/ level introduced by the Angular 19 application builder:
/usr/share/nginx/html/support-center/browser/assets/app-config.json
/usr/share/nginx/html/management-console/browser/assets/app-config.json
Fields:
| Field | Meaning |
|---|---|
|
Set by the entrypoint from |
|
The build-time portal name ( |
|
Link target for the product information entry. |
|
Base URL every REST call is built on. |
|
WebSocket endpoint placeholder ( |
|
Client-side polling switch and interval in milliseconds. |
The key field is server.api. The container entrypoint patches it with jq at startup:
.server.api = "/iot-webservice/"
A relative path: the browser calls the portals origin, and Nginx proxies the request to the
address configured in FT_UI_BACKEND_URL. Running from source, the checked-in absolute development
URL is used instead, so no proxy is involved.
Startup sequence
On start, docker/ops/entrypoint.sh performs five steps before Nginx serves traffic:
-
Render
nginx.conf—envsubstexpands the upstream URLs,METRICS_ALLOW_IPand the DNS resolver into/etc/nginx/nginx.conf.template. -
Patch runtime config — rewrite
.server.apiand.company(fromFT_COMPANY_NAME) in each app’sapp-config.json. -
Apply branding overrides — copy any present file from
FT_BRANDING_DIRover the matching built-in asset in both portals; a missing file is left at its default and logged as aWARN. See Branding. -
Upload portal permissions — one
PUTper portal to the backend, tagged by client type (sc= Support Portal,mc= Management Portal) and authenticated with the internal keyword header. -
Start Nginx — serve both portals and proxy the upstreams.
See Installation & Deployment for the exact commands and the verification steps that confirm the patch and upload succeeded.
Settings that come from the backend
Some behaviour is configured server-side and read at runtime through the settings API, not through
app-config.json:
-
AIServiceConnectionURL— enables the AI assistant and provides its base URL. -
The Grafana dashboard URLs used by the system-overview pages.
-
Portal permissions per user group, uploaded by the entrypoint and enforced by the backend.
Branding
One image serves every customer: the company name and the four brandable images are supplied at container start, not baked into the image. Both portals are branded identically — there is no per-portal override.
Company Name
FT_COMPANY_NAME is written into .company in both portals' app-config.json at startup (see
Runtime config: app-config.json above). It appears in:
-
the About dialog
-
the sidebar header
-
the login, restore-password and change-password screens
Default: Friendly Technologies — byte-identical to the value already shipped in the image, so
leaving the variable unset reproduces current behavior exactly.
Branding Folder
FT_BRANDING_DIR (default /branding) is a path inside the container, backed by a folder
mounted read-only from the host. It is flat — no subfolders — and holds up to four files,
applied to both portals:
| File | Replaces |
|---|---|
|
The browser tab icon. |
|
The About-dialog logo (light theme). |
|
The About-dialog logo (dark theme). |
|
The login-screen background. |
Any other file in the folder is ignored.
Ready-made asset sets for existing customers are checked in as a starting point:
projects/customization-for-customers/radisys/ and
projects/customization-for-customers/genix/.
Fallback Behavior
-
A present file is applied to both portals.
-
An absent file leaves that one artifact at its built-in default and logs a
WARNnaming the file — the fallback is per file, not all-or-nothing; every other present file is still applied. -
An empty folder, or one holding none of the four supported names, means branding is not in use: every default stays in place, one informational line, no warnings. The folder is part of the standard directory layout, so an installation that does not brand still has it — warning on every start there would make the
WARNmeaningless where it matters. -
A folder missing entirely, or
FT_BRANDING_DIRpointing at something that is not a directory, is treated the same way: quiet, defaults kept. -
The
WARNfor an absent file therefore appears only once at least one supported file is present — that is, once the operator has visibly opted in and forgotten the rest. -
Symlinks inside the folder are rejected with a warning — a security measure, see [branding-trust].
-
A branding problem never prevents the container from starting.
Example log lines:
branding: file=logo.png portal=support-center applied
WARN: branding: file=favicon.ico missing or not a regular file in dir=/branding, keeping built-in default
|
Replacing or adding a file takes effect on the next container restart. Removing a file to fall back to the built-in default does not — files are copied into the container’s writable layer, which survives a plain restart. Removing a file from the host folder requires recreating the container:
|
|
Do not populate the branding folder directly from an untrusted customer upload. Whoever writes that folder is trusted at the same level as whoever writes the compose file — treat it as deployment-time configuration, not user-submitted content. |
Do not bind-mount assets/app-config.json directly to set the company name — use
FT_COMPANY_NAME instead. Mounting that file makes the container’s startup rewrite of it fail
(see Runtime config: app-config.json).
|
What Branding Does Not Change
-
The browser tab title (
Support Portal/Management Portal) — a build-time constant. -
The About-dialog copyright line, which intentionally stays
Friendly Technologies LTD— the software copyright belongs to Friendly Technologies regardless of whose logo is shown. -
appNameandmoreInformationUrlinapp-config.json. -
The sidebar brand mark and the AI-chat icons and text — deliberately out of scope in this version.
See Installation & Deployment — Environment Configuration for the variable table and defaults, Installation & Deployment — Preparation for the host-side folder layout, and Installation & Deployment — Branding for the Compose snippet.
Environment variables
The container environment variables that drive the startup sequence — their names, defaults,
whether each is required, and a complete .env example — are documented once, in
Installation & Deployment — Environment Configuration.