You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Important: Gateways are exposed directly on their own IP/port (e.g., gateway-prd.company.com:4443).
They do NOT go through nginx. Each zone (PRD, DR, DMZ) has its own gateway.
Communication Protocols
Browser ---HTTPS---> nginx:443 ---HTTP---> backend:3000
(proxy_pass /api/* and /ws)
---HTTP---> frontend:8080
(proxy_pass /* for SPA)
appctl ---HTTP(S)---> backend:3000
(direct API calls, no nginx needed)
Gateway ---WebSocket---> backend:3000/ws/gateway
(internal, persistent connection, reconnect on failure)
Agent ---WSS (mTLS)---> gateway:4443/ws
(DIRECT connection, not through nginx)
(outbound only, reconnect with exponential backoff 1s..60s)
Connection Details
Agent --> Gateway (WSS, mTLS)
Agent initiates outbound WebSocket connection to gateway
No inbound port needed on the agent (firewall-friendly)
mTLS: agent presents its certificate, gateway verifies it
WSS on port 443/4443 passes through most corporate firewalls
(indistinguishable from HTTPS traffic)
Automatic reconnect with exponential backoff (1s, 2s, 4s... max 60s)
Offline buffer: agent stores messages locally if gateway is unreachable
1. User clicks "Start" / POST /api/v1/apps/{id}/start
|
2. Backend: INSERT INTO action_log (log before execute)
|
3. Backend: Kahn's topological sort → execution plan
| Level 0: [Oracle-DB]
| Level 1: [Tomcat-App, RabbitMQ]
| Level 2: [Apache-Front, Batch-Processor]
|
4. For each level (sequentially):
| For each component in level (in parallel):
| 4a. Set state STARTING → INSERT INTO state_transitions
| 4b. Send ExecuteCommand (start_cmd) → Gateway → Agent
| 4c. Agent: double-fork + setsid → detached process
| 4d. Wait for check_cmd to return exit 0 (RUNNING)
| 4e. If timeout/fail → mark FAILED, suspend job
|
5. All levels complete → all components RUNNING → job complete
Data Flow: DR Switchover (6 Phases)
Phase 1 - PREPARE: Verify DR agents connected, run health checks
Phase 2 - FREEZE: Block user operations on active site
Phase 3 - STOP_SOURCE: Stop all components on PRD (reverse DAG)
Phase 4 - START_TARGET: Start all components on DR (DAG order)
Phase 5 - VERIFY: Run integrity checks on DR site
Phase 6 - COMMIT: Update active_site_id (point of no return)
Rollback possible before COMMIT → restart source, cancel switchover
RTO measured: time from FREEZE to COMMIT
Data Flow: 3-Level Diagnostic + Rebuild
1. POST /api/v1/apps/{id}/diagnose
|
2. For each component, run 3 check levels:
| Level 1 (Health): check_cmd → exit code
| Level 2 (Integrity): integrity_check_cmd → exit code
| Level 3 (Infrastructure): infra_check_cmd → exit code
|
3. Recommendation matrix (8 combinations):
| H=OK, I=OK, F=OK → HEALTHY (no action)
| H=OK, I=OK, F=KO → HEALTHY (infra issue but app works)
| H=OK, I=KO, * → HEALTHY (integrity issue, informational)
| H=KO, I=OK, F=OK → RESTART (process died, data OK)
| H=KO, I=OK, F=KO → INFRA_REBUILD (process + infra bad)
| H=KO, I=KO, F=OK → APP_REBUILD (process + data bad)
| H=KO, I=KO, F=KO → INFRA_REBUILD (everything bad)
|
4. POST /api/v1/apps/{id}/rebuild
| Check rebuild_protected flag (409 if protected)
| Execute in DAG order (databases before appservers)
| For INFRA_REBUILD: use bastion agent (rebuild_agent_id)
| Measure RTR (Recovery Time for Rebuild)
WebSocket Considerations for Legacy Environments
WebSocket (RFC 6455) is used for all real-time communication. This is the right
choice for AppControl because:
Agent connections are long-lived (hours/days) — HTTP polling would be wasteful
Bidirectional messaging — backend can push commands to agents without polling
Low latency — state changes are reflected in the UI within milliseconds
Potential Issues on Legacy Infrastructure
Scenario
Problem
Mitigation
Old HTTP/1.0 proxy
Cannot upgrade to WebSocket
Use WSS on port 443 (looks like HTTPS, proxy passes it through)
Corporate firewall
Blocks non-HTTP protocols
WSS on 443 is indistinguishable from HTTPS at the TLS level
Load balancer timeout
Closes idle connections
Agent heartbeat every 60s keeps connections alive
WAF inspection
Deep packet inspection rejects WS frames
Whitelist the gateway endpoint, or use mTLS (WAF cannot inspect)
Reverse proxy misconfigured
Missing Upgrade/Connection headers
nginx config includes proper WebSocket proxy headers (see nginx.conf)
Long polling would mean agents cannot receive commands instantly (only on next poll)
The 60s heartbeat interval already acts as a keep-alive mechanism
WebSocket overhead per message is 2-6 bytes vs. ~500 bytes for HTTP headers
Deployment Recommendation
For environments with strict proxy requirements:
Gateway: listen on port 443 (standard HTTPS port)
with TLS termination + mTLS client verification
→ passes through all corporate firewalls
→ indistinguishable from HTTPS traffic
LISTEN_PORT=443 (in gateway config / env var)
The agent's outbound-only connection model means no firewall rules need
to be opened for inbound traffic on monitored servers.
Message Protocol (Agent <-> Backend)
Agent → Backend
Message
Fields
Purpose
Register
agent_id, hostname, labels, version
First message on connect
Heartbeat
agent_id, cpu, memory, at
Every 60s, keeps connection alive
CheckResult
component_id, check_type, exit_code, stdout, duration_ms, at