All-in-One UI Services Deployment
Overview
This deployment runs all UI services on a single host using Docker Compose:
-
UI Backend (Spring Boot)
-
UI Portals (Angular on Nginx)
-
FT Device Network Service (Spring Boot)
-
AI Agent Service (Python)
-
PostgreSQL database (for AI Agent)
Prerequisites
Required External Components
The following components must be installed and accessible before deployment:
| Component | Purpose | Default Port |
|---|---|---|
MySQL or Oracle |
Main application database |
3306 (MySQL) / 1521 (Oracle) |
Hazelcast |
Distributed cache |
5701 |
FTACS Application |
ACS web service |
8080 |
Clickhouse |
Analytics database |
9000 |
Preparation
1. Prepare Configuration Directory
Create the required directory structure:
mkdir -p /usr/local/ft-services/{ui-backend-conf,ft-data/{ui-portals/{backend,nginx}/logs,ft-device-network/logs,ai-agent/postgres/data}}
Download the deployment files (compose.yml, .env.mysql, .env.oracle) from the FT_DISK on SharePoint and place them into the working directory.
Volume Mounts & Directory Layout
The ui-backend-conf folder contains essential configuration files for the backend service. Download pre-configured files from the FT_DISK on SharePoint and place them into the directory. See UI Services on Separate Host for detailed configuration instructions.
The tree below shows the baseline layout plus common environment-dependent entries. Not every deployment needs every entry, but the standard SharePoint package can include them because some are default runtime config, some are loaded only when present, and some are used only for specific integrations.
/usr/local/ft-services/
├── ui-backend-conf/ # Configuration (backup required)
│ ├── hazelcast-client.xml # Main Hazelcast client configuration
│ ├── ftacs.keystore # Backend keystore used when HTTPS is enabled
│ ├── logback-spring.xml # Default external logging configuration
│ ├── interfaceItems.json # Interface seed data, loaded if present
│ ├── customization/ # Portal customization JSON files
│ │ ├── def/ # Default system-wide customizations
│ │ ├── mc/ # Management Console customizations
│ │ └── sc/ # Support Center customizations
│ ├── ssl/ # TLS certificates for Nginx/portals when configured
│ └── keys/ # Integration credentials (when used)
└── ft-data/ # Runtime data and logs
├── ui-portals/
│ ├── backend/logs/
│ └── nginx/logs/
├── ft-device-network/logs/
└── ai-agent/postgres/data/
| Path | Content | Backup Required |
|---|---|---|
ui-backend-conf/ |
Configuration files. At minimum this includes |
Yes |
ft-data/ui-portals/backend/logs/ |
Backend application logs |
No |
ft-data/ui-portals/nginx/logs/ |
Nginx access and error logs |
No |
ft-data/ft-device-network/logs/ |
FT Device Network application logs |
No |
ft-data/ai-agent/postgres/data/ |
PostgreSQL database files |
Yes |
2. Prepare Environment File
The compose.yml references the env file via env_file directive.
Make sure it points to the file matching your database:
- MySQL
-
env_file: - .env.mysql - Oracle
-
env_file: - .env.oracle
3. Configure Host Variables
Edit .env.mysql or .env.oracle and replace all ~PLACEHOLDER~ values with actual hostnames or IP addresses.
The env files contain placeholders in the format ~NAME~ that must be replaced before starting the services:
| Placeholder | Variable in .env | Description |
|---|---|---|
~HOST~ |
FT_UI_HOST |
Public hostname or IP address of this server (the machine where all services are being deployed). Used by the Portals entrypoint to patch Angular app-config.json so that browsers know where to send API requests. Must be accessible from end-user browsers — use a real IP or DNS name, not localhost. |
~HAZEL_HOST~ |
HZ_MEMBERS |
Hazelcast cluster member address(es). Format: host:port (comma-separated for multiple members). The backend connects to this cluster for distributed caching and session sharing. |
~FTACS_HOST~ |
ACS_WEB_SERVICE_HOST |
Hostname or IP of the FTACS application server. The backend uses this to make SOAP calls for device provisioning, parameter reads, and firmware management. |
~CLICKHOUSE_HOST~ |
CLICKHOUSE_HOST |
Hostname or IP of the ClickHouse server. Used for QoE analytics queries. If ClickHouse is not deployed, leave the default value — the application will skip analytics features. |
~MYSQL_HOST~ |
DB_HOST |
Hostname or IP of the MySQL server (only in .env.mysql). Both FTACS and IOTW schemas must be accessible at this address. |
~ORACLE_HOST~ |
DB_HOST |
Hostname or IP of the Oracle server (only in .env.oracle). Both FTACS and IOTW schemas must be accessible at this address. |
Example (.env.mysql):
FT_UI_HOST=192.168.1.100
HZ_MEMBERS=192.168.1.50:5701,192.168.1.51:5701,192.168.1.52:5701
ACS_WEB_SERVICE_HOST=192.168.1.60
CLICKHOUSE_HOST=192.168.1.70
DB_HOST=192.168.1.80
|
FT_UI_HOST must be the address that end-user browsers can reach. If users access the portal through a load balancer or public DNS (e.g., iot.example.com), use that value instead of the server’s internal IP. |
Docker Networking: host.docker.internal
If the database, Hazelcast, FTACS, or ClickHouse runs on the host machine (not inside Docker), use host.docker.internal as the hostname in .env variables (DB_HOST, HZ_MEMBERS, ACS_WEB_SERVICE_HOST, etc.):
DB_HOST=host.docker.internal
HZ_MEMBERS=host.docker.internal:5701
ACS_WEB_SERVICE_HOST=host.docker.internal
CLICKHOUSE_HOST=host.docker.internal
Why this is needed:
-
Inside a Docker container, localhost and 127.0.0.1 point to the container itself, not to the host machine. Any connection attempt to a host-side service via localhost will fail.
-
host.docker.internal is a special DNS name that Docker resolves to the host’s internal IP address.
-
The provided compose.yml already includes the required mapping:
extra_hosts: - "host.docker.internal:host-gateway" -
On Docker Desktop (macOS, Windows) this works out of the box. On Linux the extra_hosts directive above is required (already present in compose.yml).
Alternatively, use the host machine’s real IP address (e.g., 192.168.1.10) instead of host.docker.internal.
Environment Variables
Common Variables
| Variable | Description | Default | Required |
|---|---|---|---|
|
Base directory for persistent data and configurations |
|
Yes |
|
Timezone for all services |
|
Yes |
|
Database type: |
|
Yes |
|
Database password |
|
Yes |
Database Configuration
- MySQL
-
Variable Description Default DB_HOSTMySQL server address
-
MYSQL_PORTMySQL port
3306MYSQL_USERMySQL username
ftacs - Oracle
-
Variable Description Default DB_HOSTOracle server address
-
ORACLE_PORTOracle port
1521ORACLE_SERVICEOracle service name
XEPDB1ORACLE_USER_FTACSOracle username
ftacs
External Dependencies
| Variable | Description | Default | Required |
|---|---|---|---|
|
Hazelcast cluster members (comma-separated list of HOST:PORT) |
|
Yes |
|
FTACS application host |
|
Yes |
|
FTACS application port |
|
Yes |
|
Clickhouse server address |
|
Yes |
|
Clickhouse port |
|
Yes |
|
Clickhouse database name |
|
Yes |
|
Clickhouse username |
|
Yes |
|
Clickhouse password |
|
Yes |
UI Services Configuration
| Variable | Description | Default | Required |
|---|---|---|---|
|
Public hostname for UI access |
|
Yes |
|
UI Portals HTTP port |
|
Yes |
|
UI Portals HTTPS port |
|
Yes |
|
Backend API port |
|
Yes |
|
Grafana url for dashboards exporting (http://IP:PORT/) |
No |
|
|
Superset base URL for dashboard embedding |
No |
|
|
Superset API username for backend authentication |
|
No |
|
Superset API password for backend authentication |
|
No |
|
Backend JVM memory settings |
|
No |
|
Backend log level |
|
No |
|
Internal authentication keyword for cross-application communication (see separate-host deployment for details) |
|
Yes |
FT Device Network Configuration
| Variable | Description | Default | Required |
|---|---|---|---|
|
Service HTTP port |
|
Yes |
|
JVM memory settings |
|
No |
|
Log level |
|
No |
AI Agent Configuration
| Variable | Description | Default | Required |
|---|---|---|---|
|
PostgreSQL hostname (internal) |
|
Yes |
|
PostgreSQL port |
|
Yes |
|
PostgreSQL database name |
|
Yes |
|
PostgreSQL username |
|
Yes |
|
PostgreSQL password |
|
Yes |
|
Google API key for AI features |
- |
Yes |
|
API request timeout in seconds |
|
No |
|
Device command timeout in seconds |
|
No |
|
Maximum tokens for LLM |
|
No |
|
Maximum audio file size |
|
No |
|
Minimum db pool size |
|
Yes |
|
Maximum db pool size |
|
Yes |
Service Startup Order
Services start in the following order with health checks:
-
PostgreSQL - Database for AI Agent
-
UI Backend - REST API service (waits for DB)
-
UI Portals - Web interface (waits for backend)
-
FT Device Network - Device management service (independent start)
-
AI Agent - AI service (waits for PostgreSQL, UI Backend, and FT Device Network)
Service Access
After successful deployment, access services at:
| Service | URL | Description |
|---|---|---|
UI Portals |
Main web interface |
|
UI Backend API |
|
API documentation |
FT Device Network |
Health check endpoint |
|
AI Agent |
AI agent service |
Exposed Ports
The following ports are exposed on the host:
| Port | Service | Protocol | Configurable Via |
|---|---|---|---|
8880 |
UI Portals (Nginx) |
HTTP |
|
8843 |
UI Portals (Nginx) |
HTTPS |
|
8881 |
UI Backend (Spring Boot) |
HTTP |
|
8383 |
FT Device Network (Spring Boot) |
HTTP |
|
To verify ports are listening:
netstat -tlnp | grep -E '8880|8881|8383|8882'
# or
ss -tlnp | grep -E '8880|8881|8383|8882'
Troubleshooting
Check Service Logs
# All services
docker compose logs -f
# Specific service
docker compose logs -f ui-backend
docker compose logs -f portals
docker compose logs -f ft-device-network-service
docker compose logs -f ui-ai-agent
docker compose logs -f postgres
Common Issues
Services Not Starting
Check if all external dependencies are accessible:
# Test database connection
telnet <DB_HOST> 3306 # MySQL
telnet <DB_HOST> 1521 # Oracle
# Test Hazelcast
telnet <HAZEL_HOST> 5701
# Test FTACS
curl http://<FTACS_HOST>:8080
# Test Clickhouse
telnet <CLICKHOUSE_HOST> 9000
Maintenance
Update Services
Pull latest images and restart:
# Pull latest images
docker compose pull
# Restart with new images
docker compose --env-file .env.mysql up -d
OR
# Restart with new images
docker compose --env-file .env.oracle up -d
Force Repull Images
Force Docker to pull fresh images (ignores cache):
# Stop services
docker compose down
# Remove existing images
docker compose pull --ignore-pull-failures
# Or remove images manually
docker images | grep "hub.friendly-tech.com" | awk '{print $3}' | xargs docker rmi -f
# Start with fresh images
docker compose --env-file .env.mysql up -d
OR
# Start with fresh images
docker compose --env-file .env.oracle up -d
Stop Services
# Stop services (keeps data)
docker compose down
# Stop services and remove all data (WARNING: deletes all persistent data)
docker compose down -v
# Remove specific volumes only
docker volume rm ft-ui-services_postgres_data