3-Tier Architecture Reference
Detailed technical documentation of the 3-Tier Docker Swarm architecture, compose compilation, overlay networking, and container constraints.
MCM Platform — 3-Tier Swarm Internal Reference & Architecture Guide
Confidential — For Internal Operations and DevOps Engineering Teams Only.
This document details the low-level architecture, multi-node clustering mechanics, Docker Compose compilation pipeline, internal security layers, scripting engines, and overlay network topography of the MCM (Multi-Cloud Management) Platform deployed on a 3-Tier Docker Swarm.
1. High-Level Orchestration & Topography
The 3-Tier production environment consists of 26 distinct containerized services distributed across a multi-node Swarm cluster consisting of one Swarm Manager (mcm-access) and two Swarm Workers (mcm-app and mcm-db).
2. Service Inventory
The table below lists all cluster-managed services, detailing their target node labels, internal networking ports, technology stack, and description.
| Service | Container Name | Placement Label | Replica | Tech Stack | Description |
|---|---|---|---|---|---|
| MCM UI | mcm_mcm-ui | node.labels.tier == app | 1 | Next.js 16, React 19 | Web interface |
| MCM API | mcm_mcm-api | node.labels.tier == app | 1 | Java 21, Spring Boot 3.4.5 | Core platform logic |
| APISIX | mcm_apisix | node.labels.tier == access | 1 | Apache APISIX 3.12.0 | API gateway & reverse proxy |
| etcd | mcm_etcd | node.labels.tier == access | 1 | etcd 3.5.11 | APISIX configuration store |
| Keycloak | mcm_keycloak | node.labels.tier == db | 1 | Keycloak 26.3.1 | Identity provider (IAM/SSO) |
| PostgreSQL | mcm_postgres | node.labels.tier == db | 1 | PostgreSQL 17.7 | Keycloak relational database |
| MongoDB | mcm_mongodb | node.labels.tier == db | 1 | MongoDB 7.0.16 | Primary application data store |
| Elasticsearch | mcm_elasticsearch | node.labels.tier == db | 1 | Elasticsearch 8.19.3 | Search and analytics engine |
| Kibana | mcm_kibana | node.labels.tier == db | 1 | Kibana 8.19.3 | Log dashboard visualization |
| Filebeat | mcm_filebeat | node.labels.tier == db | 1 | Filebeat 8.19.3 | DB / Security log collector |
| Governance API | mcm_mcm-governance-api | node.labels.tier == app | 1 | Java 21, Spring Boot 3.4.5 | Governance & compliance engine |
| FinOps API | mcm_mcm-finops-api | node.labels.tier == app | 1 | Java 21, Spring Boot 3.4.5 | Financial cost analysis module |
| SecOps API | mcm_mcm-secops-api | node.labels.tier == app | 1 | Java 21, Spring Boot 3.4.5 | Security operations API |
| Orchestration API | mcm_mcm-orchestration-api | node.labels.tier == app | 1 | Java 21, Spring Boot 3.4.5 | IaC engine (OpenTofu) |
| AI API | mcm_mcm-ai-api | node.labels.tier == app | 1 | Python, FastAPI | Chatbot service |
| Discovery API | mcm_mcm-discovery-api | node.labels.tier == app | 1 | Java 21, Spring Boot 3.4.5 | Asset discovery backend |
| Observability API | mcm_mcm-observability-api | node.labels.tier == app | 1 | Java 21, Spring Boot 3.4.5 | Observability manager |
| Fleet Server | mcm_observability-fleet-server | node.labels.tier == db | 1 | Elastic Agent 8.19.3 | Observability fleet controller |
| Wazuh Manager | mcm_wazuh-manager | node.labels.tier == db | 1 | Wazuh Manager 4.14.1 | SIEM coordinator |
| Wazuh Indexer | mcm_wazuh-indexer | node.labels.tier == db | 1 | Wazuh Indexer 4.14.1 | SIEM database (OpenSearch) |
| Wazuh Dashboard | mcm_wazuh-dashboard | node.labels.tier == db | 1 | Wazuh Dashboard 4.14.1 | SIEM web console |
3. Docker Compose Consolidation & Compilation Deep Dive
The installer does not deploy raw Docker Compose files. Instead, it consolidates four independent configuration sources into a single optimized deployment stack file (/opt/mcm/docker-compose-stack.yml).
3.1 The Merging Command
During installation or upgrade, the script runs the following command on VM1:
docker compose \
--env-file /opt/mcm/internal_config.env \
--env-file /etc/mcm/secrets.env \
--env-file /etc/mcm/user_config.env \
-f /opt/mcm/docker-compose-access.yml \
-f /opt/mcm/docker-compose-app.yml \
-f /opt/mcm/docker-compose-db.yml \
-f /opt/mcm/docker-compose-swarm-override.yml \
config | sed -E 's|image: /|image: |g' > /opt/mcm/docker-compose-stack.ymlWhy this is done:
- Modularity: Developers maintain clean service blocks split by tier (Access, App, DB).
- Constraint Isolation: Node constraints and replica policies are kept in
docker-compose-swarm-override.ymlto prevent leakage into standard developer builds. - Secret Injection: Config attributes are pre-resolved from env files directly into the compiled output.
3.2 Compilation Transformations
Following the merge, the installer executes two critical post-processing steps to ensure Docker Swarm engine compatibility:
1. yq Sanitization
Docker Swarm ignores certain Compose parameters and throws schema validation errors if they remain in the file. The compiler strips them out using yq:
yq -i 'del(.services[].depends_on) | del(.services[].profiles) | del(.services[].links) | del(.name)' /opt/mcm/docker-compose-stack.ymldepends_onis stripped because Swarm relies on dynamic service health checks and DNS availability rather than startup sequencing.profilesare stripped to force all services to compile into a single static stack representation.linksare removed in favor of native overlay network service discovery.
2. Port Quote Stripping (Integer Resolution)
Docker Compose outputs port numbers wrapped in quotes (e.g. published: "80"), which causes Docker Swarm schema parser validations to fail (rejecting strings where integers are expected).
The compiler uses a Python regex replacement engine to remove quotes around these values:
import re
c = re.sub(r"published:\s*[\x22\x27](\d+)[\x22\x27]", r"published: \1", c)
c = re.sub(r"target:\s*[\x22\x27](\d+)[\x22\x27]", r"target: \1", c)4. Node Placement Constraints & Replica Pinning
To enforce physical isolation, services declare placement constraints referencing labeled nodes.
During the install.sh sequence, nodes are labeled by their hostname:
docker node update --label-add tier=access "$VM1_HOSTNAME"docker node update --label-add tier=app "$VM2_HOSTNAME"docker node update --label-add tier=db "$VM3_HOSTNAME"
Database Pinning & Data Volumes
Databases (postgres, mongodb, elasticsearch, wazuh-indexer) require persistent storage. In Docker Swarm:
- Replica Constraints: All databases are pinned to
replicas: 1. - Host Pinning: Databases are restricted to
node.labels.tier == db. This forces Swarm to always schedule databases on VM3, binding their named persistent volumes (e.g.,postgres_db_data,mongodb_data) to the local disk of VM3, preventing volume divergence across hosts.
5. Swarm Overlay Networking & Service Discovery
Services communicate across physical VM boundaries via the virtual apisix-net Overlay Network.
VM 1 (Access Gateway) VM 2 (Application API) VM 3 (Data & Auth)
+---------------------------+ +---------------------------+ +---------------------------+
| Ingress Traffic (443) | | | | |
| | | | | | |
| apisix | | mcm-api (Java) | | postgres |
+-------------+-------------+ +-------------+-------------+ +-------------+-------------+
| | |
+============= VXLAN Tunnel (UDP Port 4789) ======================+5.1 Communication Protocols
- Data Plane (VXLAN): Container-to-container packets are encapsulated and transmitted over physical host interfaces using UDP Port 4789.
- Control Plane (Gossip): Cluster nodes exchange membership details and routing tables over TCP and UDP Port 7946 (configured as two separate rules).
- Docker Swarm DNS: Docker runs an internal DNS resolver at
127.0.0.11inside each container. Resolving a container name (e.g.,mongodborkeycloak) returns a service Virtual IP (VIP). Swarm's built-in IPVS load balancer routes the request directly to the hosting container.
6. Multi-VM Installation and Upgrade Flows
6.1 Multi-Node Installation Flow (install.sh)
6.2 Multi-Node Upgrade Flow (upgrade.sh)
7. Certificate Architecture & Sync Deep Dive
MCM implements a dual Certificate Authority (CA) topology to secure both application-level traffic (via the MCM Root CA) and security monitoring telemetry (via the Wazuh CA):
7.1 Keystore and Truststore Internals
Java services require secure cryptographic storage formatted as PKCS12 archives:
keystore.p12: Holds the individual service's private key, certificate, and CA chain.- Alias:
mcm - Encryption Password: Read from
KEYSTORE_PASSWORDin/etc/mcm/secrets.env
- Alias:
truststore.p12: Holds trusted certificates representing entities the service can communicate with.- Alias
mcm: Points to the MCM Root CA (ca.crt). - Alias
wazuh-root-ca: Points to the Wazuh Root CA (root-ca.pem). - Aliases
<domain>-<index>: Points to certificates fetched recursively fromTRUSTED_DOMAINS(e.g.login.microsoftonline.com-0,login.microsoftonline.com-1). - Encryption Password: Read from
TRUSTSTORE_PASSWORDin/etc/mcm/secrets.env
- Alias
7.2 Configuration Fingerprint and Rotation
To prevent unnecessary certificate generation, the generate-certs.sh script tracks changes using /var/lib/mcm/.config_fingerprint.
The fingerprint is an MD5 hash calculated from:
Fingerprint = MD5(HOST_SERVER_IP | DOMAIN | TRUSTED_DOMAINS | MD5(secrets.env))If the fingerprint changes or is missing:
- The entire directory
/var/lib/mcm/is backed up to/var/backups/mcm/backup_<YYYYMMDD_HHMMSS>/. - A new MCM Root CA is generated at
/var/lib/mcm/certs/ca.keyandca.crt. - Each microservice's keystore, truststore, and self-signed certificate are regenerated.
- Wazuh certificates are regenerated using the generator container.
- A new
.config_fingerprintfile is written.
7.3 Multi-Node Certificate Distribution Pipeline
- Generation: On execution of the installer,
generate-certs.shexecutes on VM1 (Access Node). It calculates the configuration fingerprint and generates CA files, keystores, and truststores inside/var/lib/mcm/if changes are detected. - Synchronization: The installer recursively copies
/var/lib/mcm/from VM1 to VM2 and VM3 over SSH prior to stack deployment, ensuring all cluster hosts share identical trust roots.
8. Wazuh SIEM Complete Reference
Wazuh operates as an independent security enclave using standard configurations and secure certificate authentication.
8.1 Deployment Profile: mcm-secops
Wazuh components are deployed dynamically under the mcm-secops Swarm profile:
wazuh.manager: Central analysis engine performing file integrity monitoring (FIM), system auditing, and active response. Scheduled on VM3.wazuh.indexer: Security index database storing logs and vulnerability logs. Scheduled on VM3.wazuh.dashboard: Security console mapping alarms to compliance frameworks. Scheduled on VM3.init-wazuh-security: Configures certificate verification and index security mappings on first boot.
8.2 Certificate Generation & VM3 Distribution
Wazuh requires a strict directory structure of certificates under /var/lib/mcm/wazuh/certs/.
- Generation: The
generate-certs.shscript runswazuh-certs-generatorin a container on VM1, which compiles and generates all Wazuh node certs (wazuh.indexer.pem,wazuh.manager.pem,wazuh.dashboard.pem,admin.pem) and writes them into.tararchives. - Distribution & Extraction: The installer automatically transfers
/var/lib/mcm/over SSH from VM1 to VM3. It then extracts, flattens, and fixes file permissions to755under/var/lib/mcm/wazuh/certs/on VM3 before Swarm services are launched.
9. Internal Configuration Reference (internal_config.env)
Location: /opt/mcm/internal_config.env (on VM1 - Access Node)
This configuration file is compiled during the packaging/release stage and contains registry locations, microservice image tags, and common environment configurations. In the 3-tier architecture, this file resides on VM1 and is sourced by the Swarm Manager during stack compilation.
| Variable | Type | Description / Default Value |
|---|---|---|
DOCKER_REGISTRY | Hostname | URL of the Nexus container registry (e.g., nexus.revdau.internal:8082) |
MCM_UI_IMAGE | Image Tag | UI service image reference (e.g., revdau/mcm-ui:1.0.0-develop) |
MCM_API_IMAGE | Image Tag | Core API service image reference |
MCM_GOVERNANCE_API_IMAGE | Image Tag | Governance API image reference |
MCM_FINOPS_API_IMAGE | Image Tag | FinOps API image reference |
MCM_SECOPS_API_IMAGE | Image Tag | SecOps API image reference |
MCM_ORCHESTRATION_API_IMAGE | Image Tag | Orchestration API image reference |
MCM_DISCOVERY_API_IMAGE | Image Tag | Discovery API image reference |
MCM_OBSERVABILITY_API_IMAGE | Image Tag | Observability API image reference |
MCM_AI_API_IMAGE | Image Tag | AI API image reference |
APISIX_IMAGE | Image Tag | apache/apisix:3.12.0-debian |
ETCD_IMAGE | Image Tag | bitnami/etcd:3.5.11 |
POSTGRES_IMAGE | Image Tag | postgres:17.7-alpine |
KEYCLOAK_IMAGE | Image Tag | quay.io/keycloak/keycloak:26.3.1 |
ELASTICSEARCH_IMAGE | Image Tag | docker.elastic.co/elasticsearch/elasticsearch:8.19.3 |
MONGODB_IMAGE | Image Tag | mongo:7.0.16 |
YQ_IMAGE | Image Tag | mikefarah/yq:4.44.1 |
KIBANA_IMAGE | Image Tag | docker.elastic.co/kibana/kibana:8.19.3 |
FILEBEAT_IMAGE | Image Tag | docker.elastic.co/beats/filebeat:8.19.3 |
WAZUH_MANAGER_IMAGE | Image Tag | wazuh/wazuh-manager:4.14.1 |
WAZUH_INDEXER_IMAGE | Image Tag | wazuh/wazuh-indexer:4.14.1 |
WAZUH_DASHBOARD_IMAGE | Image Tag | wazuh/wazuh-dashboard:4.14.1 |
WAZUH_CERTS_GENERATOR_IMAGE | Image Tag | wazuh/wazuh-certs-generator:0.0.3 |
ELASTIC_AGENT_IMAGE | Image Tag | docker.elastic.co/beats/elastic-agent:8.19.3 |
ELASTIC_USERNAME | Username | Default Elasticsearch superuser (elastic) |
KIBANA_SYSTEM_USERNAME | Username | Kibana system process user (kibana_system) |
KIBANA_READ_ONLY_USERNAME | Username | Kibana read-only user (KibanaReadOnlyUser) |
TRUSTED_DOMAINS | CSV List | Domain list whose SSL certs are imported into service truststores |
HOST_SERVER_IP | IPv4 | VM1's IP address (detected automatically on startup) |
10. Complete Variable & Secrets Reference
All environment settings, profiles, and backend credentials are split across user configurations and system-managed secrets.
10.1 User Configuration (/etc/mcm/user_config.env)
This file is created on VM1 (Access Node) and synced to VM2 and VM3 during installation. It controls the global deployment variables and active Swarm profiles:
| Variable | Values | Description |
|---|---|---|
DEPLOY_ENV | main | Deployment environment identifier. Set to main for production. Do not modify. |
GENERATE_SECRETS | true, false | When true, auto-generates all passwords in secrets.env via pwgen. Set to false after first run. |
GENERATE_SELF_SIGN_CERTS | true, false | When true, auto-generates self-signed TLS certificates for the active domain/IP. Set to false after first run. |
COMPOSE_PROFILES | CSV List | Controls which Swarm service profiles to run. E.g., mcm-api,mcm-monitoring,mcm-governance,mcm-finops,mcm-orchestration,mcm-discovery,mcm-ai,mcm-observability. |
DOMAIN | FQDN or empty | Custom domain (e.g., mcm.example.com). If left empty, the server's public IP address is used. |
10.2 Secrets (/etc/mcm/secrets.env)
This file contains randomly generated system passwords. These are generated via pwgen on first install:
| Variable | Key Target | Description |
|---|---|---|
POSTGRES_KEYCLOAK_PASSWORD | PostgreSQL / Keycloak | Relational db authentication password |
KC_BOOTSTRAP_ADMIN_PASSWORD | Keycloak | Realm bootstrap administrator password |
KC_MCM_CLIENT_SECRET | Keycloak / Backend APIs | Client secret for secure client authentication |
ELASTIC_PASSWORD | Elasticsearch | Elastic superuser authentication password |
KEYSTORE_PASSWORD | Java API Keystores | PKCS12 keystore file security password |
TRUSTSTORE_PASSWORD | Java API Truststores | PKCS12 truststore file security password |
MONGO_INITDB_ROOT_PASSWORD | MongoDB | NoSQL root database administrator password |
MONGO_MASTER_KEY | MongoDB | Field-Level Encryption master key (96 bytes base64) |
11. Swarm Container Mounts & Volumes
Persistent data is mapped via named Docker volumes pinned to VM3 (the database node) to protect cluster storage integrity:
| Volume Name | Container Path | Stored Data |
|---|---|---|
mongodb_data | /data/db | App collections & user configuration data |
es_data | /usr/share/elasticsearch/data | Platform auditing records and analytics logs |
keycloak_db_data | /var/lib/postgresql/data | Relational tables, configurations, and users |
wazuh-indexer-data | /usr/share/wazuh-indexer/data | Threat intelligence records and SIEM logs |
wazuh_etc | /var/ossec/etc | Active response rules and Wazuh config |
12. Dynamic Health Check Endpoints
Engineers can query local diagnostic checks directly on the hosting nodes:
| Service | Host | Target Port | Health Check Query |
|---|---|---|---|
| MCM API | VM 2 | 9091 | curl -sk https://localhost:9091/api/actuator/health |
| Keycloak | VM 3 | 8080 | curl -sk http://localhost:8080/keycloak/health |
| Elasticsearch | VM 3 | 9200 | curl -sk -u elastic:<ELASTIC_PASSWORD> https://localhost:9200/_cluster/health |
| APISIX Gateway | VM 1 | 80 | curl -sk http://localhost/ (redirects to HTTPS) |
MCM Platform 3-Tier Swarm Engineering Reference v1.0.0
© 2026 RevDau Industries Private Limited. All rights reserved.
Proprietary and Confidential. Unauthorized distribution is strictly prohibited.
Internal Reference Guide
Technical deep dive into the MCM platform architecture, credentials, networking, and scripting internals for RevDau Ops.
VM Sizing Calculation Guide
Internal engineering reference documenting empirical telemetry measurements, per-module data footprint calculations, and formula derivations for MCM platform VM sizing.