Skip to content

Instantly share code, notes, and snippets.

@alifhaikal88
Last active August 7, 2025 03:12
Show Gist options
  • Save alifhaikal88/4f5c6216aa90100a9f0c2490fa77f9d5 to your computer and use it in GitHub Desktop.
Save alifhaikal88/4f5c6216aa90100a9f0c2490fa77f9d5 to your computer and use it in GitHub Desktop.
MyWira Portal (MWP) System Architecture

MyWira Backend System Architecture

1. System Components

Backend Application (Spring Boot)

  • Technology Stack: Java 11, Spring Boot 2.7.18, Maven
  • Main Class: com.isianpadu.mywira.Application.java
  • Deployment: WAR packaging for Tomcat deployment
  • Context Path: /api

Database Layer

  • Primary Database: PostgreSQL (MyWira)
    • Host: 172.16.50.71:6432
    • Database: mywira / mywiraprod
    • Connection Pool: HikariCP (max 500 connections)
  • Secondary Database: PostgreSQL (LCMS)
    • Host: 172.16.50.223:5432
    • Database: ltat_lcms
    • Purpose: Legacy Contribution Management System integration

Caching Layer

  • Technology: EhCache 2.10.6
  • Configuration: XML-based cache configuration
  • Purpose: Performance optimization for frequently accessed data

Activity Logging System

  • Technology: Custom Spring Boot AOP-based solution
  • Database: PostgreSQL table app_user_activity_logs
  • Features: Non-blocking, batch processing, circuit breaker pattern
  • Configuration: Configurable batch size (100), flush interval (30s), queue capacity (10,000)
  • Purpose: Comprehensive user activity tracking and audit trail

File Storage

  • Document Management: Laserfiche integration
    • URL: https://mywiraportal.ltat.gov.my/lf/api/v1/upload
    • Purpose: Document storage and management

2. Data Flow Diagrams

System Overview

graph LR
    A[Frontend Web Portal] --> B[Spring Boot Backend]
    B --> C[PostgreSQL - MyWira DB]
    B --> D[PostgreSQL - LCMS DB]
    B --> E[EhCache]
    B --> F[Laserfiche DMS]
    B --> G[Activity Logging System]
    B --> H[Email Service]
    B --> I[SMS Gateway - 360.my]
    B --> J[LCMS API]
    
    G --> C
    G --> K[In-Memory Queue]
    G --> L[Batch Processor]
    
    style A fill:#1a237e,color:#ffffff
    style B fill:#4a148c,color:#ffffff
    style C fill:#1b5e20,color:#ffffff
    style D fill:#1b5e20,color:#ffffff
    style E fill:#e65100,color:#ffffff
    style F fill:#880e4f,color:#ffffff
    style G fill:#9c27b0,color:#ffffff
    style H fill:#004d40,color:#ffffff
    style I fill:#004d40,color:#ffffff
    style J fill:#f57f17,color:#ffffff
    style K fill:#ff5722,color:#ffffff
    style L fill:#ff9800,color:#ffffff
Loading

Authentication Flow

sequenceDiagram
    participant U as User
    participant F as Auth Filter
    participant J as JWT Utils
    participant A as Auth Provider
    participant S as User Details Service
    participant D as Database
    
    U->>F: HTTP Request with JWT
    F->>J: Validate JWT Token
    J->>J: Parse & Verify Signature
    alt Valid Token
        J->>F: Token Valid
        F->>A: Create Authentication
        A->>S: Load User Details
        S->>D: Query User Data
        D->>S: User Info
        S->>A: User Details
        A->>F: Authentication Success
        F->>U: Continue Request
    else Invalid Token
        J->>F: Token Invalid
        F->>U: 401 Unauthorized
    end
Loading

Business Operation Flow (CQRS Pattern)

graph TD
    A[Controller] --> B{Request Type}
    B -->|Command| C[Command Handler]
    B -->|Query| D[Query Handler]
    
    C --> E[Service Layer]
    D --> E
    
    E --> F[Repository Layer]
    F --> G[Database]
    
    E --> H[Event Processing]
    H --> I[Scheduler Services]
    I --> J[External APIs]
    
    subgraph "Commands (Write Operations)"
        C1[Create Contribution]
        C2[Submit Withdrawal]
        C3[Update Profile]
    end
    
    subgraph "Queries (Read Operations)"
        Q1[Get Account Statement]
        Q2[List Contributions]
        Q3[Dashboard Data]
    end
    
    C --> C1
    C --> C2
    C --> C3
    
    D --> Q1
    D --> Q2
    D --> Q3
    
    style C fill:#c62828,color:#ffffff
    style D fill:#2e7d32,color:#ffffff
    style E fill:#6a1b9a,color:#ffffff
    style I fill:#e65100,color:#ffffff
Loading

File Upload Flow

sequenceDiagram
    participant U as User
    participant C as Controller
    participant V as Validator
    participant S as Upload Service
    participant L as Laserfiche
    participant D as Database
    
    U->>C: Upload File Request
    C->>V: Validate File Type & Size
    V->>C: Validation Result
    
    alt Valid File
        C->>S: Process Upload
        S->>L: Upload to Laserfiche
        L->>S: Return Document ID & URL
        S->>D: Save File Metadata
        D->>S: Confirmation
        S->>C: Upload Success
        C->>U: Document ID & Metadata
    else Invalid File
        C->>U: 400 Bad Request
    end
Loading

Activity Logging Flow

graph TB
    A[Business Method with @UserLogActivity] --> B[ActivityLoggingAspect]
    B --> C[ActivityEvent]
    C --> D[ActivityLogService]
    D --> E[In-Memory Queue]
    E --> F[Batch Processor]
    F --> G[UserActivityLogRepository]
    G --> H[PostgreSQL Database]
    
    I[Health Check] --> D
    J[REST API] --> K[Activity Log Controller]
    K --> G
    
    D --> L[Circuit Breaker]
    D --> M[Metrics & Monitoring]
    
    subgraph "Activity Types"
        AT1[LOGIN/LOGOUT]
        AT2[API_CALL]
        AT3[DATA_CREATE/UPDATE/DELETE]
        AT4[FILE_UPLOAD/DOWNLOAD]
        AT5[CONTRIBUTION_SUBMIT]
        AT6[WITHDRAWAL_SUBMIT]
    end
    
    B --> AT1
    B --> AT2
    B --> AT3
    B --> AT4
    B --> AT5
    B --> AT6
    
    style A fill:#1a237e,color:#ffffff
    style B fill:#4a148c,color:#ffffff
    style D fill:#9c27b0,color:#ffffff
    style E fill:#ff5722,color:#ffffff
    style F fill:#ff9800,color:#ffffff
    style H fill:#1b5e20,color:#ffffff
    style L fill:#d32f2f,color:#ffffff
    style M fill:#00acc1,color:#ffffff
Loading

Data Synchronization Flow

graph TD
    A[Scheduler Service] --> B{Sync Type}
    
    B -->|Contributor Data| C[LCMS API Call]
    B -->|Account Statement| D[LCMS API Call]
    B -->|Contribution History| E[LCMS API Call]
    
    C --> F[Process Response]
    D --> F
    E --> F
    
    F --> G[Transform Data]
    G --> H[Validate Data]
    H --> I[Update Local Database]
    
    I --> J[Audit Log]
    J --> K[Send Notifications]
    J --> AL[Activity Logging]
    
    subgraph "Scheduled Jobs"
        S1[Daily Sync]
        S2[Hourly Sync]
        S3[Real-time Sync]
    end
    
    A --> S1
    A --> S2
    A --> S3
    
    style A fill:#e65100,color:#ffffff
    style F fill:#2e7d32,color:#ffffff
    style I fill:#1a237e,color:#ffffff
    style K fill:#880e4f,color:#ffffff
    style AL fill:#9c27b0,color:#ffffff
Loading

3. Integration Points

External APIs and Services

3.1 LCMS (Legacy Contribution Management System)

  • Primary URL: http://172.16.50.221:8080/lcms-platform
  • Fallback URL: http://172.16.50.222:8080/lcms-platform
  • Authentication: Bearer Token (JWT)
  • Purpose: Contributor data synchronization, account statements, contributions

3.2 Email Services

  • Email Configuration:
  • SMTP Provider: Configuration managed via profile-specific properties
  • Backup SMTP: Office365 SMTP (configured in mail.properties)

3.3 SMS Gateway

  • Provider: 360.my SMS Gateway
  • URL: https://sms.360.my/gw/bulk360/v3_0/send.php
  • Sender ID: MyWIRA
  • Backup Provider: GoSMS
    • URL: https://api.gosms.com.my/eapi/sms.aspx

3.4 Document Storage

  • Laserfiche: Document management system integration

3.5 Web Portal

  • Frontend URL: https://mywiraportal.ltat.gov.my
  • Purpose: User interface for the MyWira portal

Module Integration Architecture

graph TB
    subgraph "Frontend Layer"
        FE[Web Portal - Angular/React]
    end
    
    subgraph "API Gateway Layer"
        AG[Spring Boot Controllers]
        AG1[Auth Controller]
        AG2[Contribution Controller]
        AG3[Withdrawal Controller]
        AG4[Dashboard Controller]
    end
    
    subgraph "Business Logic Layer"
        BL1[User Service]
        BL2[Contribution Service]
        BL3[Withdrawal Service]
        BL4[Notification Service]
        BL5[Dashboard Service]
        BL6[Activity Log Service]
    end
    
    subgraph "Data Access Layer"
        DA1[User Repository]
        DA2[Contribution Repository]
        DA3[Withdrawal Repository]
        DA4[Audit Repository]
        DA5[Activity Log Repository]
    end
    
    subgraph "External Integrations"
        EI1[LCMS API]
        EI2[Email Service]
        EI3[SMS Gateway]
        EI4[Laserfiche]
    end
    
    subgraph "Database Layer"
        DB1[(MyWira DB)]
        DB2[(LCMS DB)]
    end
    
    FE --> AG
    AG --> AG1
    AG --> AG2
    AG --> AG3
    AG --> AG4
    
    AG1 --> BL1
    AG2 --> BL2
    AG3 --> BL3
    AG4 --> BL5
    
    BL1 --> DA1
    BL2 --> DA2
    BL3 --> DA3
    BL4 --> DA4
    BL6 --> DA5
    
    BL1 --> BL6
    BL2 --> BL6
    BL3 --> BL6
    
    BL2 --> EI1
    BL3 --> EI1
    BL4 --> EI2
    BL4 --> EI3
    BL3 --> EI4
    
    DA1 --> DB1
    DA2 --> DB1
    DA3 --> DB1
    DA4 --> DB1
    DA5 --> DB1
    EI1 --> DB2
    
    style FE fill:#1a237e,color:#ffffff
    style AG fill:#4a148c,color:#ffffff
    style BL1 fill:#2e7d32,color:#ffffff
    style BL2 fill:#2e7d32,color:#ffffff
    style BL3 fill:#2e7d32,color:#ffffff
    style BL4 fill:#2e7d32,color:#ffffff
    style BL5 fill:#2e7d32,color:#ffffff
    style BL6 fill:#9c27b0,color:#ffffff
    style EI1 fill:#f57f17,color:#ffffff
    style EI2 fill:#004d40,color:#ffffff
    style EI3 fill:#004d40,color:#ffffff
    style EI4 fill:#880e4f,color:#ffffff
Loading

Integration Flow Diagram

sequenceDiagram
    participant U as User
    participant P as Portal
    participant API as MyWira API
    participant LCMS as LCMS System
    participant EMAIL as Email Service
    participant SMS as SMS Gateway
    
    Note over U,SMS: User Registration Flow
    U->>P: Register Account
    P->>API: Submit Registration
    API->>LCMS: Validate Contributor
    LCMS->>API: Contributor Data
    API->>EMAIL: Send Verification Email
    API->>SMS: Send OTP SMS
    EMAIL->>U: Email Notification
    SMS->>U: SMS OTP
    
    Note over U,SMS: Contribution Submission
    U->>P: Submit Contribution
    P->>API: Process Contribution
    API->>LCMS: Sync Contribution Data
    LCMS->>API: Confirmation
    API->>EMAIL: Send Confirmation
    EMAIL->>U: Success Notification
Loading

4. Security Controls

Security Architecture Overview

graph TB
    subgraph "Client Layer"
        CL[Web Browser]
        MOBILE[Mobile App]
    end
    
    subgraph "Network Security"
        HTTPS[HTTPS/TLS 1.3]
        CORS[CORS Policy]
        FIREWALL[Network Firewall]
    end
    
    subgraph "Application Security"
        AUTH[Authentication Filter]
        JWT[JWT Validation]
        RBAC[Role-Based Access Control]
        RATE[Rate Limiting]
        VALID[Input Validation]
        CSRF[CSRF Protection]
    end
    
    subgraph "Data Security"
        ENCRYPT[Data Encryption]
        HASH[Password Hashing - BCrypt]
        AUDIT[Audit Logging]
        BACKUP[Secure Backups]
    end
    
    subgraph "Infrastructure Security"
        DB_SEC[Database Security]
        FILE_SEC[File Upload Security]
        API_SEC[API Security]
        MONITOR[Security Monitoring]
    end
    
    CL --> HTTPS
    MOBILE --> HTTPS
    HTTPS --> FIREWALL
    FIREWALL --> CORS
    CORS --> AUTH
    
    AUTH --> JWT
    JWT --> RBAC
    RBAC --> RATE
    RATE --> VALID
    VALID --> CSRF
    
    CSRF --> ENCRYPT
    ENCRYPT --> HASH
    HASH --> AUDIT
    
    AUDIT --> DB_SEC
    DB_SEC --> FILE_SEC
    FILE_SEC --> API_SEC
    API_SEC --> MONITOR
    
    style CL fill:#1a237e,color:#ffffff
    style HTTPS fill:#2e7d32,color:#ffffff
    style AUTH fill:#e65100,color:#ffffff
    style JWT fill:#e65100,color:#ffffff
    style RBAC fill:#e65100,color:#ffffff
    style ENCRYPT fill:#880e4f,color:#ffffff
    style HASH fill:#880e4f,color:#ffffff
    style DB_SEC fill:#4a148c,color:#ffffff
Loading

Authentication & Authorization Flow

sequenceDiagram
    participant U as User
    participant F as Frontend
    participant A as Auth Controller
    participant J as JWT Service
    participant P as Auth Provider
    participant S as User Service
    participant D as Database
    
    Note over U,D: Login Process
    U->>F: Enter Credentials
    F->>A: POST /auth/login
    A->>P: Authenticate User
    P->>S: Load User Details
    S->>D: Query User & Roles
    D->>S: User Data with Permissions
    S->>P: UserDetails Object
    P->>A: Authentication Success
    A->>J: Generate JWT Token
    J->>A: JWT with Claims
    A->>F: JWT Token + User Info
    F->>U: Login Success
    
    Note over U,D: Authenticated Request
    U->>F: Make API Request
    F->>A: Request with JWT Header
    A->>J: Validate JWT
    J->>J: Check Signature & Expiry
    J->>A: Token Valid
    A->>S: Authorize Request
    S->>A: Permission Granted
    A->>F: API Response
    F->>U: Display Data
Loading

4.1 Authentication & Authorization

  • JWT-based Authentication: Token expiration set to 24 hours (86400000ms)
  • Multiple Authentication Providers: Support for standard and MyDID authentication
  • Password Security: BCrypt encryption with strength 10
  • Session Management: Stateless (no server-side sessions)

4.2 Access Control

  • Role-Based Access Control (RBAC): Implemented through Spring Security
  • Method-Level Security: @EnableMethodSecurity annotations
  • Public Endpoints: Limited set of endpoints accessible without authentication
    • /token, /auth/**, /appConfig/**, /doc/**, /public/**, /metrics/**

4.3 Network Security

  • CORS Configuration:
    • Allowed Origins: All (*)
    • Allowed Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
    • Exposed Headers: Authorization
    • Max Age: 3600 seconds

4.4 Data Protection

  • Database Security: Connection pooling with timeout configurations
  • Password History: Tracks previous passwords to prevent reuse
  • Password Reset: Secure token-based password reset mechanism
  • Rate Limiting: Implemented via RateLimitService and RateLimitInterceptor

4.5 Input Validation

  • Spring Validation: Bean validation annotations
  • File Upload Security:
    • Allowed file types: PDF, JPEG, PNG, JPG, GIF, BMP, WEBP
    • Maximum file size: 10MB
    • Maximum request size: 10MB

4.6 Audit & Logging

  • Audit Trail: Comprehensive audit logging through AuditTrailService
  • User Activity Logging: Non-blocking activity tracking via @UserLogActivity annotation
    • Database Table: app_user_activity_logs with optimized indexes
    • Batch Processing: Configurable batch size (100 events) and flush interval (30s)
    • Circuit Breaker: Automatic failure handling and system protection
    • Activity Types: LOGIN, API_CALL, DATA_CREATE/UPDATE/DELETE, FILE_UPLOAD/DOWNLOAD, etc.
  • HTTP Request Logging: Via HttpLoggingInterceptor and UserLoggingFilter
  • Structured Logging: Logback configuration with environment-specific settings

4.7 Security Headers & Filters

  • Authentication Filter: AuthTokenFilter for JWT validation
  • CSRF Protection: Disabled for REST API (stateless)
  • Security Entry Point: Custom authentication entry point for unauthorized access

4.8 Sensitive Data Handling

  • Configuration Management: Environment-specific property files
  • Secret Management: JWT secrets and API keys stored in configuration
  • Data Encryption: Utility classes for encryption operations

4.9 Task Scheduling & Background Processing

  • Scheduled Jobs:
    • Account unlock scheduler
    • Email/SMS processing
    • Data synchronization with LCMS
    • Auto-resolved inquiry processing
  • Async Processing: Enabled for background tasks
  • Job Execution Logging: Tracks scheduled job execution

5. Infrastructure & Deployment Architecture

Production VM Setup

# Component Internal IP Public IP (via CDN) Hostname Network Zone
1 External Load Balancer 172.30.10.68 104.26.0.87, 104.26.1.87, 172.67.74.126 mywprod-extloadbalancer DMZ
2 Portal Database 172.16.50.71 N/A (Internal Only) mywprod-portaldb VLAN50
3 Portal Server 1 172.30.10.69 Via Load Balancer mywprod-portalserver1 DMZ
4 Portal Server 2 172.30.10.70 Via Load Balancer mywprod-portalserver2 DMZ

Note: The public IPs (104.26.0.87, 104.26.1.87, 172.67.74.126) are managed through Cloudflare CDN for mywiraportal.ltat.gov.my

Network Topology

graph TB
    subgraph "Internet & CDN"
        INTERNET[Internet Users]
        CDN[Cloudflare CDN<br/>104.26.0.87<br/>104.26.1.87<br/>172.67.74.126]
    end
    
    subgraph "DMZ Network - 172.30.10.0/24"
        ELB[External Load Balancer<br/>172.30.10.68]
        PS1[Portal Server 1<br/>172.30.10.69]
        PS2[Portal Server 2<br/>172.30.10.70]
    end
    
    subgraph "Internal Network - VLAN50 - 172.16.50.0/24"
        DB[Portal Database<br/>172.16.50.71]
        LCMS1[LCMS Server 1<br/>172.16.50.221]
        LCMS2[LCMS Server 2<br/>172.16.50.222]
        LCMS_DB[LCMS Database<br/>172.16.50.223]
    end
    
    subgraph "Security Zones"
        FW1[Firewall - CDN to DMZ]
        FW2[Firewall - DMZ to Internal]
    end
    
    INTERNET --> CDN
    CDN --> FW1
    FW1 --> ELB
    
    ELB --> PS1
    ELB --> PS2
    
    PS1 --> FW2
    PS2 --> FW2
    FW2 --> DB
    FW2 --> LCMS1
    FW2 --> LCMS2
    FW2 --> LCMS_DB
    
    PS1 --> LCMS1
    PS1 --> LCMS2
    PS2 --> LCMS1
    PS2 --> LCMS2
    
    style INTERNET fill:#1a237e,color:#ffffff
    style CDN fill:#e65100,color:#ffffff
    style ELB fill:#f57f17,color:#ffffff
    style PS1 fill:#2e7d32,color:#ffffff
    style PS2 fill:#2e7d32,color:#ffffff
    style DB fill:#1565c0,color:#ffffff
    style LCMS1 fill:#d84315,color:#ffffff
    style LCMS2 fill:#d84315,color:#ffffff
    style LCMS_DB fill:#d84315,color:#ffffff
    style FW1 fill:#b71c1c,color:#ffffff
    style FW2 fill:#b71c1c,color:#ffffff
Loading

High Availability Architecture

graph TB
    subgraph "External Access"
        USERS[End Users]
        DNS[DNS Resolution<br/>mywiraportal.ltat.gov.my]
        CDN_LAYER[Cloudflare CDN<br/>104.26.0.87, 104.26.1.87<br/>172.67.74.126]
    end
    
    subgraph "DMZ - External Load Balancer"
        ELB[External Load Balancer<br/>172.30.10.68<br/>HAProxy/Nginx]
    end
    
    subgraph "DMZ - Application Servers"
        AS1[Portal Server 1<br/>172.30.10.69<br/>Tomcat + Spring Boot]
        AS2[Portal Server 2<br/>172.30.10.70<br/>Tomcat + Spring Boot]
    end
    
    subgraph "VLAN50 - Database Layer"
        DB_PRIMARY[Primary Database<br/>172.16.50.71<br/>PostgreSQL Master]
        DB_CACHE[Application Cache<br/>EhCache In-Memory]
    end
    
    subgraph "VLAN50 - External Integrations"
        LCMS_PRIMARY[LCMS Primary<br/>172.16.50.221<br/>REST API Server]
        LCMS_BACKUP[LCMS Backup<br/>172.16.50.222<br/>REST API Server]
        LCMS_DATABASE[LCMS Database<br/>172.16.50.223<br/>PostgreSQL]
    end
    
    subgraph "External Services"
        EMAIL[Email Service<br/>SMTP Providers]
        SMS[SMS Gateway<br/>360.my]
        LASERFICHE[Laserfiche DMS<br/>Document Storage]
    end
    
    USERS --> DNS
    DNS --> CDN_LAYER
    CDN_LAYER --> ELB
    
    ELB -->|Round Robin| AS1
    ELB -->|Round Robin| AS2
    
    AS1 --> DB_PRIMARY
    AS2 --> DB_PRIMARY
    
    AS1 --> DB_CACHE
    AS2 --> DB_CACHE
    
    AS1 -->|Primary| LCMS_PRIMARY
    AS1 -->|Fallback| LCMS_BACKUP
    AS2 -->|Primary| LCMS_PRIMARY
    AS2 -->|Fallback| LCMS_BACKUP
    
    LCMS_PRIMARY --> LCMS_DATABASE
    LCMS_BACKUP --> LCMS_DATABASE
    
    AS1 --> EMAIL
    AS1 --> SMS
    AS1 --> LASERFICHE
    AS2 --> EMAIL
    AS2 --> SMS
    AS2 --> LASERFICHE
    
    style USERS fill:#1a237e,color:#ffffff
    style CDN_LAYER fill:#e65100,color:#ffffff
    style ELB fill:#f57f17,color:#ffffff
    style AS1 fill:#2e7d32,color:#ffffff
    style AS2 fill:#2e7d32,color:#ffffff
    style DB_PRIMARY fill:#1565c0,color:#ffffff
    style LCMS_PRIMARY fill:#d84315,color:#ffffff
    style LCMS_BACKUP fill:#d84315,color:#ffffff
    style EMAIL fill:#ad1457,color:#ffffff
    style SMS fill:#ad1457,color:#ffffff
    style LASERFICHE fill:#4a148c,color:#ffffff
Loading

Security Network Segmentation

graph TB
    subgraph "Security Zones"
        subgraph "Internet Zone"
            INT[Internet<br/>Untrusted Network]
        end
        
        subgraph "DMZ Zone - 172.30.10.0/24"
            ELB_DMZ[Load Balancer<br/>172.30.10.68]
            APP1_DMZ[App Server 1<br/>172.30.10.69]
            APP2_DMZ[App Server 2<br/>172.30.10.70]
        end
        
        subgraph "Internal Zone - VLAN50 - 172.16.50.0/24"
            DB_INT[Database<br/>172.16.50.71]
            LCMS_INT[LCMS Servers<br/>172.16.50.221-223]
        end
    end
    
    subgraph "Security Controls"
        subgraph "Perimeter Security"
            FW_EXT[External Firewall<br/>Internet to DMZ]
            FW_INT[Internal Firewall<br/>DMZ to VLAN50]
        end
        
        subgraph "Access Controls"
            RULES_EXT[Rules: HTTPS/443, HTTP/80]
            RULES_INT[Rules: PostgreSQL/5432, LCMS/8080]
        end
        
        subgraph "Monitoring"
            IDS[Intrusion Detection]
            LOG[Security Logging]
            SIEM[SIEM Integration]
        end
    end
    
    INT --> FW_EXT
    FW_EXT --> ELB_DMZ
    FW_EXT --> RULES_EXT
    
    ELB_DMZ --> APP1_DMZ
    ELB_DMZ --> APP2_DMZ
    
    APP1_DMZ --> FW_INT
    APP2_DMZ --> FW_INT
    FW_INT --> RULES_INT
    FW_INT --> DB_INT
    FW_INT --> LCMS_INT
    
    FW_EXT --> IDS
    FW_INT --> IDS
    IDS --> LOG
    LOG --> SIEM
    
    style INT fill:#c62828,color:#ffffff
    style ELB_DMZ fill:#e65100,color:#ffffff
    style APP1_DMZ fill:#2e7d32,color:#ffffff
    style APP2_DMZ fill:#2e7d32,color:#ffffff
    style DB_INT fill:#1a237e,color:#ffffff
    style LCMS_INT fill:#f57f17,color:#ffffff
    style FW_EXT fill:#b71c1c,color:#ffffff
    style FW_INT fill:#b71c1c,color:#ffffff
    style IDS fill:#e65100,color:#ffffff
Loading

Nginx Load Balancer Configuration

graph TB
    subgraph "External Load Balancer - 172.30.10.68"
        NGINX[Nginx Load Balancer<br/>TLS 1.2/1.3<br/>HTTP/2 Enabled]
        SSL_TERM[SSL Termination<br/>Certificate: ltat.crt<br/>Key: ltat.rsa]
        SECURITY[Security Headers<br/>HSTS, X-Frame-Options<br/>XSS Protection]
    end
    
    subgraph "Upstream Configurations"
        WEB_UPSTREAM[Web Upstream<br/>Angular Frontend<br/>Port 9090]
        API_UPSTREAM[Backend Upstream<br/>Spring Boot API<br/>Port 8080]
        LF_UPSTREAM[Laserfiche Upstream<br/>Document Server<br/>Port 9090]
    end
    
    subgraph "Backend Servers"
        WEB1[Web Server 1<br/>172.30.10.69:9090<br/>Weight: 1]
        WEB2[Web Server 2<br/>172.30.10.70:9090<br/>Weight: 1 - Disabled]
        API1[API Server 1<br/>172.30.10.69:8080<br/>Weight: 1]
        API2[API Server 2<br/>172.30.10.70:8080<br/>Weight: 1]
        LF1[Laserfiche Server<br/>172.16.51.82:9090<br/>Weight: 1]
    end
    
    subgraph "Routing Rules"
        ROOT_ROUTE[Root Path to Web<br/>Angular SPA]
        API_ROUTE[API Gateway Route<br/>Backend API with Rewrite]
        LF_ROUTE[Laserfiche Route<br/>Document Management]
        HEALTH_ROUTE[Health Check Route<br/>Load Balancer Status]
    end
    
    NGINX --> SSL_TERM
    SSL_TERM --> SECURITY
    SECURITY --> ROOT_ROUTE
    SECURITY --> API_ROUTE
    SECURITY --> LF_ROUTE
    SECURITY --> HEALTH_ROUTE
    
    ROOT_ROUTE --> WEB_UPSTREAM
    API_ROUTE --> API_UPSTREAM
    LF_ROUTE --> LF_UPSTREAM
    
    WEB_UPSTREAM --> WEB1
    WEB_UPSTREAM -.-> WEB2
    API_UPSTREAM --> API1
    API_UPSTREAM --> API2
    LF_UPSTREAM --> LF1
    
    style NGINX fill:#2e7d32,color:#ffffff
    style SSL_TERM fill:#c62828,color:#ffffff
    style SECURITY fill:#e65100,color:#ffffff
    style WEB_UPSTREAM fill:#1b5e20,color:#ffffff
    style API_UPSTREAM fill:#1a237e,color:#ffffff
    style LF_UPSTREAM fill:#f57f17,color:#ffffff
    style WEB2 fill:#d32f2f,color:#ffffff
Loading

Nginx Routing Architecture

sequenceDiagram
    participant U as User
    participant CDN as Cloudflare CDN
    participant LB as Nginx Load Balancer
    participant WEB as Web Server (Angular)
    participant API as API Server (Spring Boot)
    participant LF as Laserfiche Server
    
    Note over U,LF: Frontend Request Flow
    U->>CDN: HTTPS Request (/)
    CDN->>LB: Forward to 172.30.10.68:443
    LB->>LB: SSL Termination & Security Headers
    LB->>WEB: Proxy to Web Upstream (9090)
    WEB->>LB: Angular SPA Response
    LB->>CDN: HTTPS Response
    CDN->>U: Cached/Optimized Response
    
    Note over U,LF: API Request Flow
    U->>CDN: HTTPS Request to API Gateway
    CDN->>LB: Forward with gw prefix
    LB->>LB: Rewrite gw path to root
    LB->>API: Proxy to Backend Upstream (8080)
    API->>LB: JSON API Response
    LB->>CDN: HTTPS Response
    CDN->>U: API Data
    
    Note over U,LF: Document Upload Flow
    U->>CDN: HTTPS Request to Laserfiche
    CDN->>LB: Forward with lf prefix
    LB->>LB: Rewrite lf path to root
    LB->>LF: Proxy to Laserfiche (9090)
    LF->>LB: Document Response
    LB->>CDN: HTTPS Response
    CDN->>U: Document/Upload Result
Loading

Frontend Server Configuration

graph TB
    subgraph "Web Server - 172.30.10.69:9090"
        WEB_SERVER[Nginx Web Server<br/>Angular SPA Host]
        STATIC_CACHE[Static File Caching<br/>JS, CSS, Images<br/>1 Year Expiry]
        SPA_ROUTING[SPA Fallback Routing<br/>try_files $uri /index.html]
        WEB_HEALTH[Health Check<br/>/health endpoint]
    end
    
    subgraph "Static Assets"
        JS[JavaScript Files<br/>Gzip Compressed]
        CSS[CSS Stylesheets<br/>Cache-Control: immutable]
        IMAGES[Images & Fonts<br/>Long-term Caching]
    end
    
    subgraph "Angular Application"
        INDEX[index.html<br/>No-cache Headers]
        ROUTES[Client-side Routes<br/>Angular Router]
        COMPONENTS[Angular Components<br/>Lazy Loaded]
    end
    
    WEB_SERVER --> STATIC_CACHE
    WEB_SERVER --> SPA_ROUTING
    WEB_SERVER --> WEB_HEALTH
    
    STATIC_CACHE --> JS
    STATIC_CACHE --> CSS
    STATIC_CACHE --> IMAGES
    
    SPA_ROUTING --> INDEX
    INDEX --> ROUTES
    ROUTES --> COMPONENTS
    
    style WEB_SERVER fill:#2e7d32,color:#ffffff
    style STATIC_CACHE fill:#e65100,color:#ffffff
    style SPA_ROUTING fill:#1b5e20,color:#ffffff
    style INDEX fill:#1a237e,color:#ffffff
    style JS fill:#d84315,color:#ffffff
    style CSS fill:#d84315,color:#ffffff
    style IMAGES fill:#d84315,color:#ffffff
Loading

Nginx Configuration Summary

External Load Balancer (nginx-elb.conf)

Server Details:

  • Host: 172.30.10.68
  • Ports: 80 (HTTP redirect), 443 (HTTPS/HTTP2)
  • SSL: TLS 1.2/1.3 with custom certificates
  • Security: HSTS, X-Frame-Options, XSS Protection

Upstream Configurations:

  • Web Upstream: Round-robin to port 9090 (Angular frontend)
    • Active: 172.30.10.69:9090
    • Disabled: 172.30.10.70:9090
  • Backend Upstream: Round-robin to port 8080 (Spring Boot API)
    • Active: 172.30.10.69:8080, 172.30.10.70:8080
  • Laserfiche Upstream: Single server
    • Active: 172.16.51.82:9090

Routing Rules:

  • / → Web upstream (Angular SPA)
  • /gw/* → Backend upstream (API with path rewrite)
  • /lf/* → Laserfiche upstream (Document management)
  • /nginx-health → Health check endpoint

Performance Settings:

  • Connection pooling: 64 keepalive connections
  • Client body size: 10MB
  • Proxy timeouts: 30s for all operations
  • HTTP/2 enabled for better performance

Frontend Web Server (nginx-mwp-web.conf)

Server Details:

  • Port: 9090
  • Document Root: /var/www/html/mwp-web
  • Application: Angular Single Page Application

Caching Strategy:

  • Static Assets: 1-year expiry with immutable cache control
    • Files: *.js, *.css, *.png, *.jpg, *.jpeg, *.gif, *.ico, *.svg, *.woff, *.woff2, *.ttf, *.eot
    • Gzip compression enabled
  • HTML Files: No-cache headers to ensure updates are delivered
  • SPA Routing: try_files $uri $uri/ /index.html for client-side routing

Health Monitoring:

  • Endpoint: /health
  • Response: "web-server-healthy"
  • Logging: Disabled for health checks

Zero-Downtime Deployment Flow

sequenceDiagram
    participant DEV as Developer
    participant GIT as Git Repository
    participant DEPLOY as Deployment Script
    participant SERVER1 as Portal Server 1 (172.30.10.69)
    participant SERVER2 as Portal Server 2 (172.30.10.70)
    participant LB as Load Balancer (172.30.10.68)
    participant HEALTH as Health Check Endpoint
    
    Note over DEV,HEALTH: Zero-Downtime Rolling Deployment
    
    DEV->>DEPLOY: ./deployment.sh ltat
    DEPLOY->>DEPLOY: Profile Selection & Validation
    DEPLOY->>SERVER1: Test SSH Connectivity
    DEPLOY->>SERVER2: Test SSH Connectivity
    
    Note over DEPLOY,HEALTH: Pre-deployment Health Check
    DEPLOY->>SERVER1: Check Current Health Status
    SERVER1->>HEALTH: GET /api/metrics/health
    HEALTH->>DEPLOY: Server 1 Status
    DEPLOY->>SERVER2: Check Current Health Status
    SERVER2->>HEALTH: GET /api/metrics/health
    HEALTH->>DEPLOY: Server 2 Status
    
    Note over DEPLOY,HEALTH: Deploy to Server 1 First
    DEPLOY->>SERVER1: Deploy Script Execution
    SERVER1->>GIT: git pull origin main
    SERVER1->>SERVER1: mvn clean package -DskipTests
    SERVER1->>SERVER1: Graceful Shutdown (SIGTERM)
    SERVER1->>SERVER1: Start New Instance (PID)
    SERVER1->>HEALTH: Health Check Validation
    HEALTH->>DEPLOY: Server 1 Healthy ✅
    
    Note over DEPLOY,HEALTH: Wait 15s then Deploy to Server 2
    DEPLOY->>DEPLOY: Sleep 15 seconds
    DEPLOY->>SERVER2: Deploy Script Execution
    SERVER2->>GIT: git pull origin main
    SERVER2->>SERVER2: mvn clean package -DskipTests
    SERVER2->>SERVER2: Graceful Shutdown (SIGTERM)
    SERVER2->>SERVER2: Start New Instance (PID)
    SERVER2->>HEALTH: Health Check Validation
    HEALTH->>DEPLOY: Server 2 Healthy ✅
    
    Note over DEPLOY,HEALTH: Final Status Check
    DEPLOY->>SERVER1: Check Final Status
    DEPLOY->>SERVER2: Check Final Status
    DEPLOY->>DEV: Deployment Complete ✅
Loading

Deployment Architecture Overview

graph TB
    subgraph "Deployment Environments"
        UAT_ENV[UAT Environment<br/>172.30.10.72, 172.30.10.73]
        LTAT_ENV[LTAT Environment<br/>172.30.10.69, 172.30.10.70]
    end
    
    subgraph "Deployment Script Components"
        PROFILE[Profile Selection<br/>uat / ltat]
        SSH_CHECK[SSH Connectivity Test<br/>Key-based Authentication]
        PRE_CHECK[Pre-deployment Health Check<br/>Ensure Zero Downtime]
        ROLLING[Rolling Deployment<br/>Server1 → Wait → Server2]
    end
    
    subgraph "Build & Deploy Process"
        GIT_PULL[Git Pull<br/>origin/main]
        MVN_BUILD[Maven Build<br/>clean package -DskipTests]
        GRACEFUL[Graceful Shutdown<br/>SIGTERM → Wait → SIGKILL]
        NEW_START[New Instance Start<br/>JVM Heap: 8GB]
        HEALTH_WAIT[Health Check Wait<br/>Max 60 seconds]
    end
    
    subgraph "Monitoring & Validation"
        HEALTH_ENDPOINT[Health Endpoint<br/>/api/metrics/health:8080]
        LOG_TAIL[Log Monitoring<br/>app.log tail -f]
        STATUS_CHECK[Process Status<br/>PID, CPU, Memory]
        ROLLBACK_READY[Rollback Capability<br/>Previous Instance Recovery]
    end
    
    PROFILE --> SSH_CHECK
    SSH_CHECK --> PRE_CHECK
    PRE_CHECK --> ROLLING
    
    ROLLING --> GIT_PULL
    GIT_PULL --> MVN_BUILD
    MVN_BUILD --> GRACEFUL
    GRACEFUL --> NEW_START
    NEW_START --> HEALTH_WAIT
    
    HEALTH_WAIT --> HEALTH_ENDPOINT
    HEALTH_ENDPOINT --> LOG_TAIL
    LOG_TAIL --> STATUS_CHECK
    STATUS_CHECK --> ROLLBACK_READY
    
    style PROFILE fill:#1a237e,color:#ffffff
    style ROLLING fill:#e65100,color:#ffffff
    style GRACEFUL fill:#d84315,color:#ffffff
    style HEALTH_ENDPOINT fill:#2e7d32,color:#ffffff
    style ROLLBACK_READY fill:#c62828,color:#ffffff
Loading

Deployment Script Configuration

graph LR
    subgraph "Configuration Settings"
        APP_CONFIG[Application Config<br/>APP_NAME: mywira-backend<br/>DEPLOY_DIR: /home/isianpadu_user3/projects/mywira-backend<br/>JAR_FILE: target/mywira-backend.war]
        
        JVM_CONFIG[JVM Configuration<br/>HEAP_SIZE: 8GB<br/>METASPACE_SIZE: 512MB<br/>PROFILE: uat/ltat]
        
        HEALTH_CONFIG[Health Check Config<br/>URL: /api/metrics/health<br/>PORT: 8080<br/>MAX_WAIT: 60 seconds]
    end
    
    subgraph "Environment Servers"
        UAT_SERVERS[UAT Servers<br/>172.30.10.72<br/>172.30.10.73]
        LTAT_SERVERS[LTAT Servers<br/>172.30.10.69<br/>172.30.10.70]
    end
    
    subgraph "SSH Configuration"
        SSH_OPTS[SSH Options<br/>StrictHostKeyChecking=no<br/>ConnectTimeout=5s<br/>PasswordAuthentication=no<br/>PubkeyAuthentication=yes<br/>BatchMode=yes]
    end
    
    subgraph "Deployment Commands"
        COMMANDS[Available Commands<br/>deploy profile<br/>status profile<br/>logs profile<br/>test profile<br/>uat shorthand<br/>ltat shorthand]
    end
    
    APP_CONFIG --> JVM_CONFIG
    JVM_CONFIG --> HEALTH_CONFIG
    
    HEALTH_CONFIG --> UAT_SERVERS
    HEALTH_CONFIG --> LTAT_SERVERS
    
    UAT_SERVERS --> SSH_OPTS
    LTAT_SERVERS --> SSH_OPTS
    
    SSH_OPTS --> COMMANDS
    
    style APP_CONFIG fill:#1a237e,color:#ffffff
    style JVM_CONFIG fill:#e65100,color:#ffffff
    style HEALTH_CONFIG fill:#2e7d32,color:#ffffff
    style SSH_OPTS fill:#d84315,color:#ffffff
    style COMMANDS fill:#ad1457,color:#ffffff
Loading

Deployment Script Features

Zero-Downtime Strategy:

  • Rolling Deployment: Deploy to one server at a time
  • Health Check Validation: Ensure new instance is healthy before proceeding
  • Graceful Shutdown: SIGTERM followed by 30s wait, then SIGKILL if needed
  • 15-second Gap: Wait between server deployments for stability

Environment Management:

  • UAT Environment: 172.30.10.72, 172.30.10.73
  • LTAT Environment: 172.30.10.69, 172.30.10.70 (Production)
  • Profile Selection: Interactive or command-line argument
  • Local vs Remote: Detects if running locally on a server

Build & Deployment Process:

  1. Git Update: git pull origin main
  2. Maven Build: mvn clean package -DskipTests
  3. Process Management: Find and gracefully stop old instance
  4. JVM Startup: Configure 8GB heap, 512MB metaspace
  5. Health Monitoring: Wait up to 60 seconds for health check pass

Safety & Monitoring Features:

  • Pre-deployment Check: Ensures at least one server is running
  • SSH Connectivity Test: Validates authentication before deployment
  • Process Monitoring: CPU, memory, uptime tracking
  • Log Tailing: Real-time log monitoring across all servers
  • Rollback Ready: Can recover previous instance if needed

Command Line Interface:

# Deployment commands
./deployment.sh deploy ltat    # Deploy with LTAT profile
./deployment.sh ltat           # Shorthand for LTAT deployment
./deployment.sh status ltat    # Check deployment status
./deployment.sh logs ltat      # Tail logs from all servers
./deployment.sh test ltat      # Test connectivity and health

6. Summary

  1. System Overview - High-level component relationships
  2. Authentication Flow - JWT-based security process
  3. Business Operations - CQRS pattern implementation
  4. File Upload Process - Multi-service integration
  5. Data Synchronization - Scheduled background jobs
  6. Module Integration - Layered architecture design
  7. Integration Flows - External service interactions
  8. Security Architecture - Multi-layered security controls
  9. Network Topology - Production infrastructure layout
  10. Nginx Configuration - Load balancer and routing setup
  11. Zero-Downtime Deployment - Rolling deployment strategy

The system demonstrates a robust, scalable, and secure foundation for the MyWira contribution management system, with comprehensive integration capabilities, strong security controls, and production-ready deployment processes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment