Installation & Deployment

This guide covers installing and running FTACS — the TR-069/TR-369 Auto Configuration Server. Two deployment methods are supported: Docker (recommended) and manual (bare-metal / VM).

The deployment includes:

  • FTACS — core ACS application (TR-069, USP, MQTT, SOAP, REST)

  • MySQL 8.4 or Oracle 19c+ — relational database

  • ClickHouse — analytics and QoE time-series data

  • Hazelcast — distributed cache cluster

  • JDBC Bridge — ClickHouse-to-RDBMS connector

For the full environment variables reference, see Supported Environment Variables.

1. Prerequisites

1.1. System Requirements

1.1.1. Hardware

Component Minimum Specification

CPU

4 cores (8+ recommended for production)

RAM

16 GB (64 GB recommended for production)

Disk Space

20 GB (50+ GB recommended with ClickHouse)

Network

1 Gbps network interface

1.1.2. Software

Component Version

Operating System (Docker)

Linux with Docker Engine 20.10+, macOS, or Windows with WSL2

Operating System (Manual)

Linux (recommended), Windows Server

Java (Manual deployment only)

JDK 25

Docker Engine

20.10+

Docker Compose

2.0+ (optional — for multi-service stacks)

Database

MySQL 8.0+ or Oracle 19c+

ClickHouse

21.3+

Hazelcast

5.3+ (external cluster)

1.1.3. JVM Sizing by Deployment Scale

Deployment Size Devices JVM Settings

Small

< 1,000

-Xms512m -Xmx2g

Medium

1,000 — 5,000

-Xms1g -Xmx4g

Large

5,000 — 20,000

-Xms2g -Xmx8g

Very Large

20,000+

-Xms4g -Xmx16g

1.2. Required External Dependencies

The following components must be installed and configured before FTACS deployment:

  • Database — MySQL or Oracle with schema created

  • ClickHouse — for historical data and QoE storage

  • Hazelcast — external cluster (minimum 1 node; 2+ recommended for production)

1.3. Registry Access

Network access to hub.friendly-tech.com Docker registry (or offline image archives). Access to Friendly Tech SharePoint (FT_DISK) for downloading configuration files.

2. Quick Start

For experienced users who already have Docker installed and configuration files ready.

# 1. Create working directory
export DATA_FOLDER=/usr/local/ftacs
mkdir -p ${DATA_FOLDER}/{ftacs-conf,ft-data/ftacs/logs}

# 2. Copy configuration files from FT_DISK to ${DATA_FOLDER}/ftacs-conf/

# 3. Authenticate with the Docker registry
docker login hub.friendly-tech.com

# 4. Create .env and compose.yml (see "Docker Deployment" section)
#    or download from FT_DISK (see structure below)

# 5. Start all services
cd ${DATA_FOLDER}
docker compose up -d

# 6. Verify (allow 30-60 seconds for startup)
curl -s http://localhost:8080/acsstats

If the curl command returns application statistics, FTACS is running. For detailed verification steps, see Verify Installation.

3. Prepare Working Directory

Create the following directory structure on the host.

/usr/local/ftacs may require sudo on most Linux systems. Alternatively, use a path in your home directory (e.g., ~/ftacs) and adjust all paths accordingly.

export DATA_FOLDER=/usr/local/ftacs

mkdir -p ${DATA_FOLDER}/ftacs-conf                    # ACS configuration files
mkdir -p ${DATA_FOLDER}/ft-data/ftacs/logs            # ACS runtime logs
mkdir -p ${DATA_FOLDER}/ft-data/mysql/{data,logs}     # MySQL data and logs
mkdir -p ${DATA_FOLDER}/ft-data/clickhouse/{data,logs}  # ClickHouse data and logs
mkdir -p ${DATA_FOLDER}/ft-data/hazelcast/logs        # Hazelcast logs
mkdir -p ${DATA_FOLDER}/mysql-chain                   # MySQL init scripts
mkdir -p ${DATA_FOLDER}/mysql-conf                    # MySQL custom config
mkdir -p ${DATA_FOLDER}/clickhouse/{config.d,initdb.d}  # ClickHouse config and init
mkdir -p ${DATA_FOLDER}/clickhouse/jdbc-bridge/{config,drivers}  # JDBC Bridge
mkdir -p ${DATA_FOLDER}/hazelcast                     # Hazelcast config

chmod -R 755 ${DATA_FOLDER}

3.1. Directory Layout

/usr/local/ftacs/
├── compose.yml                          # Docker Compose definition (from FT_DISK)
├── .env                                 # Shared environment variables (from FT_DISK)
│
├── ftacs-conf/                          # from FT_DISK → ftacs-conf/
│   ├── acs_configuration.xml            # Core ACS runtime behavior
│   ├── bulk_data.xml                    # Bulk data upload targets per model
│   ├── ctn_info.properties              # CTN enrichment / RADIUS lookup rules
│   ├── external_trace.properties        # RPC trace routing
│   ├── fcc.properties                   # Speed and latency test tuning
│   ├── force_qoe_stop.properties        # QoE monitor stop switches
│   ├── ftacs.keystore                   # SSL keystore for HTTPS ports
│   ├── ftacs_task.properties            # RPC retry and timeout rules
│   ├── ftacsws-roles.properties         # Web service role mapping
│   ├── ftacsws-users.properties         # Web service users (basic auth)
│   ├── hardcoded_event_soap_template.xml           # SOAP event template
│   ├── hardcoded_event_soap_template (windstream).xml  # Windstream variant
│   ├── hazelcast-client.xml             # Hazelcast cluster client config
│   ├── logback-spring.xml               # Logging configuration
│   └── parameterNamesCacheRules.yaml    # Rules for parameter-name caching
│
├── ft-data/
│   ├── ftacs/logs/                      # ACS runtime logs
│   ├── mysql/
│   │   ├── data/                        # created by MySQL on first start
│   │   └── logs/
│   ├── clickhouse/
│   │   ├── data/                        # created by ClickHouse on first start
│   │   └── logs/
│   └── hazelcast/logs/
│
├── mysql-chain/                         # MySQL init scripts (run on first start)
│   └── *.sql
├── mysql-conf/                          # MySQL custom configuration
│   └── custom.cnf
│
├── clickhouse/
│   ├── config.d/                        # ClickHouse server config files
│   │   ├── config_new.xml
│   │   ├── users_new.xml
│   │   └── jdbc_bridge_<db>.xml         # <-- replace <db> with mysql or oracle
│   └── initdb.d/                        # Init SQL (run on first start)
│
├── clickhouse/jdbc-bridge/
│   ├── config/
│   │   └── datasource_mysql.json        # DB datasource for JDBC Bridge
│   └── drivers/
│       └── mysql-connector-j-*.jar      # JDBC driver
│
└── hazelcast/
    ├── hazelcast.xml                    # Hazelcast server config
    └── log4j2.properties                # Hazelcast logging

3.1.1. Manual (non-Docker) Distribution Layout

When deploying without Docker, the extracted distribution package has this structure:

dist/
├── app/                 # Compiled application (WAR exploded) -- do NOT modify
│   ├── META-INF/        # JAR/WAR manifest and persistence descriptors
│   ├── org/             # Java bytecode packages (ACS core classes)
│   └── WEB-INF/         # Spring Boot web configuration and libraries
│
├── bin/                 # Executable scripts and environment definitions
│   ├── app.env          # Main environment file (DB, ports, JVM, etc.)
│   ├── env_to_cmd.cmd   # Helper: .env → Windows CMD variables
│   ├── start.cmd        # Windows startup script
│   ├── start.sh         # Linux startup script
│   ├── stop.cmd         # Windows shutdown script
│   └── stop.sh          # Linux shutdown script
│
├── conf/                # Configuration files (editable by operators)
│   ├── acs_configuration.xml
│   ├── hazelcast-client.xml
│   ├── logback-spring.xml
│   ├── ftacs.keystore
│   └── ...              # (same files as ftacs-conf above)
│
├── ext/                 # External extensions / JARs loaded dynamically
├── liquibase/           # Database migration scripts (managed by Liquibase)
├── logs/                # Runtime logs (created at startup)
└── patches/             # Hot-fix patches
  • app/ is static — do not modify; changes belong in conf/.

  • bin/ scripts assume APP_HOME defined in app.env; all paths resolve relative to it.

  • conf/ is safe for edits and should be version-controlled in ops repositories.

  • logs/ may be mounted to external storage for persistent log retention.

  • liquibase/ drives schema migrations; changes here must match release cycles.

  • ext/ enables plugin-like JARs or vendor integrations without rebuilding.

4. Configuration

4.1. Docker Deployment (Environment Files)

The stack uses a two-layer environment file architecture. MySQL is the default — if you are using MySQL, no changes are needed beyond replacing passwords.

Download all three files from FT_DISK and place them in the DATA_FOLDER root:

File Purpose

.env

Main environment file — FTACS ports, HikariCP pools, deployment mode, protocol settings (TR-069/MQTT/USP), TLS certificates, async executor tuning, JVM options. Shared across all deployment types.

.env.mysql

Database-specific overlay for MySQL — DATA_FOLDER, timezone, DB host/vendor/credentials, Hazelcast, ClickHouse, TR-069 URL mappings, host port assignments.

.env.oracle

Database-specific overlay for Oracle — same structure as .env.mysql but with Oracle connection settings (DB_VENDOR=oracle, ORACLE_PORT, ORACLE_SERVICE, etc.).

# Copy env files from FT_DISK:
cp .env ${DATA_FOLDER}/
cp .env.mysql ${DATA_FOLDER}/       # or .env.oracle for Oracle deployments

The .env file contains FTACS application settings that are independent of the database vendor. The .env.mysql / .env.oracle files contain database connection details, infrastructure hosts, and port mappings. Both files are loaded by compose.yml via env_file directives.

4.1.1. Switching to Oracle

To switch from MySQL to Oracle, download .env.oracle from FT_DISK instead of .env.mysql and use compose-oracle.yml instead of compose-mysql.yml.

4.1.2. Main environment file (.env)

The .env file controls FTACS application behavior. Download it from FT_DISK or customize using the reference below.

Click to expand .env reference
# =============================================================================
# FTACS - Core ACS Engine
# =============================================================================

# Host port exposed on the server for HTTP traffic.
# Maps to container internal port 8080 in compose.yml.
FTACS_HTTP_PORT=8080

# Host port exposed on the server for HTTPS traffic.
# Maps to container internal port 8443 in compose.yml.
FTACS_HTTPS_PORT=8443

# =============================================================================
# HikariCP Connection Pools
# =============================================================================

# Shared pool defaults (apply to all datasources unless overridden below)
DB_MAX_POOL_SIZE=10
DB_MIN_IDLE=5
DB_CONNECTION_TIMEOUT_MS=30000

# Main FTACS datasource pool. Handles CPE management, parameters,
# provisioning operations. Needs larger pool due to high concurrency.
FTACS_MAX_POOL=30
FTACS_MIN_POOL=5

# Quartz job scheduler datasource. Used for scheduled tasks persistence
# (UpdateGroup, QoE, Events). Lower load than main datasource.
QUARTZ_MAX_POOL=10
QUARTZ_MIN_POOL=2

# ClickHouse analytics datasource. Used for QoE data and statistics.
# Only active when CLICKHOUSE_HOST is configured (shared .env).
CLICKHOUSE_MAX_POOL=10
CLICKHOUSE_MIN_POOL=2

# =============================================================================
# ACS Deployment Mode
# Controls which functionality is active. Used for distributed deployments
# where provisioning and management run on separate nodes.
# =============================================================================

# ALL  = full functionality (provisioning + management) — single-node default
# PROV = provisioning only (device bootstrap, session handling)
# MNGMNT = management only (device monitoring, configuration)
# In MNGMNT mode, FTACS connects to a separate Hazelcast "provision" cluster.
# FTACS_MODE=ALL

# =============================================================================
# Server IP Address
# Advertised to CPE devices for callbacks and connection requests.
# Auto-detected from hostname if not set. Set explicitly in Docker/NAT
# environments where auto-detection returns an unreachable address.
# =============================================================================

# IPv4 address advertised to CPE devices. Format: dotted decimal (e.g., 192.168.1.100)
# FTACS_IP_ADDRESS=

# IPv6 address for dual-stack deployments. Brackets added automatically if missing.
# Format: colon-hexadecimal (e.g., 2001:db8::1)
# FTACS_IPV6_ADDRESS=

# =============================================================================
# Event Subscription Parameters
# Control when parameter change notifications are sent to subscriber URLs.
# =============================================================================

# 0 = notify on every parameter update (EACH_VALUE trigger)
# 1 = notify only when parameter value actually changes (VALUE_CHANGE trigger)
# Reduces notification volume for high-frequency polling scenarios.
# FTACS_SUBSCRIPTION_PARAMETER_ONLY_VALUE_CHANGE=0

# 0 = include all parameter values (including null/empty)
# 1 = skip notifications for null or empty parameter values
# Filters out spurious empty values during device initialization.
# FTACS_SUBSCRIPTION_PARAMETER_NOT_NULL_ONLY=0

# =============================================================================
# TR-069 Endpoint URL Mappings
# Each defines the servlet URL path for a different authentication mode.
# Multiple paths can be comma-separated.
# =============================================================================

# No authentication — CPE connects without credentials
WEB_TR069_NO_AUTH=/ftacs/ACS

# HTTP Basic Authentication (RFC 7617) — CPE sends base64(user:password)
WEB_TR069_BASIC=/ftacs-basic/ACS

# HTTP Digest Authentication (RFC 2617) — challenge-response, no plaintext password
WEB_TR069_DIGEST=/ftacs-digest/ACS

# =============================================================================
# MQTT Protocol (optional)
# Activates the embedded MQTT broker for TR-369/USP MQTT-MTP transport.
# =============================================================================

# Enable/disable MQTT protocol support (true/false)
MQTT_ENABLE=false

# Additional MQTT transport connector URI (ActiveMQ format).
# Useful for binding MQTT on a custom IP/port beyond the standard ones.
# Format: mqtt+nio://<host>:<port> or mqtt+nio+ssl://<host>:<port>
# Example: mqtt+nio://0.0.0.0:9001
# FT_MQTT_ADDITIONAL_CONNECTOR_URI=

# Active MQTT API versions. Comma-separated list.
# Incoming requests are validated against this list.
# MQTT_ACTIVE_API=api-v1,api-v2

# =============================================================================
# USP Protocol (optional)
# =============================================================================

# Path to USP data model XML specification (BBF TR-181-2 standard).
# Loaded from filesystem first; falls back to classpath resource.
# USP_SERVER_DM_PATH=tr-181-2-16-0-usp-full.xml

# =============================================================================
# X509 Certificates - USP TLS/DTLS (optional)
# Used for secure USP MTP connections (WebSocket, STOMP, CoAP over DTLS).
# Format: JKS or PKCS12 keystore files.
# =============================================================================
# FT_USP_X509_KEYSTORE_PATH=        # Server keystore with private key and certificate
# FT_USP_X509_KEYSTORE_PASSWORD=    # Keystore file password
# FT_USP_X509_KEYSTORE_PK_PASSWORD= # Private key password (if differs from keystore)
# FT_USP_X509_TRUSTSTORE_PATH=      # Truststore with trusted CA certificates
# FT_USP_X509_TRUSTSTORE_PASSWORD=  # Truststore file password

# =============================================================================
# X509 Certificates - MQTT TLS (optional)
# Used for MQTTS (MQTT over TLS) on port 8883.
# Enables mutual TLS when truststore is configured.
# =============================================================================
# FT_MQTT_X509_KEYSTORE_PATH=       # MQTT server keystore path
# FT_MQTT_X509_KEYSTORE_PASSWORD=   # MQTT keystore password
# FT_MQTT_X509_PK_PASSWORD=         # MQTT private key password
# FT_MQTT_X509_TRUSTSTORE_PATH=     # MQTT truststore path
# FT_MQTT_X509_TRUSTSTORE_PASSWORD= # MQTT truststore password

# =============================================================================
# General Async Executor (used by @Async methods without explicit executor)
# =============================================================================

# Minimum threads always running. Idle core threads are reclaimed
# after ASYNC_KEEPALIVE seconds (allowCoreThreadTimeout=true).
ASYNC_CORE=10

# Maximum threads under load. When queue=0, threads spawn immediately
# up to this limit before tasks go to an external 10,000-task overflow queue.
ASYNC_MAX=200

# Internal queue capacity before spawning new threads.
# 0 = no internal queue (SynchronousQueue); tasks spawn threads immediately.
# An external OverflowingExecutor with 10,000-task queue wraps the pool
# as a safety net, blocking on overflow to provide backpressure.
ASYNC_QUEUE=0

# Seconds an idle thread stays alive before termination.
ASYNC_KEEPALIVE=60

# Thread pool size for @Scheduled methods (virtual threads enabled).
# Handles periodic tasks: statistics flush (every 60s), counter reset (daily).
# Quartz jobs use a separate JDBC-based scheduler, not this pool.
SCHED_POOL=300

# =============================================================================
# HikariCP Tuning (optional)
# Applies to ALL three datasources (ftacs, quartz, clickhouse).
# =============================================================================

# Max time (ms) a connection can sit idle before removal. Default: 60000 (1 min)
# HIKARI_IDLE_TIMEOUT_MS=60000

# Max time (ms) to wait for a connection from the pool. Default: 45000 (45 sec)
# HIKARI_CONN_TIMEOUT_MS=45000

# Max age (ms) of a connection before forced rotation. Default: 180000 (3 min)
# Must be greater than HIKARI_IDLE_TIMEOUT_MS.
# HIKARI_MAX_LIFETIME_MS=180000

# Max time (ms) for connection validation query (SELECT 1). Default: 3000 (3 sec)
# HIKARI_VALIDATION_TIMEOUT_MS=3000

# Register HikariCP pool metrics as JMX MBeans (true/false).
# Enables monitoring via JConsole/VisualVM. Minor performance overhead.
# HIKARI_REGISTER_MBEANS=false

# =============================================================================
# JVM Options
# Passed directly to the java command. Controls heap, GC, timezone.
# =============================================================================
JAVA_OPTS=-Xms512m -Xmx2g -Duser.timezone=${TZ}

4.1.3. Database-specific overlay (.env.mysql / .env.oracle)

These files contain infrastructure settings: database host, vendor, credentials, Hazelcast, ClickHouse, and host port mappings.

Click to expand .env.mysql
# Common vars
DATA_FOLDER=/usr/local/ftacs                          # <-- replace with your path
TZ=Europe/Kiev
FT_ACS_JAVA_RAM=-Xms1g -Xmx4g

# JVM tuning
JAVA_OPTS="-Xms1g -Xmx4g -Duser.timezone=Europe/Kiev"

# Hazelcast settings
HZ_MEMBERS=hazelcast:5701

# DB settings
DB_HOST=mysql
DB_PASSWORD=ftacs                                     # <-- replace in production

# MySQL settings
DB_VENDOR=mysql
MYSQL_EXTERNAL_PORT=3306
MYSQL_PORT=3306
MYSQL_USER=ftacs

# ClickHouse
CLICKHOUSE_HOST=clickhouse
CLICKHOUSE_PORT=8123
CLICKHOUSE_SCHEMA=ftacs_qoe_ui_data
CLICKHOUSE_USERNAME=ftacs
CLICKHOUSE_PASSWORD=ftacs                             # <-- replace in production

# TR-069 device URL mappings
WEB_TR069_NO_AUTH=/ftacs/ACS
WEB_TR069_BASIC=/ftacs-basic/ACS
WEB_TR069_DIGEST=/ftacs-digest/ACS

# Ports
ACS_MQTT=1883
ACS_USP_WS=8025
ACS_HTTP_ADDITIONAL=8181
ACS_USP_MQTT=18881
ACS_USP_BULK=18891
ACS_USP_STOMP=61617
ACS_USP_CoAP=5783
ACS_USP_WSS=4430
ACS_HTTPS=8443
ACS_MQTT_TLS=8883
ACS_USP_MQTT_TLS=18882
ACS_USP_DTLS=5784
Click to expand .env.oracle
# Common vars
DATA_FOLDER=/usr/local/ftacs                          # <-- replace with your path
TZ=Europe/Kiev
FT_ACS_JAVA_RAM=-Xms1g -Xmx4g

# JVM tuning
JAVA_OPTS="-Xms1g -Xmx4g -Duser.timezone=Europe/Kiev"

# Hazelcast settings
HZ_MEMBERS=hazelcast:5701

# DB settings
DB_HOST=oracle
DB_PASSWORD=ftacs                                     # <-- replace in production

# Oracle settings
DB_VENDOR=oracle
ORACLE_PORT=1521
ORACLE_EXTERNAL_PORT=1521
ORACLE_SERVICE=XEPDB1
ORACLE_USER_FTACS=ftacs
ORACLE_USER_QUARTZ=ftacs_quartz

# ClickHouse
CLICKHOUSE_HOST=clickhouse
CLICKHOUSE_PORT=8123
CLICKHOUSE_SCHEMA=ftacs_qoe_ui_data
CLICKHOUSE_USERNAME=ftacs
CLICKHOUSE_PASSWORD=ftacs                             # <-- replace in production

# TR-069 device URL mappings
WEB_TR069_NO_AUTH=/ftacs/ACS
WEB_TR069_BASIC=/ftacs-basic/ACS
WEB_TR069_DIGEST=/ftacs-digest/ACS

# Ports
ACS_MQTT=1883
ACS_USP_WS=8025
ACS_HTTP_ADDITIONAL=8181
ACS_USP_MQTT=18881
ACS_USP_BULK=18891
ACS_USP_STOMP=61617
ACS_USP_CoAP=5783
ACS_USP_WSS=4430
ACS_HTTPS=8443
ACS_MQTT_TLS=8883
ACS_USP_MQTT_TLS=18882
ACS_USP_DTLS=5784

4.1.4. Replace placeholder values

Replace all values marked with # ←- replace in both files.

Replace all # ←- replace in production values before deploying to any non-development environment. Default passwords (ftacs, friendly) are for local development only.

4.2. Manual Deployment (app.env)

Edit bin/app.env in the extracted distribution package.

# === Base directories (all other paths derive from APP_HOME) ===
APP_HOME=/usr/local/ftacs/                             # <-- replace with your dist path
CONF_DIR=${APP_HOME}/conf
LOG_DIR=${APP_HOME}/logs
EXT_DIR=${APP_HOME}/ext
PATCHES_DIR=${APP_HOME}/patches
DB_LIQUIBASE_DIR=${APP_HOME}/liquibase

# === Database connection ===
DB_HOST=localhost                                     # <-- replace
DB_PASSWORD=ftacs                                     # <-- replace in production

# --- MySQL (default) ---
DB_VENDOR=mysql
MYSQL_PORT=3306
MYSQL_USER=ftacs

# --- Oracle (uncomment to switch) ---
#DB_VENDOR=oracle
#ORACLE_PORT=1521
#ORACLE_SERVICE=XEPDB1
#ORACLE_USER_FTACS=ftacs
#ORACLE_USER_QUARTZ=ftacs_quartz

# === ClickHouse configuration ===
CLICKHOUSE_HOST=localhost                             # <-- replace
CLICKHOUSE_PORT=8123
CLICKHOUSE_SCHEMA=ftacs_qoe_ui_data
CLICKHOUSE_USER=ftacs
CLICKHOUSE_PASWORD=ftacs                              # <-- replace in production

# === Hazelcast ===
HZ_MEMBERS=127.0.0.1:5701                            # <-- replace with cluster addresses
HZ_CLIENT_CONFIG=${CONF_DIR}/hazelcast-client.xml

# === TR-069 device URL mappings ===
WEB_TR069_NO_AUTH=/ftacs/ACS
WEB_TR069_BASIC=/ftacs-basic/ACS
WEB_TR069_DIGEST=/ftacs-digest/ACS

# === Web/SSL ===
HTTP_PORTS=8080,8181
HTTPS_PORTS=8443
SSL_KEYSTORE=${CONF_DIR}/ftacs.keystore
SSL_KEYSTORE_PASSWORD=friendly                        # <-- replace in production

# === JVM options ===
JAVA_OPTS='-Xms1g -Xmx4g'

# === Additional Configuration ===
SPRING_CONFIG_EXTRA=file:${CONF_DIR}/
LOGBACK_CONFIG=${CONF_DIR}/logback-spring.xml
CXF_PATH=/ACSServer-ACS
QUARTZ_PASSWORD=${DB_PASSWORD}

Set APP_HOME to the absolute path of your dist directory.

  • Linux example: APP_HOME=/usr/local/ftacs/

  • Windows example: APP_HOME=D:/ftacs/dist/

On Windows, use forward slashes (/) and include the trailing slash. Avoid double slashes in the path.

4.2.1. SSL Certificate Configuration (Optional)

The distribution includes a default self-signed certificate (conf/ftacs.keystore). This is suitable for testing only.

To use a custom certificate:

  1. Generate or obtain an SSL certificate.

  2. Create a Java keystore:

    keytool -genkey -alias ftacs -keyalg RSA -keystore ftacs.keystore -keysize 2048
  3. Place the keystore in conf/.

  4. Update app.env:

    SSL_KEYSTORE=${CONF_DIR}/ftacs.keystore
    SSL_KEYSTORE_PASSWORD=<your-keystore-password>        # <-- replace

5. Docker Deployment

5.1. Authenticate with Docker Registry

docker login hub.friendly-tech.com

Enter credentials when prompted.

Alternatively, use non-interactive login:

echo "<your-password>" | docker login hub.friendly-tech.com -u <your-username> --password-stdin

Verify authentication:

docker info | grep -A 5 Registry

5.2. Docker Compose File

Download compose-mysql.yml (or compose-oracle.yml) from FT_DISK and rename to compose.yml.

Click to expand compose.yml
version: "3.8"
name: ft-services-mysql

services:
  mysql:
    image: mysql:8.4.6
    platform: linux/amd64
    environment:
      MYSQL_ROOT_PASSWORD: ftacs
      MYSQL_DATABASE: ftacs
      MYSQL_USER: ftacs
      MYSQL_PASSWORD: ftacs
    command: [ "mysqld", "--log_error_verbosity=3", "--general-log=1", "--general-log-file=/dev/stdout", "--slow-query-log=0" ]
    ports:
      - "${MYSQL_EXTERNAL_PORT:-3306}:3306"
    volumes:
      - ${DATA_FOLDER:-.}/ft-data/mysql/data:/var/lib/mysql
      - ${DATA_FOLDER:-.}/ft-data/mysql/logs:/var/log
      - ${DATA_FOLDER:-.}/mysql-chain:/docker-entrypoint-initdb.d:ro
      - ${DATA_FOLDER:-.}/mysql-conf:/etc/mysql/conf.d
    healthcheck:
      test: [ "CMD-SHELL", "mysql -h 127.0.0.1 -uroot -p$$MYSQL_ROOT_PASSWORD -N -e \"SELECT 1 FROM dual\" || exit 1" ]
      interval: 5s
      timeout: 3s
      retries: 30

  clickhouse:
    image: clickhouse/clickhouse-server:24.8
    depends_on:
      - jdbc-bridge
    env_file: [.env]
    environment:
      - CLICKHOUSE_USER=${CLICKHOUSE_USERNAME:-ftacs}
    ports:
      - "${CH_HTTP_PORT:-8123}:8123"   # HTTP
      - "${CH_TCP_PORT:-9000}:9000"    # Native
    volumes:
      - ${DATA_FOLDER:-.}/ft-data/clickhouse/data:/var/lib/clickhouse
      - ${DATA_FOLDER:-.}/ft-data/clickhouse/logs:/var/log/clickhouse-server
      - ${DATA_FOLDER:-.}/clickhouse/config.d/jdbc_bridge_${DB}.xml:/etc/clickhouse-server/config.d/jdbc_bridge.xml:ro
      - ${DATA_FOLDER:-.}/clickhouse/initdb.d:/docker-entrypoint-initdb.d:ro
      - ${DATA_FOLDER:-.}/clickhouse/config.d/config_new.xml:/etc/clickhouse-server/config.xml:ro
      - ${DATA_FOLDER:-.}/clickhouse/config.d/users_new.xml:/etc/clickhouse-server/users.xml:ro
    healthcheck:
      test: [ "CMD", "bash", "-lc", "clickhouse-client --user=$$CLICKHOUSE_USER --password=$$CLICKHOUSE_PASSWORD --query='SELECT 1'" ]
      interval: 5s
      timeout: 3s
      retries: 60

  jdbc-bridge:
    image: clickhouse/jdbc-bridge:2.1.0
    expose: [ "9019" ]
    depends_on:
      mysql:
        condition: service_healthy
      hazelcast:
        condition: service_healthy
    volumes:
      - ${DATA_FOLDER:-.}/clickhouse/jdbc-bridge/config/datasource_mysql.json:/app/config/datasources/datasource.json
      - ${DATA_FOLDER:-.}/clickhouse/jdbc-bridge/drivers:/app/drivers
      - ${DATA_FOLDER:-.}/clickhouse-jdbc-bridge/logs:/var/log/clickhouse-jdbc-bridge/

  hazelcast:
    image: hub.friendly-tech.com/components/hazelcast:ft.5.5.0
    volumes:
      - ${DATA_FOLDER:-.}/hazelcast/hazelcast.xml:/opt/hazelcast/hazelcast.xml:ro
      - ${DATA_FOLDER:-.}/hazelcast/log4j2.properties:/opt/hazelcast/config/log4j2.properties:ro
      - ${DATA_FOLDER:-.}/ft-data/hazelcast/logs:/opt/hazelcast/logs
    command: [ "start","-c","/opt/hazelcast/hazelcast.xml" ]
    environment:
      JAVA_OPTS: >-
        -Duser.timezone=${TZ}
        -Dhazelcast.local.publicAddress=${HZ_PUBLIC_ADDRESS:-hazelcast}
        -Dcom.sun.management.jmxremote
        -Djava.rmi.server.hostname=hazelcast
        -Dcom.sun.management.jmxremote.rmi.port=${HZ_JMX_INTERNAL_PORT:-9110}
        -Dcom.sun.management.jmxremote.port=${HZ_JMX_INTERNAL_PORT:-9110}
        -Dcom.sun.management.jmxremote.authenticate=false
        -Dcom.sun.management.jmxremote.ssl=false
        -Dcom.sun.management.jmxremote.local.only=false
        -Dhazelcast.jmx=true
    healthcheck:
      test: [ "CMD", "curl", "-f", "http://127.0.0.1:8090/hazelcast/health" ]
      interval: 10s
      timeout: 5s
      retries: 50
    ports:
      - "${HZ_PORT:-5701}:5701"
      - "${HZ_SERVER_PORT:-5711}:5711"
      - "${HZ_JMX_PORT:-9110}:${HZ_JMX_INTERNAL_PORT:-9110}"

  ftacs:
    depends_on:
      mysql:
        condition: service_healthy
      hazelcast:
        condition: service_healthy
      clickhouse:
        condition: service_healthy
    image: hub.friendly-tech.com/ftacs/ftacs:latest
    ports:
      - "${ACS_WEB_SERVICE_PORT:-8080}:8080"
      - "${ACS_MQTT:-1883}:1883"
      - "${ACS_USP_WS:-8025}:8025"
      - "${ACS_HTTP_ADDITIONAL:-8181}:8181"
      - "${ACS_USP_MQTT:-18881}:18881"
      - "${ACS_USP_BULK:-18891}:18891"
      - "${ACS_USP_STOMP:-61617}:61617"
      - "${ACS_USP_CoAP:-5783}:5783"
      - "${ACS_UST_WSS:-4430}:4430"
      - "${ACS_HTTPS:-8443}:8443"
      - "${ACS_MQTT_TLS:-8883}:8883"
      - "${ACS_USP_MQTT_TLS:-18882}:18882"
      - "${ACS_USP_DTLS:-5784}:5784"
    env_file: [ .env ]
    environment:
      USE_NOHUP: 0
      APP_HOME: "/opt/FTACS"
      JAVA_OPTS: "${FT_ACS_JAVA_RAM:--Xms1g -Xmx4g} -Duser.timezone=${TZ}"
    healthcheck:
      test: [ "CMD", "curl", "-f", "http://127.0.0.1:8080/acsstats" ]
      interval: 10s
      timeout: 5s
      retries: 100
    volumes:
      - ${DATA_FOLDER:-.}/ftacs-conf:/opt/FTACS/conf
      - ${DATA_FOLDER:-.}/ft-data/ftacs/logs:/opt/FTACS/logs
    stop_grace_period: 45s

5.3. Deploy the Stack

cd ${DATA_FOLDER}
docker compose up -d

Monitor startup progress:

docker compose logs -f

Stop all services:

docker compose down

Stop and remove all data volumes (destroys data):

docker compose down -v

docker compose down -v removes all named volumes, including database data. Use this only when you want to start from scratch.

5.4. Docker Run (Standalone)

To run FTACS as a single container (without Compose), use the following command:

export DATA_FOLDER=/usr/local/ftacs
cd ${DATA_FOLDER}

docker run -d \
  --name ftacs \
  --env-file .env --env-file .env.mysql \
  -p 8080:8080 \
  -p 8443:8443 \
  -v ${DATA_FOLDER:-.}/ftacs-conf:/opt/FTACS/conf \
  -v ${DATA_FOLDER:-.}/ft-data/ftacs/logs:/opt/FTACS/logs \
  hub.friendly-tech.com/ftacs/ftacs:latest

Ensure .env and .env.mysql (or .env.oracle) exist in ${DATA_FOLDER} before starting the container. When using standalone docker run, you are responsible for running MySQL, ClickHouse, and Hazelcast separately.

6. Non-Docker Deployment

6.1. Step 1: Install Java Development Kit

6.1.1. Linux

# Download JDK 25
wget https://download.oracle.com/java/25/latest/jdk-25_linux-x64_bin.tar.gz

# Extract
tar -xzf jdk-25_linux-x64_bin.tar.gz

# Move to installation directory
sudo mv jdk-25 /opt/jdk-25

# Set JAVA_HOME (add to ~/.bashrc or /etc/profile)
export JAVA_HOME=/opt/jdk-25
export PATH=$JAVA_HOME/bin:$PATH

# Verify installation
java -version

6.1.2. Windows

  1. Download JDK 25 installer from Oracle website.

  2. Run installer (e.g., jdk-25_windows-x64_bin.exe).

  3. Set JAVA_HOME environment variable:

    • Right-click "This PC" → Properties → Advanced system settings

    • Environment Variables → New System Variable

    • Variable name: JAVA_HOME

    • Variable value: C:\Program Files\Java\jdk-25

  4. Add %JAVA_HOME%\bin to PATH variable.

  5. Verify: Open Command Prompt and run java -version.

6.2. Step 2: Extract Distribution Package

# Linux/Unix
tar -xzf ftacs-dist-<version>.tar.gz
cd dist/

# Windows -- extract ftacs-dist-<version>.zip using Windows Explorer or:
unzip ftacs-dist-<version>.zip
cd dist\

6.3. Step 3: Configure app.env

Edit bin/app.env with your environment-specific settings. See Manual Deployment (app.env) for the full reference.

6.4. Step 4: Start Application

6.4.1. Linux

cd bin/
chmod +x start.sh
./start.sh

6.4.2. Windows

cd bin
start.cmd

6.5. Step 5: Verify Installation

Monitor the log file for successful startup:

# Linux
tail -f ../logs/server.log

# Windows
type ..\logs\server.log

Look for these indicators:

INFO: Tomcat started on ports 8080 (http), 8181 (http), 8443 (https)
INFO: Starting Quartz Scheduler now
INFO: Scheduler quartzScheduler started
INFO: TR069 Device URLs:
        NOAUTH: /ftacs/ACS
        BASIC: /ftacs-basic/ACS
        DIGEST: /ftacs-digest/ACS
INFO: WebServices:
        /ACSServer-ACS/ACSWebService
        /ACSServer-ACS/ACSWebServiceAdditional
        /ACSServer-ACS/ACSWebServiceConfiguration
        /ACSServer-ACS/ACSWebServiceEventSubscription
INFO: Swagger UI: /rest/swagger-ui
INFO: Friendly IOT Management Server V6.x.x started
INFO: Started FtAcsApp in XX.XXX seconds

You may see messages about "ClusterManager: detected failed or restarted instances" during startup — this is normal for Quartz scheduler recovery and can be ignored.

Liquibase migration messages appear in the liquibase.log file, not in server.log.

7. Verify Installation

7.1. Check Startup Logs

Wait 30-60 seconds after starting the container, then check the logs:

# Docker Compose
docker compose logs ftacs | tail -20

# Docker standalone
docker logs ftacs | tail -20

A successful startup produces the following output:

INFO: Tomcat started on ports 8080 (http), 8181 (http), 8443 (https)
INFO: Starting Quartz Scheduler now
INFO: Scheduler quartzScheduler started
INFO: TR069 Device URLs:
        NOAUTH: /ftacs/ACS
        BASIC: /ftacs-basic/ACS
        DIGEST: /ftacs-digest/ACS
INFO: WebServices:
        /ACSServer-ACS/ACSWebService
        /ACSServer-ACS/ACSWebServiceAdditional
        /ACSServer-ACS/ACSWebServiceConfiguration
        /ACSServer-ACS/ACSWebServiceEventSubscription
INFO: Swagger UI: /rest/swagger-ui
INFO: Friendly IOT Management Server V6.x.x started
INFO: Started FtAcsApp in XX.XXX seconds

The startup banner is generated by FTIOTApplicationListener — the version and build number are read from version.xml inside the container.

7.2. Check Endpoints

# Application statistics
curl http://localhost:8080/acsstats

# TR-069 ACS endpoint
curl -I http://localhost:8080/ftacs/ACS

# SOAP WSDL
curl http://localhost:8080/ACSServer-ACS/ACSWebService?wsdl

# Swagger UI
curl -I http://localhost:8080/rest/swagger-ui

Expected: HTTP 200 responses for all endpoints.

7.3. Access Web Interface

7.4. Check Logs

# Docker Compose
docker compose logs -f ftacs

# Docker standalone
docker logs -f ftacs

# Manual deployment
tail -f ${APP_HOME}/logs/server.log

7.5. Verify Database Connectivity

Check that Liquibase created the schema tables:

MySQL
USE ftacs;
SHOW TABLES;
Oracle
SELECT table_name FROM user_tables ORDER BY table_name;

You should see multiple tables created by Liquibase migrations.

8. Port Reference

8.1. HTTP/HTTPS Services

Service Port Protocol

Main web interface (SOAP, REST, TR-069, statistics, bulk data)

8080

HTTP

Secondary HTTP port (same services as 8080)

8181

HTTP

Secure web interface (SOAP, REST, TR-069, statistics, bulk data)

8443

HTTPS

8.2. MQTT Protocol

Service Port Security

MQTT broker

1883

Plain

MQTT broker

8883

TLS

8.3. USP Protocol (TR-369)

Service Port Security

USP WebSocket

8025

Plain

USP WebSocket Secure

4430

WSS

USP MQTT

18881

Plain

USP MQTT

18882

TLS

USP Bulk Data Receiver

18891

Plain

USP STOMP

61617

Plain

USP CoAP (UDP)

5783

Plain

USP CoAP (UDP)

5784

DTLS

8.4. Infrastructure Services

Service Port Protocol

MySQL database

3306

TCP

ClickHouse HTTP interface

8123

HTTP

ClickHouse native protocol

9000

TCP

Hazelcast cluster

5701

TCP

Hazelcast server

5711

TCP

Hazelcast JMX

9110

TCP

JDBC Bridge (internal)

9019

TCP

8.5. HTTP Endpoints

Endpoint Description

/acsstats

TR-069 protocol statistics

/ftacs/ACS

TR-069 endpoint (no authentication)

/ftacs-basic/ACS

TR-069 endpoint (HTTP Basic authentication)

/ftacs-digest/ACS

TR-069 endpoint (HTTP Digest authentication)

/ACSServer-ACS/ACSWebService?wsdl

Primary SOAP web service WSDL

/ACSServer-ACS/ACSWebServiceAdditional?wsdl

Additional SOAP web service WSDL

/rest/swagger-ui

Swagger UI documentation interface

TR-069 endpoints can be changed, added, or removed via environment variables (WEB_TR069_NO_AUTH, WEB_TR069_BASIC, WEB_TR069_DIGEST).

8.6. Endpoint URL Examples

# No Authentication
http://<your-server>:8080/ftacs/ACS

# Basic Authentication
http://<your-server>:8080/ftacs-basic/ACS

# Digest Authentication (HTTPS)
https://<your-server>:8443/ftacs-digest/ACS

# SOAP Web Service
http://<your-server>:8080/ACSServer-ACS/ACSWebService?wsdl

# Swagger UI
http://<your-server>:8080/rest/swagger-ui

8.7. Security Considerations

Plain-text ports (no encryption): 1883, 8025, 8080, 8181, 18881, 18891, 61617, 5783

Encrypted ports: 4430 (WSS), 8443 (HTTPS), 8883 (MQTT TLS), 18882 (USP MQTT TLS), 5784 (CoAP DTLS)

In production, disable or firewall plain-text ports and route all traffic through encrypted endpoints.

9. Container Management

9.1. Check Container Status

# List running containers
docker ps

# View container logs
docker logs ftacs

# Follow logs in real-time
docker logs -f ftacs

# View last 100 lines
docker logs --tail 100 ftacs

9.2. Stop, Start, and Restart

# Stop container
docker stop ftacs

# Start container
docker start ftacs

# Restart container
docker restart ftacs

9.3. Remove Container

# Stop and remove container
docker stop ftacs
docker rm ftacs

# Force remove running container
docker rm -f ftacs

9.4. Shell Access

# Execute bash in running container
docker exec -it ftacs bash

# Run single command
docker exec ftacs ls -la /opt/FTACS/logs

9.5. Update FTACS Image

See Docker Image Management Guide for the full image lifecycle.

# 1. Backup before update
tar -czf ftacs-backup-$(date +%Y%m%d).tar.gz ${DATA_FOLDER}/ft-data
docker exec mysql mysqldump -uftacs -pftacs ftacs > ftacs-db-backup.sql

# 2. Pull new image
docker pull hub.friendly-tech.com/ftacs/ftacs:<new-version>   # <-- replace

# 3. Stop and remove current container
docker stop ftacs
docker rm ftacs

# 4. Run with new image
docker run -d \
  --name ftacs \
  --env-file .env --env-file .env.mysql \
  -p 8080:8080 \
  -p 8443:8443 \
  -v ${DATA_FOLDER:-.}/ftacs-conf:/opt/FTACS/conf \
  -v ${DATA_FOLDER:-.}/ft-data/ftacs/logs:/opt/FTACS/logs \
  hub.friendly-tech.com/ftacs/ftacs:<new-version>              # <-- replace

For Docker Compose, update the image tag in compose.yml and run:

docker compose pull
docker compose up -d

10. Production Checklist

  • Change all default passwords in .env / app.env (DB_PASSWORD, SSL_KEYSTORE_PASSWORD, CLICKHOUSE_PASSWORD)

  • Use a valid SSL certificate — replace the self-signed ftacs.keystore with a CA-issued certificate

  • Configure firewall rules — allow only required ports; restrict database access to ACS hosts only

  • Review TR-069 authentication — disable the no-auth endpoint (/ftacs/ACS) if not required

  • Secure configuration files — restrict permissions: chmod 600 bin/app.env

  • Enable auto-restart — use --restart unless-stopped in docker run or restart: unless-stopped in compose.yml

  • Configure health checks — compose.yml includes health checks; for standalone docker run, add --health-cmd

  • Set up monitoring — deploy Grafana with ClickHouse data sources and import ACS dashboard templates

  • Configure backups — regular database backups, configuration directory backup, ClickHouse backup strategy, log rotation

  • Deploy multiple ACS instances for high availability — same configuration, external Hazelcast cluster with 2+ nodes, load balancer in front

  • Tune JVM settings — match the JVM Sizing table to your deployment size

10.1. Log Files Reference

Log File Purpose

server.log

Main application log

acsws.log

Web service calls and responses

liquibase.log

Database migration logs

sql.log

SQL query execution logs

bulk_process.log

Bulk operation processing

monitors.log

System monitoring events

db_session_killed.log

Database session management

externalTrace.log

External system integration traces

old_data_clean.log

Data cleanup operations

hikari.log

Connection pool diagnostics

11. Troubleshooting

11.1. Symptom: Container fails to start or exits immediately

Cause

Application configuration error, missing environment file, or dependency not ready.

Fix
# Check container logs for the error message
docker logs ftacs

# Check docker events
docker events --filter container=ftacs

# Inspect container configuration
docker inspect ftacs

# Verify environment variables are loaded
docker exec ftacs env | grep DB_

11.2. Symptom: Database connection failure on startup

Cause

Database is not running, wrong hostname/port, or incorrect credentials.

Fix
# Test MySQL connectivity from the container
docker exec ftacs nc -zv mysql 3306

# Check database logs
docker logs mysql

# Verify database credentials match between .env and MySQL container
docker exec ftacs env | grep DB_

Check that DB_HOST, DB_PASSWORD, MYSQL_PORT, and MYSQL_USER match the database configuration.

11.3. Symptom: "Port already in use" error

Cause

Another process is already bound to the requested port.

Fix
# Find process using port 8080
sudo lsof -i :8080

# Or use netstat
netstat -tulpn | grep 8080

# Option A: Kill the process
sudo kill <PID>

# Option B: Change the host port mapping in compose.yml or docker run
docker run -p 9080:8080 ...

11.4. Symptom: Permission denied on mounted volumes

Cause

Host directory permissions do not allow the container user to read/write.

Fix
# Fix volume permissions
sudo chown -R $(whoami):$(whoami) ${DATA_FOLDER}
chmod -R 755 ${DATA_FOLDER}

# Or run container as root (not recommended for production)
docker run --user root ...

11.5. Symptom: java.lang.OutOfMemoryError or container killed by OOM

Cause

JVM heap size exceeds available memory, or Docker memory limit is too low.

Fix
  1. Increase Docker memory limit (Docker Desktop: Settings → Resources → Memory: 4 GB+).

  2. Adjust JVM settings in .env or app.env:

    JAVA_OPTS='-Xms1g -Xmx4g'
  3. Analyze heap dump if the issue persists to identify memory leaks.

11.6. Symptom: Hazelcast connection warnings on startup

Cause

Hazelcast cluster is not running or not reachable from the ACS host.

Fix
  1. Verify Hazelcast cluster is running: docker logs hazelcast

  2. Check HZ_MEMBERS addresses in .env / app.env.

  3. Verify network connectivity: telnet <hazelcast-host> 5701

  4. Check firewall rules allow port 5701.

11.7. Symptom: "ClusterManager: detected failed or restarted instances"

Cause

This is normal behavior when the application restarts or a previous instance was not shut down cleanly.

Fix

No action needed. Quartz automatically recovers jobs from failed instances.

11.8. Symptom: Application fails to start (manual deployment)

Cause

Incorrect JAVA_HOME, wrong JDK version, missing database, or Liquibase migration failure.

Fix
  1. Verify Java: java -version must show JDK 25.

  2. Check JAVA_HOME in app.env.

  3. Verify database is running: telnet <DB_HOST> <DB_PORT>.

  4. Check credentials in app.env.

  5. Review logs/liquibase.log for SQL errors.

  6. On Windows, ensure APP_HOME uses forward slashes: D:/ftacs/dist/

11.9. Symptom: Docker containers not reachable from host (bridge networking)

Cause

The host firewall blocks traffic on Docker bridge interfaces (br-*) in the host INPUT/OUTPUT path for IPv4 and/or IPv6. This is not a Docker Compose or application issue.

Signs:

  • Container is healthy and responds on localhost inside the container.

  • Published ports appear correct (0.0.0.0:PORT→PORT).

  • Requests from the host hang / time out (no ECONNREFUSED, only timeouts).

    Fix

    Allow host-to-container traffic on Docker bridges:

    # IPv4 (generic -- all Docker bridges)
    iptables -I INPUT  1 -i br+ -j ACCEPT
    iptables -I OUTPUT 1 -o br+ -j ACCEPT
    
    # IPv6 (separate rules required)
    ip6tables -I INPUT  1 -i br+ -j ACCEPT
    ip6tables -I OUTPUT 1 -o br+ -j ACCEPT
    
    # Persist rules (Debian/Ubuntu)
    apt-get install -y iptables-persistent
    netfilter-persistent save

Diagnosis steps:

# 1. Confirm container works internally
docker exec <container> curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8080

# 2. Get container IPv4 address
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container>

# 3. Test from host to container IP
nc -vz <container_ipv4> 8080

# 4. Identify Docker bridge
ip -4 addr | grep '^.*br-'

# 5. Check firewall
iptables -S INPUT
iptables -S OUTPUT

IPv4 working does not imply IPv6 works. IPv4 and IPv6 are separate firewall stacks. Docker programs NAT and FORWARD rules but does not override host INPUT/OUTPUT firewall policies.

11.10. Symptom: Slow performance or high response times

Cause

Undersized JVM, database query performance issues, or network latency.

Fix
  1. Check database query performance.

  2. Verify Hazelcast cache hit ratios.

  3. Review connection pool settings.

  4. Monitor with Grafana dashboards.

  5. Check network latency to database/Hazelcast.

  6. Increase JVM heap if needed (see JVM Sizing table).

11.11. Getting Support

If issues persist, collect the following information and contact Friendly Tech support:

  1. app.env / .env configuration (mask passwords)

  2. logs/server.log (last 1000 lines)

  3. logs/liquibase.log (if database issues)

  4. Java version: java -version

  5. Operating system version

  6. Database type and version

  7. Docker version: docker version (if applicable)

11.12. Upgrade Procedure (Manual Deployment)

  1. Backup current installation — database backup, configuration files, log files.

  2. Stop application:

    ps aux | grep ftacs
    kill <PID>
  3. Extract new version to a new directory.

  4. Migrate configuration — copy and adapt app.env from the old version; review new configuration options.

  5. Start new version — Liquibase automatically migrates the database schema.

  6. Verify functionality — test device connections, web services, monitoring dashboards.

  7. Rollback (if needed) — stop new version, restore database backup, start old version.