Installation & Deployment
Installing the Provision Portal UI — an Angular single-page application served by Nginx, which also
reverse-proxies /prov-api/ to the Provision Portal backend.
1. Overview
This guide deploys one container: the Provision Portal UI, whose TLS pair ships in the Provision Portal UI
folder on FT_DISK. The image is built from docker/Dockerfile on top of nginx:alpine; it copies the
pre-built Angular application (dist/provision-portal_angular/browser) to
/usr/share/nginx/html/provision-portal and serves it. There is no Node.js in the runtime image.
The deployment method is Docker (Compose or docker run) — this repository does not build a
distribution archive.
It is a plain Compose service on the ft-network bridge, deployed from /usr/local/ft-system/ under
the Compose project name ft-system — the same layout as every deployment guide in the Friendly Tech
portal. The Provision Portal UI folder on FT_DISK carries a single-service compose.yml in that
layout, for a host that runs this service on its own, plus the TLS pair this container mounts. On a
host running the full FT System stack the same service block is already part of the stack
compose.yml from the FT System MySQL Stack / FT System Oracle Stack folder — use that one, and
take the shared root .env from the same folder.
The Provision Portal backend (the Spring Boot / Flowable service served at the /prov-portal/ context
path) is assumed to be already deployed and reachable; it is not deployed by this guide — see
Provision Portal API — Installation & Deployment. The two meet
at exactly one setting, FT_PROV_API_URL (Pointing at the Backend): the browser never talks to the
backend directly, it calls the same-origin path /prov-api/, and Nginx proxies that to the URL in
FT_PROV_API_URL.
2. Prerequisites
2.1. Host Requirements
| Component | Minimum | Recommended | Notes |
|---|---|---|---|
Docker Engine |
19.03 |
verify with DevOps |
|
Docker Compose |
v2 ( |
v2 |
All commands in this guide use the Compose v2 CLI plugin syntax. |
RAM |
verify with DevOps |
verify with DevOps |
Not pinned in this repository — |
Disk |
verify with DevOps |
verify with DevOps |
Sized by the |
|
Node.js is required only to produce the Angular build from source (see [build-from-source]). The
runtime image is |
2.2. Required External Dependencies
These services must be installed, running, and reachable from this host before the Provision Portal UI starts. None of them are deployed by this guide.
| Component | Minimum Version | Why It Is Needed | Port | Required |
|---|---|---|---|---|
Provision Portal backend |
verify with the backend owner |
Serves every API call the SPA makes (authentication, provisioning, device status, logs, user management) at the |
8080 on the shared bridge, or 8091 published across hosts ( |
Yes |
Registry reachability is not a runtime dependency of this container and is therefore not listed above; it is covered by Registry Access and Registry Authentication.
The backend in turn reaches the Friendly TR-069 ACS and its database. Those are never contacted by the browser or by this container.
2.3. Supported Operating Systems
| Deployment | Operating system |
|---|---|
Docker (Compose or |
Linux (recommended), macOS, or Windows with WSL2 |
2.4. Registry Access
Network access to the hub.friendly-tech.com Docker registry (or offline image archives — see
Offline Servers).
Read-only pull credentials for the registry are issued by the DevOps team; request them before starting. They are sufficient for installation and upgrades.
Access to FT_DISK — Provision Portal UI for compose.yml and the self-signed TLS pair;
the shared root .env comes from the FT System MySQL Stack / FT System Oracle Stack folder, or is
written from the three values in Environment Configuration.
docker/docker-compose.yml in this repository is a local build-and-run file, not the deployment
descriptor.
3. Network Requirements
| Destination | Port | Protocol | Purpose |
|---|---|---|---|
Provision Portal backend (host taken from |
8080 on the shared bridge, 8091 published across hosts — whatever |
HTTP |
Nginx |
|
443 |
HTTPS |
Pulling the |
3.1. Docker Networking
provision-portal joins the ft-network bridge of the ft-system Compose project, together with
every other FT service on the host. It reaches the backend by whatever hostname FT_PROV_API_URL
contains, resolved from inside the container — the provision-api service name on this host, an IP
address across hosts; see Pointing at the Backend.
localhost and 127.0.0.1 never work here — inside the container they point at the container
itself.
4. Registry Authentication
All Provision Portal UI images are pulled from hub.friendly-tech.com.
Authenticate once per host before the first docker compose up.
docker login hub.friendly-tech.com
Enter the read-only pull credentials when prompted. Request the user name and password from the DevOps team — they are not published in this documentation.
|
The read-only account provides pull-only access to the published images. It cannot push. For elevated Harbor access (push rights, a dedicated robot token), contact the DevOps team. |
Alternatively, log in non-interactively, reading the password from a file that is not committed anywhere:
docker login hub.friendly-tech.com -u <readonly-user> --password-stdin < ~/.ft-harbor-password
Verify authentication:
docker info | grep -A 5 Registry
Then pull the image:
docker pull hub.friendly-tech.com/ui/provision-portal:<tag>
CI publishes the image for linux/amd64 only (platforms: 'linux/amd64' in
.github/workflows/build-callable.yml, and the same platform in docker/docker-push.sh).
Building the image from source. Developers who cannot use a published image build it locally. The
Dockerfile is runtime-only: it copies an already-produced dist/, so the Angular build runs first.
git clone <repository-url> provision-portal_angular
cd provision-portal_angular
npm ci
npm run build # emits dist/provision-portal_angular/browser
docker build -f docker/Dockerfile -t provision-portal-ui:local .
CI runs ng build --project=provision-portal_angular -c=production --base-href /provision-portal/
after npm install --legacy-peer-deps. The Node.js version is not pinned in this repository
(no engines field, no setup-node step) — verify with the build owner before choosing one.
To build and push the way docker/docker-push.sh does:
docker buildx create --name multi --driver docker-container --use
docker buildx build --platform linux/amd64 --push \
-f docker/Dockerfile -t hub.friendly-tech.com/ui/provision-portal:<tag> .
4.1. Offline Servers
When the Provision Portal UI host cannot reach hub.friendly-tech.com, pull the image on a machine
that does have registry access, export it to an archive, transfer it, and load it on the offline
host.
The connected machine can run Linux, macOS, or Windows — commands are given for both shells below. It does not need to be the same platform as the offline host.
|
An explicit |
-
On the offline host, find out which architecture it runs — this is the value you will pass as
PLATFORMbelow. Ask Docker itself, since it reports what the daemon will actually accept:docker version --format '{{.Server.Arch}}'If Docker is not installed there yet, use the operating system instead —
uname -mon Linux, orecho $env:PROCESSOR_ARCHITECTUREin PowerShell on Windows. Map the result:docker versionreportsuname -m/ Windows reportsUse as PLATFORMamd64x86_64/AMD64linux/amd64arm64aarch64/ARM64linux/arm64On Windows with Docker Desktop,
{{.Server.Arch}}reports the architecture of the Linux VM that actually runs the containers — which is the value you want, not the Windows host’s own architecture. -
On a machine with registry access, log in. Run this on its own — it prompts for a password, so anything pasted after it on the same go would be swallowed as input:
docker login hub.friendly-tech.com -
Pull and export the image. Paste the whole block as-is; the only lines to change are
PLATFORMandTAGon top.Linux / macOS (bash):
PLATFORM=linux/amd64 TAG=<tag> docker pull --platform "$PLATFORM" "hub.friendly-tech.com/ui/provision-portal:$TAG" docker save "hub.friendly-tech.com/ui/provision-portal:$TAG" | gzip > "provision-portal-ui-$TAG.tar.gz"Windows (PowerShell):
$PLATFORM = "linux/amd64" $TAG = "<tag>" docker pull --platform $PLATFORM "hub.friendly-tech.com/ui/provision-portal:$TAG" docker save -o "provision-portal-ui-$TAG.tar" "hub.friendly-tech.com/ui/provision-portal:$TAG"On Windows, always write the archive with
docker save -o <file>. Piping or redirectingdocker savefrom PowerShell (docker save … > file.tar) corrupts the archive, because the PowerShell pipeline re-encodes the stream as text instead of passing raw bytes.docker loadthen fails withunexpected EOForinvalid tar header. To compress for transfer, use the built-intar.exe(Windows 10 1803+ / Server 2019+):tar.exe -czf provision-portal-ui.tar.gz provision-portal-ui-$TAG.tar. -
Transfer the archive to the offline host, together with
compose.ymland thessl/pair (friendly.crt,friendly.key) from the Provision Portal UI folder, and the root.env— see Directory Layout. -
On the offline host, load the archive and start the service. Set
TAGto the same value you used above:Linux (bash):
TAG=<tag> gzip -dc "provision-portal-ui-$TAG.tar.gz" | docker load cd /usr/local/ft-system docker compose up -d provision-portalWindows (PowerShell):
$TAG = "<tag>" docker load -i "provision-portal-ui-$TAG.tar" cd /usr/local/ft-system docker compose up -d provision-portal
Confirm the image is present before starting, so a missing or mis-architected image fails here rather than mid-startup:
docker images hub.friendly-tech.com/ui/provision-portal
Upgrades use the same flow: pull the new tag on the connected machine, transfer and load the archive, then docker compose up -d provision-portal.
5. Preparation
5.1. Directory Structure
The platform layout gives each service one directory directly under /usr/local/ft-system, beside the
host-level compose.yml and the shared .env. This container needs two directories of its own — an
empty log directory does not survive a download:
mkdir -p /usr/local/ft-system/provision-portal/{ssl,nginx/logs}
cd /usr/local/ft-system
This follows the platform layout documented in
Full System Deployment:
one directory per service directly under /usr/local/ft-system.
5.1.1. Directory Layout
Once the files below are in place, the Provision Portal UI part of /usr/local/ft-system/ looks like
this:
/usr/local/ft-system/
├── compose.yml # from FT_DISK -- Provision Portal UI (or the FT System <vendor> Stack)
├── .env # shared stack environment
└── provision-portal/
├── ssl/ # -> /etc/nginx/ssl (read-only)
│ ├── friendly.crt
│ └── friendly.key
└── nginx/
└── logs/ # -> /var/log/nginx (created above)
| Path | Content | Backup |
|---|---|---|
|
Stack definition, including the |
Yes |
|
Shared stack environment. The three values this container reads live here: |
Yes |
|
|
Yes |
|
Nginx access and error logs, mounted at |
No |
|
The backend is deployed from its own FT_DISK folder into the sibling directory |
5.1.2. FT_DISK Downloads
Download the following from FT_DISK — Provision Portal UI; the root .env comes from
the FT System MySQL Stack / FT System Oracle Stack folder or is written from the three values in
Environment Configuration:
| Component | FT_DISK | Target | Files |
|---|---|---|---|
Stack definition |
|
|
|
Shared environment |
FT System MySQL Stack / FT System Oracle Stack |
|
|
Provision Portal UI certificate |
|
Only the TLS pair: |
There is no per-service .env in the folder, and that is deliberate: the container reads exactly one
setting of its own, FT_PROV_API_URL, and that setting lives in the root .env next to the two
published ports. A per-service copy would be a second place to edit the same values — and the
published ports could not live there at all ([env-file-is-not-interpolated]).
5.2. Environment Configuration
Every value this container needs comes from the shared root .env, which compose.yml uses twice: it
hands the file to the container through env_file:, and it reads the same file to interpolate
$\{…} inside compose.yml.
This container needs no database, no Flowable schema, no Northbound API and no JWT secret: tokens are issued and validated by the backend.
| Variable | Description | Default | Required |
|---|---|---|---|
|
Upstream URL used by Nginx |
|
Yes |
|
Published HTTP port ( |
|
Yes |
|
Published HTTPS port ( |
|
Yes |
|
Container time zone |
|
No |
|
Why the published ports live in the root Moved into a per-service env file, |
5.2.1. Pointing at the Backend
FT_PROV_API_URL is the only link between the two services. Its value depends on where the backend
runs:
| Backend runs | FT_PROV_API_URL |
|---|---|
On this host |
|
On another host |
|
|
Set Since Nginx resolves the |
The browser API base path is not configurable. docker/ops/entrypoint.sh rewrites
assets/config/app.config.json with jq so that .apiUrl is the fixed relative value /prov-api/,
matching the Nginx location. The browser calls /prov-api/… same-origin, Nginx forwards to
FT_PROV_API_URL.
The Angular app loads assets/config/app.config.json before it boots
(ConfigService.loadConfig() in an app initializer), so apiUrl is available to the first HTTP
call. See Configuration.
5.3. TLS Certificate (required)
There is no HTTPS_ENABLED switch and no keystore environment variable. nginx.conf.template
contains listen 443 ssl unconditionally and reads /etc/nginx/ssl/friendly.crt and
/etc/nginx/ssl/friendly.key, so in practice the certificate mount is mandatory: without it Nginx
fails to start. TLSv1.2 and TLSv1.3 with ECDHE ciphers are configured in the template.
FT_DISK ships a self-signed pair, enough to start the container. To generate a fresh one on the
deployment host (run from /usr/local/ft-system/provision-portal) — a deployment host installing from the registry image has no source
checkout, so docker/generate-cert.sh is not available there, and the command below is what that
script does:
openssl req -x509 -nodes -days 3650 -newkey rsa:4096 \
-keyout ssl/friendly.key \
-out ssl/friendly.crt \
-subj "/C=IL/ST=Israel/L=Tel-Aviv/O=Friendly Tech./CN=friendly-tech.com" \
-addext "subjectAltName=DNS:friendly-tech.com,DNS:*.friendly-tech.com,DNS:localhost,IP:127.0.0.1"
chmod 600 ssl/friendly.key
chmod 644 ssl/friendly.crt
In a source checkout the equivalent is cd docker && ./generate-cert.sh, which writes
docker/ssl/friendly.crt and docker/ssl/friendly.key for the local build compose file.
For production, install a CA-issued pair under the same file names:
cp your-cert.crt ssl/friendly.crt
cp your-cert.key ssl/friendly.key
chmod 600 ssl/friendly.key
The certificate directory is mounted read-only at /etc/nginx/ssl and the HTTPS port is published by
the stack compose.yml (${PROV_PORTAL_HTTPS_PORT:-8893}:443) — see Docker Compose.
Rotate certificates before expiry — the self-signed command above issues a 10-year certificate and is
for internal use only. The container also serves plain HTTP on container port 80 (published as
8890); redirect or firewall it if your environment requires HTTPS only.
If Nginx fails to start because of the certificate, see Container Fails to Start.
6. Deployment
6.1. Startup Dependencies
provision-portal has no depends_on in the shipped compose.yml — the backend is external to
that stack. Three conditions are on you:
-
TLS certificate and key present in
provision-portal/ssl/— Nginx will not start without them. -
The host in
FT_PROV_API_URLmust resolve when the container starts:proxy_passuses a literal host, which Nginx resolves while loading the configuration. The backend does not have to be serving requests yet, but its name must resolve — see Pointing at the Backend. -
The image must be available locally (pulled or loaded).
In the full FT System stack the same service block carries depends_on: provision-api:
condition: service_healthy, so the backend is up — and its service name resolves on the shared
bridge — before Nginx loads its configuration.
|
6.2. Docker Compose
Click to expand compose.yml (Provision Portal UI)
services:
provision-portal:
image: hub.friendly-tech.com/ui/provision-portal:latest
container_name: provision-portal
# The backend is external to this stack, so there is no depends_on. Its
# host in FT_PROV_API_URL must resolve when the container starts: Nginx
# resolves the upstream while loading its configuration.
env_file:
- .env
ports:
- "${PROV_PORTAL_HTTP_PORT:-8890}:80" # HTTP
- "${PROV_PORTAL_HTTPS_PORT:-8893}:443" # HTTPS
volumes:
- ./provision-portal/ssl:/etc/nginx/ssl:ro # friendly.crt + friendly.key, required by the shipped config
- ./provision-portal/nginx/logs:/var/log/nginx
extra_hosts:
# Lets FT_PROV_API_URL use host.docker.internal when the backend runs on
# this host outside this stack. Harmless otherwise.
- "host.docker.internal:host-gateway"
healthcheck:
test: ["CMD", "curl", "-f", "http://127.0.0.1/provision-portal/index.html"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
stop_grace_period: 45s
networks:
- ft-network
networks:
ft-network:
driver: bridge
There is no per-service env_file: layer for this container: everything it reads is in the root
.env (Environment Configuration). Set FT_PROV_API_URL there before the first start
(Pointing at the Backend); to change a published port, set PROV_PORTAL_HTTP_PORT /
PROV_PORTAL_HTTPS_PORT in the same file.
|
In the full FT System stack the same block additionally carries |
6.2.1. Start the Stack
cd /usr/local/ft-system
docker login hub.friendly-tech.com
docker compose up -d provision-portal
docker compose ps
docker compose logs -f provision-portal | grep -i "nginx.conf generated"
curl -sk https://localhost:8893/provision-portal/index.html | head -1
Without Compose. The same deployment as a single docker run, executed from
/usr/local/ft-system (where the Directory Structure step left you):
docker run -d \
--name provision-portal \
-p 8890:80 \
-p 8893:443 \
--env-file .env \
-v "$PWD/provision-portal/ssl:/etc/nginx/ssl:ro" \
-v "$PWD/provision-portal/nginx/logs:/var/log/nginx" \
--add-host=host.docker.internal:host-gateway \
--restart unless-stopped \
hub.friendly-tech.com/ui/provision-portal:<tag>
Outside Compose there is no shared bridge, so FT_PROV_API_URL must use a published port here — http://host.docker.internal:8091/prov-portal/ on this host — either in the root .env or as -e FT_PROV_API_URL=… on the command above.
|
docker/docker-compose.yml in this repository is the local build variant: it builds from
docker/Dockerfile, tags the result ui/provision-portal:tmp and publishes 8880:80 for local
development only. The platform assigns this image the published ports 8890 → 80 and 8893 → 443
(Full System Deployment — Port Reference);
8880 / 8843 on a shared host belong to the Portals container and would collide. This guide follows
the platform — see docs/decisions/LOG.md.
7. Verification
7.1. Startup Log
docker compose logs -f provision-portal
docker/ops/entrypoint.sh prints, in order:
Generating nginx.conf from template...
nginx.conf generated with FT_PROV_API_URL=<your value>
Patched app.config.json -> .apiUrl = /prov-api/
A WARN: nginx.conf.template not found or WARN: … app.config.json not found (skipping) line
means the image is not the expected one.
7.2. Endpoint Checks
# 1. Container is up with both mappings
docker compose ps
# 2. The SPA is served over HTTP (host 8890 -> container 80)
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8890/provision-portal/
# Expected: 200
# 3. The no-slash form redirects
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8890/provision-portal
# Expected: 301
# 4. TLS listener answers (host 8893 -> container 443)
curl -sk -o /dev/null -w "%{http_code}\n" https://localhost:8893/provision-portal/
# 5. The runtime API base was patched to the relative proxy path
docker compose exec provision-portal \
cat /usr/share/nginx/html/provision-portal/assets/config/app.config.json
# Expected: { "apiUrl": "/prov-api/" }
# 6. The backend answers through the proxy
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8890/prov-api/
Then open http://<HOST>:8890/provision-portal/ in a browser.
8. Port Reference
Ports are written as published → container. Across hosts you connect to the published port; inside
the Docker bridge you connect to the container port.
8.1. HTTP / HTTPS
| Port | Protocol | Purpose | Exposure |
|---|---|---|---|
8890 → 80 |
HTTP |
Serves the SPA under |
Public |
8893 → 443 |
HTTPS |
TLS listener; requires |
Public |
The published ports are the ones the platform assigns to this image; docker/docker-compose.yml in
this repository publishes 8880:80 for local development only, and 8880 / 8843 belong to the
Portals container on a shared host.
8.2. Outbound Connections
| Destination | Port | Protocol | Purpose |
|---|---|---|---|
Provision Portal backend (host from |
8080 on the shared bridge, 8091 published across hosts — whatever |
HTTP |
|
|
443 |
HTTPS |
Image pull and update. |
9. Stack Management
9.2. Start, Stop, Restart
docker compose up -d provision-portal # start
docker compose stop provision-portal # stop, keep the container
docker compose restart provision-portal # restart (re-runs the entrypoint)
docker compose down # stop and remove EVERY container of the ft-system project
9.3. Shell Access
docker compose exec provision-portal bash # bash is installed in the image
docker compose exec provision-portal cat /etc/nginx/nginx.conf
docker compose exec provision-portal env | grep FT_PROV_API_URL
9.4. Updating Provision Portal UI
Online hosts:
docker compose pull provision-portal
docker compose up -d provision-portal
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8890/provision-portal/
Offline hosts: pull, save and transfer the new image as described in Offline Servers, then
gzip -dc provision-portal-ui-<new-tag>.tar.gz | docker load
docker compose up -d provision-portal # after updating the tag in compose.yml
To roll back, set the previous tag in compose.yml and run docker compose up -d provision-portal
again.
10. Production Checklist
-
FT_PROV_API_URLpoints at the correct backend/prov-portal/context path and its hostname resolves from inside the container. -
A CA-issued
friendly.crt+friendly.keyare mounted at/etc/nginx/ssl/, andssl/friendly.keyischmod 600. -
Both mappings are published:
8890:80and8893:443. -
The image tag is pinned to a release tag, never
latest— the stackcompose.ymluseslatest. -
restart: unless-stoppedis set. -
Resource limits are set (
deploy.resources.limitsor--memory) — nothing is set by default. -
The backend is reachable at the address in
FT_PROV_API_URL(Pointing at the Backend); across two hosts, verify the firewall allows port 8091. -
Container stdout/stderr is collected by the Docker logging driver or a log aggregator.
11. Troubleshooting
Start with:
docker compose logs --tail 100 provision-portal
docker compose exec provision-portal env | grep FT_PROV_API_URL
11.1. Container Fails to Start
Symptom: the container starts and immediately exits, or the log shows an SSL certificate error or
an Nginx host not found in upstream error.
Cause and fix:
-
The certificate mount is missing.
nginx.conf.templatealways listens on 443 and reads/etc/nginx/ssl/friendly.crt+friendly.key. Confirm the./provision-portal/sslvolume is mounted and both files exist and are readable. For testing, generate a self-signed pair as shown in TLS Certificate (required). -
The hostname in
FT_PROV_API_URLdoes not resolve. Nginx resolves the literalproxy_passhost when it loads the configuration. Check the rendered file:docker compose exec provision-portal cat /etc/nginx/nginx.conf.
11.2. UI Loads but Requests Fail
Symptom: the login page appears, but login fails or no data loads.
Check:
docker compose exec provision-portal \
cat /usr/share/nginx/html/provision-portal/assets/config/app.config.json
# Expected: { "apiUrl": "/prov-api/" }
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8890/prov-api/
Fix:
-
Verify
FT_PROV_API_URLin the root.envpoints at a running backend, ends with the/prov-portal/context path, and matches the topology — service name and container port on one host, IP and published port across two (Pointing at the Backend). Neverlocalhost: inside the container it points at the container itself. -
Across two hosts, check the firewall between them:
curl -s http://<api-host-ip>:8091/prov-portal/actuator/health.
11.3. Port Already in Use
Symptom: address already in use when starting the container.
Check: lsof -i :8890 or docker ps.
Fix: stop the conflicting process, or change PROV_PORTAL_HTTP_PORT in the root .env — see
[env-file-is-not-interpolated] for why the published ports live there.
11.4. Blank Page or JavaScript Errors
Symptom: the page loads blank, or the browser console shows errors.
Check: open DevTools → Console, and confirm assets/config/app.config.json is served and contains
"apiUrl": "/prov-api/".
Fix: an empty or missing config file means the entrypoint’s jq patch did not run — check
docker compose logs provision-portal for the Patched app.config.json line.
[[404-on-deep-links-or-refresh]] === 404 on Deep Links or Refresh
Symptom: opening a route directly, or refreshing, returns 404.
Fix: the location /provision-portal/ block uses try_files $uri $uri/ /provision-portal/index.html.
Confirm the request path is under /provision-portal/ and that the build output was copied to
/usr/share/nginx/html/provision-portal (docker compose exec provision-portal ls
/usr/share/nginx/html/provision-portal). The CI build sets --base-href /provision-portal/; a build
without it will not resolve its assets.
11.5. Permission Denied on Mounted Volumes
Symptom: the container starts but provision-portal/nginx/logs/ stays empty, or the log shows Nginx failing to open its log files.
Fix:
sudo chown -R $(whoami):$(whoami) /usr/local/ft-system/provision-portal
chmod -R 755 /usr/local/ft-system/provision-portal/nginx/logs
chmod 600 /usr/local/ft-system/provision-portal/ssl/friendly.key
chmod 644 /usr/local/ft-system/provision-portal/ssl/friendly.crt
The ssl/ mount is read-only, so it needs read access only — but the key must stay unreadable to
other users on the host.
11.6. Getting Support
Collect the following before contacting the Friendly Technologies support team:
docker compose logs --tail 500 provision-portal > provision-portal-ui.log
docker compose exec provision-portal cat /etc/nginx/nginx.conf > nginx.rendered.conf
docker compose exec provision-portal \
cat /usr/share/nginx/html/provision-portal/assets/config/app.config.json
docker inspect $(docker compose ps -q provision-portal) --format '{{json .Config.Env}}'
Include the image tag in use and whether the host is online or offline.
12. Related Documentation
-
Provision Portal API — Installation & Deployment — the backend, deployed from its own FT_DISK folder; Pointing at the Backend seen from its side is Connecting the UI
-
All in one server deployment — the platform stack this service joins, and the root
compose.yml/.envit is deployed from -
Separate server deployment — Server E — the split topology, with the backend and the APIs
-
Full System Deployment — Port Reference — the platform-wide port map
The repository README covers the local development workspace and the local production build.