diff --git a/mermaid/HardwareArchitecture.mmd b/mermaid/HardwareArchitecture.mmd new file mode 100644 index 000000000..921171920 --- /dev/null +++ b/mermaid/HardwareArchitecture.mmd @@ -0,0 +1,503 @@ +%% Titan Lab physical hardware architecture. +%% Solid links are physical network, storage, power, or sensor paths. +%% Dashed links are administration, telemetry, or recovery control. +%%{init: {"flowchart": {"defaultRenderer": "elk", "curve": "stepAfter", "nodeSpacing": 30, "rankSpacing": 65, "useMaxWidth": false}, "elk": {"mergeEdges": true, "nodePlacementStrategy": "NETWORK_SIMPLEX", "forceNodeModelOrder": true, "considerModelOrder": "NODES_AND_EDGES"}, "themeVariables": {"background": "#000000"}, "themeCSS": "& { background-color: #000000 !important; }"}}%% +flowchart TB + internet["Internet"]:::external + ac_cloud["AC Infinity account"]:::external + + subgraph lab["Titan Lab"] + direction TB + + subgraph link_legend["Link colors"] + direction LR + + subgraph legend_network["Network"] + direction TB + legend_1g["1 Gbps"]:::legend1g + legend_25g["2.5 Gbps"]:::legend25g + legend_external["External network"]:::legendExternal + end + + subgraph legend_resources["Resources"] + direction TB + legend_local["Local attachment"]:::legendLocal + legend_shared["Shared storage"]:::legendShared + legend_gpu["GPU"]:::legendGpu + end + + subgraph legend_operations["Operations"] + direction TB + legend_power["Power and NUT"]:::legendPower + legend_telemetry["Telemetry and environment"]:::legendTelemetry + legend_control["Administration and recovery"]:::legendControl + legend_safety["Protective shutdown"]:::legendSafety + end + end + + subgraph network["Network fabric"] + direction LR + + router["ASUS RT-AX88URouter"]:::network + cisco["Cisco CBS110-24T1 Gbps switch"]:::network + trendnet["TRENDnet 9-port2.5 Gbps switch"]:::network + + router ==> cisco + router ==> trendnet + end + + subgraph atlas["Atlas Kubernetes cluster"] + direction TB + + subgraph control_plane["High-availability control plane, ARM64"] + direction LR + + subgraph titan_0a["titan-0a"] + direction TB + t0a_host["Raspberry Pi 58 GiB RAMUbuntu 24.04"]:::control + t0a_storage["Local500 GiB boot SSD"]:::localStorage + t0a_host --- t0a_storage + end + + subgraph titan_0b["titan-0b"] + direction TB + t0b_host["Raspberry Pi 58 GiB RAMUbuntu 24.04"]:::control + t0b_storage["Local500 GiB boot SSD"]:::localStorage + t0b_host --- t0b_storage + end + + subgraph titan_0c["titan-0c"] + direction TB + t0c_host["Raspberry Pi 58 GiB RAMUbuntu 24.04"]:::control + t0c_storage["Local500 GiB boot SSD"]:::localStorage + t0c_host --- t0c_storage + end + + t0a_host --- t0b_host + t0b_host --- t0c_host + end + + subgraph workers["Workers"] + direction TB + + subgraph pi5_workers["Newer workers, ARM64 Raspberry Pi 5"] + direction TB + + subgraph pi5_row_a[" "] + direction LR + + subgraph titan_04["titan-04"] + direction TB + t04_host["Raspberry Pi 58 GiB RAMUbuntu 24.04"]:::pi5 + t04_storage["LocalSD root64 GiB astraios"]:::localStorage + t04_host --- t04_storage + end + + subgraph titan_05["titan-05"] + direction TB + t05_host["Raspberry Pi 58 GiB RAMUbuntu 24.04"]:::pi5 + t05_storage["LocalSD root64 GiB astraios"]:::localStorage + t05_host --- t05_storage + end + + subgraph titan_06["titan-06"] + direction TB + t06_host["Raspberry Pi 58 GiB RAMUbuntu 24.04"]:::pi5 + t06_storage["LocalSD root64 GiB astraios"]:::localStorage + t06_host --- t06_storage + end + end + + subgraph pi5_row_b[" "] + direction LR + + subgraph titan_07["titan-07"] + direction TB + t07_host["Raspberry Pi 58 GiB RAMUbuntu 24.04"]:::pi5 + t07_storage["LocalSD root64 GiB astraios"]:::localStorage + t07_host --- t07_storage + end + + subgraph titan_08["titan-08"] + direction TB + t08_host["Raspberry Pi 58 GiB RAMUbuntu 24.04"]:::pi5 + t08_storage["LocalSD root64 GiB astraios"]:::localStorage + t08_host --- t08_storage + end + + subgraph titan_11["titan-11"] + direction TB + t11_host["Raspberry Pi 58 GiB RAMUbuntu 24.04"]:::pi5 + t11_storage["LocalSD root64 GiB astraios"]:::localStorage + t11_host --- t11_storage + end + end + end + + subgraph pi4_workers["Older workers, ARM64 Raspberry Pi 4"] + direction TB + + subgraph pi4_row_a[" "] + direction LR + + subgraph titan_12["titan-12"] + direction TB + t12_host["Raspberry Pi 48 GiB RAMArmbian"]:::pi4 + t12_root["LocalSD root"]:::localStorage + t12_host --- t12_root + end + + subgraph titan_13["titan-13"] + direction TB + t13_host["Raspberry Pi 48 GiB RAMArmbian"]:::pi4 + t13_root["LocalSD root"]:::localStorage + t13_astreae["Longhorn8 TiB Astreae"]:::sharedStorage + t13_asteria["Longhorn12 TiB Asteria"]:::sharedStorage + t13_host --- t13_root + t13_host --- t13_astreae + t13_host --- t13_asteria + end + + subgraph titan_14["titan-14"] + direction TB + t14_host["Raspberry Pi 48 GiB RAMArmbian"]:::pi4 + t14_root["LocalSD root"]:::localStorage + t14_host --- t14_root + end + + subgraph titan_15["titan-15"] + direction TB + t15_host["Raspberry Pi 48 GiB RAMArmbian"]:::pi4 + t15_root["LocalSD root"]:::localStorage + t15_astreae["Longhorn8 TiB Astreae"]:::sharedStorage + t15_asteria["Longhorn12 TiB Asteria"]:::sharedStorage + t15_host --- t15_root + t15_host --- t15_astreae + t15_host --- t15_asteria + end + end + + subgraph pi4_row_b[" "] + direction LR + + subgraph titan_17["titan-17"] + direction TB + t17_host["Raspberry Pi 48 GiB RAMArmbian"]:::pi4 + t17_root["LocalSD root"]:::localStorage + t17_astreae["Longhorn8 TiB Astreae"]:::sharedStorage + t17_asteria["Longhorn12 TiB Asteria"]:::sharedStorage + t17_host --- t17_root + t17_host --- t17_astreae + t17_host --- t17_asteria + end + + subgraph titan_18["titan-18"] + direction TB + t18_host["Raspberry Pi 48 GiB RAMArmbian"]:::pi4 + t18_root["LocalSD root"]:::localStorage + t18_host --- t18_root + end + + subgraph titan_19["titan-19"] + direction TB + t19_host["Raspberry Pi 48 GiB RAMArmbian"]:::pi4 + t19_root["LocalSD root"]:::localStorage + t19_astreae["Longhorn8 TiB Astreae"]:::sharedStorage + t19_asteria["Longhorn12 TiB Asteria"]:::sharedStorage + t19_host --- t19_root + t19_host --- t19_astreae + t19_host --- t19_asteria + end + end + end + + subgraph accelerator_workers["Accelerators and high-capacity workers"] + direction TB + + subgraph jetson_workers["ARM64 NVIDIA Jetson"] + direction LR + + subgraph titan_20["titan-20"] + direction TB + t20_host["Jetson Xavier NX16 GiB RAMUbuntu 20.04Accelerator"]:::accelerator + t20_gpu["GPUNVIDIA Xavier"]:::gpu + t20_storage["Local256 GiB disk"]:::localStorage + t20_host --- t20_gpu + t20_host --- t20_storage + end + + subgraph titan_21["titan-21"] + direction TB + t21_host["Jetson Xavier NX16 GiB RAMUbuntu 20.04Accelerator"]:::accelerator + t21_gpu["GPUNVIDIA Xavier"]:::gpu + t21_storage["Local256 GiB disk"]:::localStorage + t21_host --- t21_gpu + t21_host --- t21_storage + end + end + + subgraph x86_workers["x86_64 systems"] + direction LR + + subgraph titan_22["titan-22"] + direction TB + t22_host["X830 mini PCCore i9-12900H32 GiB RAMDebian 13"]:::accelerator + t22_gpu["GPUNVIDIA RTX 3050 Ti"]:::gpu + t22_igpu["Intel Iris XeNot pooled"]:::localGpu + t22_storage["Local1 TiB disk"]:::localStorage + t22_host --- t22_gpu + t22_host --- t22_igpu + t22_host --- t22_storage + end + + subgraph titan_23["titan-23, Oceanus"] + direction TB + t23_host["EPYC 74F324 cores, 48 threads256 GiB RAMDebian 13"]:::server + t23_gpu["ASPEED graphicsNot pooled"]:::localGpu + t23_root["Local1 TiB disk"]:::localStorage + t23_data["Local4 TiB Veles4 TiB SUI"]:::localStorage + t23_host --- t23_gpu + t23_host --- t23_root + t23_host --- t23_data + end + + subgraph titan_24["titan-24, Tethys"] + direction TB + t24_host["Ryzen 9 3900X24 threads, 64 GiB RAMDebian 13"]:::accelerator + t24_gpu["GPUNVIDIA RTX 3080"]:::gpu + t24_root["Local500 GiB disk"]:::localStorage + t24_data["Local500 GiB home500 GiB temporary"]:::localStorage + t24_host --- t24_gpu + t24_host --- t24_root + t24_host --- t24_data + end + end + end + + pi5_workers ~~~ pi4_workers + pi4_workers ~~~ accelerator_workers + end + + subgraph virtual_resources["Virtual resource pools"] + direction LR + + subgraph cluster_storage["Longhorn storage classes"] + direction LR + + astreae["Astreae4 x 8 TiB32 TiB"]:::sharedPool + asteria["Asteria4 x 12 TiB48 TiB"]:::sharedPool + end + + subgraph cluster_gpus["Kubernetes GPU pool"] + direction LR + + arm_gpu_pool["NVIDIA ARM64titan-20 and titan-21"]:::gpuPool + x86_gpu_pool["NVIDIA x86_64titan-22 and titan-24"]:::gpuPool + end + end + + subgraph cluster_telemetry["Cluster telemetry"] + direction LR + + typhon["TyphonKubernetes workload"]:::clusterService + victoria["VictoriaMetrics"]:::telemetry + grafana["Grafana"]:::telemetry + + typhon ==>|environment metrics| victoria + victoria --> grafana + end + end + + subgraph outside_cluster["Lab systems outside the Atlas cluster"] + direction TB + + subgraph support_hosts["Support and host-level services"] + direction LR + + subgraph titan_db["titan-db"] + direction TB + + tdb_host["Raspberry Pi 58 GiB RAMUbuntu 24.04"]:::support + tdb_storage["Local500 GiB boot SSD"]:::localStorage + tdb_postgres["PostgreSQLHA control-plane database"]:::hostSoftware + ananke_db["NUT and AnankeHost servicesAutomatic recovery"]:::hostService + + tdb_host --- tdb_storage + tdb_host --- tdb_postgres + tdb_host --- ananke_db + end + + subgraph titan_jh["titan-jh"] + direction TB + + tjh_host["Raspberry Pi 58 GiB RAMArch Linux ARMJump host"]:::support + tjh_storage["Local256 GiB boot SSD"]:::localStorage + lesavka["LesavkaRemote control for Tethys"]:::hostService + + tjh_host --- tjh_storage + tjh_host --- lesavka + end + + ananke_t24["NUT and Ananke on titan-24Host services outside KubernetesUPS telemetry and safe shutdown"]:::hostService + end + + subgraph failed_hardware["Boards awaiting replacement"] + direction LR + + titan_09["titan-09Raspberry Pi 5"]:::failed + titan_10["titan-10Raspberry Pi 5"]:::failed + titan_16["titan-16Raspberry Pi 4"]:::failed + end + end + + subgraph facilities["Power and enclosure"] + direction LR + + subgraph protected_power["UPS protection"] + direction LR + + subgraph pyrphoros_power["Pyrphoros"] + direction TB + + pyrphoros["CyberPower850 VA UPS"]:::power + pyrphoros_loads["Protected loadsRouter and Cisco switchControl plane and Pi workersJetsons, titan-22, titan-dbCooling equipment"]:::powerLoad + pyrphoros --> pyrphoros_loads + end + + subgraph statera_power["Statera"] + direction TB + + statera["CyberPower1500PFCLCD"]:::power + statera_loads["Protected loadsTRENDnet switchtitan-23, titan-24, titan-jh"]:::powerLoad + statera --> statera_loads + end + end + + subgraph cooling["Enclosure cooling"] + direction TB + + enclosure["Filtered equipment tentAC-cooled intakeControlled exhaust"]:::environment + ac_controller["AC Infinity controllerTemperatureHumidityPressure"]:::environment + fans["Controlled intakeand exhaust fans"]:::environment + + enclosure --- ac_controller + ac_controller --> fans + end + end + + cisco ==> control_plane + cisco ==> pi5_workers + cisco ==> pi4_workers + cisco ==> jetson_workers + cisco ==> titan_db + trendnet ==> titan_jh + + trendnet ==> x86_workers + + t0b_host -.->|HA PostgreSQL| tdb_postgres + tjh_host -.->|administration| control_plane + tjh_host -.->|administration| workers + lesavka -.->|remote control| t24_host + + t13_astreae ==> astreae + t15_astreae ==> astreae + t17_astreae ==> astreae + t19_astreae ==> astreae + t13_asteria ==> asteria + t15_asteria ==> asteria + t17_asteria ==> asteria + t19_asteria ==> asteria + + t20_gpu ==> arm_gpu_pool + t21_gpu ==> arm_gpu_pool + t22_gpu ==> x86_gpu_pool + t24_gpu ==> x86_gpu_pool + + t24_host -.->|same physical host| ananke_t24 + pyrphoros -->|NUT| ananke_db + statera -->|NUT| ananke_t24 + ananke_db -.->|power metrics| victoria + ananke_t24 -.->|power metrics| victoria + ananke_db -.->|database and cluster recovery| t0a_host + ananke_t24 -.->|low-battery shutdown| control_plane + + ac_controller --> ac_cloud + ac_cloud -.->|environment data| typhon + end + + internet --> router + + classDef external fill:#292d33,stroke:#a0a8b3,color:#ffffff,stroke-width:2px + classDef network fill:#17324a,stroke:#65b5e8,color:#ffffff,stroke-width:2px + classDef control fill:#163e48,stroke:#65d2df,color:#ffffff,stroke-width:2px + classDef pi5 fill:#173d2a,stroke:#68d391,color:#ffffff,stroke-width:2px + classDef pi4 fill:#293b23,stroke:#9acb70,color:#ffffff,stroke-width:2px + classDef accelerator fill:#382b50,stroke:#b49aef,color:#ffffff,stroke-width:2px + classDef server fill:#3c3046,stroke:#c4a4dc,color:#ffffff,stroke-width:2px + classDef support fill:#293845,stroke:#9fc5dc,color:#ffffff,stroke-width:2px + classDef localStorage fill:#1d3040,stroke:#6f9fbd,color:#ffffff + classDef sharedStorage fill:#493b18,stroke:#efc65b,color:#ffffff,stroke-width:2px + classDef sharedPool fill:#594817,stroke:#ffd166,color:#ffffff,stroke-width:3px + classDef gpu fill:#482c5f,stroke:#d0a6ff,color:#ffffff,stroke-width:2px + classDef localGpu fill:#292d35,stroke:#9ba4b2,color:#ffffff + classDef gpuPool fill:#573476,stroke:#d8b4fe,color:#ffffff,stroke-width:3px + classDef clusterService fill:#153c38,stroke:#5fc9bc,color:#ffffff,stroke-width:2px + classDef telemetry fill:#203651,stroke:#67a9e9,color:#ffffff,stroke-width:2px + classDef hostSoftware fill:#243a45,stroke:#73b8d0,color:#ffffff,stroke-width:2px + classDef hostService fill:#48351c,stroke:#e3ae59,color:#ffffff,stroke-width:2px + classDef failed fill:#3d1f25,stroke:#f06b78,color:#ffffff,stroke-width:2px,stroke-dasharray:8 6 + classDef power fill:#49301c,stroke:#ec9f55,color:#ffffff,stroke-width:2px + classDef powerLoad fill:#3b2d20,stroke:#c98e55,color:#ffffff + classDef environment fill:#153d3a,stroke:#58c9bd,color:#ffffff,stroke-width:2px + classDef legend1g fill:#0b1726,stroke:#4ea1ff,color:#ffffff,stroke-width:3px + classDef legend25g fill:#082027,stroke:#22d3ee,color:#ffffff,stroke-width:3px + classDef legendExternal fill:#17162c,stroke:#818cf8,color:#ffffff,stroke-width:3px + classDef legendLocal fill:#171b20,stroke:#a8b3c2,color:#ffffff,stroke-width:3px + classDef legendShared fill:#2f270d,stroke:#f6c453,color:#ffffff,stroke-width:3px + classDef legendGpu fill:#271536,stroke:#c084fc,color:#ffffff,stroke-width:3px + classDef legendPower fill:#301b0c,stroke:#fb923c,color:#ffffff,stroke-width:3px + classDef legendTelemetry fill:#0b2917,stroke:#4ade80,color:#ffffff,stroke-width:3px + classDef legendControl fill:#32132a,stroke:#f472b6,color:#ffffff,stroke-width:3px + classDef legendSafety fill:#321217,stroke:#fb7185,color:#ffffff,stroke-width:3px + + style lab fill:#020202,stroke:#89919c,stroke-width:4px + style link_legend fill:#050505,stroke:#89919c,stroke-width:2px + style legend_network fill:#03070b,stroke:#4ea1ff,stroke-width:1px + style legend_resources fill:#080706,stroke:#f6c453,stroke-width:1px + style legend_operations fill:#080506,stroke:#f472b6,stroke-width:1px + style network fill:#03070b,stroke:#65b5e8,stroke-width:3px + style atlas fill:#020608,stroke:#65d2df,stroke-width:4px + style control_plane fill:#061014,stroke:#65d2df,stroke-width:3px + style workers fill:#030603,stroke:#72b879,stroke-width:3px + style pi5_workers fill:#050d08,stroke:#68d391,stroke-width:2px + style pi5_row_a fill:transparent,stroke:transparent + style pi5_row_b fill:transparent,stroke:transparent + style pi4_workers fill:#080d05,stroke:#9acb70,stroke-width:2px + style pi4_row_a fill:transparent,stroke:transparent + style pi4_row_b fill:transparent,stroke:transparent + style accelerator_workers fill:#09060d,stroke:#b49aef,stroke-width:2px + style jetson_workers fill:#0b0710,stroke:#b49aef,stroke-width:2px + style x86_workers fill:#0b0710,stroke:#c4a4dc,stroke-width:2px + style virtual_resources fill:#08080b,stroke:#a8a2b3,stroke-width:3px + style cluster_storage fill:#100d05,stroke:#ffd166,stroke-width:2px + style cluster_gpus fill:#0d0813,stroke:#d8b4fe,stroke-width:2px + style cluster_telemetry fill:#04100f,stroke:#5fc9bc,stroke-width:2px + style outside_cluster fill:#07090b,stroke:#9fc5dc,stroke-width:3px + style support_hosts fill:#07090b,stroke:#9fc5dc,stroke-width:2px + style failed_hardware fill:#0d0708,stroke:#f06b78,stroke-width:2px,stroke-dasharray:8 6 + style facilities fill:#070604,stroke:#ec9f55,stroke-width:3px + style protected_power fill:#0e0905,stroke:#ec9f55,stroke-width:2px + style pyrphoros_power fill:#100b06,stroke:#d99a58,stroke-width:2px + style statera_power fill:#100b06,stroke:#d99a58,stroke-width:2px + style cooling fill:#04100f,stroke:#58c9bd,stroke-width:2px + + linkStyle 0,54,55,56,57,58,59 stroke:#4ea1ff,color:#4ea1ff,stroke-width:3px + linkStyle 1,60 stroke:#22d3ee,color:#22d3ee,stroke-width:4px + linkStyle 86 stroke:#818cf8,color:#818cf8,stroke-width:3px + linkStyle 2,3,4,7,8,9,10,11,12,13,14,17,18,21,24,25,29,31,34,36,37,39,40,45,48 stroke:#a8b3c2,color:#a8b3c2,stroke-width:2px + linkStyle 15,16,19,20,22,23,26,27,65,66,67,68,69,70,71,72 stroke:#f6c453,color:#f6c453,stroke-width:3px + linkStyle 28,30,32,33,35,38,73,74,75,76 stroke:#c084fc,color:#c084fc,stroke-width:3px + linkStyle 50,51,78,79 stroke:#fb923c,color:#fb923c,stroke-width:3px + linkStyle 43,44,52,53,80,81,84,85 stroke:#4ade80,color:#4ade80,stroke-width:3px + linkStyle 5,6,46,47,49,61,62,63,64,77,82 stroke:#f472b6,color:#f472b6,stroke-width:2px + linkStyle 83 stroke:#fb7185,color:#fb7185,stroke-width:4px diff --git a/mermaid/HardwareArchitecture.svg b/mermaid/HardwareArchitecture.svg new file mode 100644 index 000000000..ddd96e8d6 --- /dev/null +++ b/mermaid/HardwareArchitecture.svg @@ -0,0 +1,67 @@ +Titan LabPower and enclosureLab systems outside the Atlas clusterAtlas Kubernetes clusterNetwork fabricLink colorsEnclosure coolingUPS protectionBoards awaiting replacementSupport and host-level servicesCluster telemetryVirtual resource poolsWorkersHigh-availability control plane, ARM64OperationsResourcesNetworkStateraPyrphorostitan-jhtitan-dbKubernetes GPU poolLonghorn storage classesAccelerators and high-capacity workersOlder workers, ARM64 Raspberry Pi 4Newer workers, ARM64 Raspberry Pi 5titan-0ctitan-0btitan-0ax86_64 systemsARM64 NVIDIA Jetsontitan-24, Tethystitan-23, Oceanustitan-22titan-21titan-20titan-19titan-18titan-17titan-15titan-14titan-13titan-12titan-11titan-08titan-07titan-06titan-05titan-04Filtered equipment tentAC-cooled intakeControlled exhaustAC Infinity controllerTemperatureHumidityPressureControlled intakeand exhaust fansCyberPower1500PFCLCDProtected loadsTRENDnet switchtitan-23, titan-24, titan-jhCyberPower850 VA UPSProtected loadsRouter and Cisco switchControl plane and Pi workersJetsons, titan-22, titan-dbCooling equipmenttitan-09Raspberry Pi 5titan-10Raspberry Pi 5titan-16Raspberry Pi 4Raspberry Pi 58 GiB RAMArch Linux ARMJump hostLocal256 GiB boot SSDLesavkaRemote control for TethysRaspberry Pi 58 GiB RAMUbuntu 24.04Local500 GiB boot SSDPostgreSQLHA control-plane databaseNUT and AnankeHost servicesAutomatic recoveryNUT and Ananke on titan-24Host services outside KubernetesUPS telemetry and safe shutdownTyphonKubernetes workloadVictoriaMetricsGrafanaNVIDIA ARM64titan-20 and titan-21NVIDIA x86_64titan-22 and titan-24Astreae4 x 8 TiB32 TiBAsteria4 x 12 TiB48 TiBRyzen 9 3900X24 threads, 64 GiB RAMDebian 13GPUNVIDIA RTX 3080Local500 GiB diskLocal500 GiB home500 GiB temporaryEPYC 74F324 cores, 48 threads256 GiB RAMDebian 13ASPEED graphicsNot pooledLocal1 TiB diskLocal4 TiB Veles4 TiB SUIX830 mini PCCore i9-12900H32 GiB RAMDebian 13GPUNVIDIA RTX 3050 TiIntel Iris XeNot pooledLocal1 TiB diskJetson Xavier NX16 GiB RAMUbuntu 20.04AcceleratorGPUNVIDIA XavierLocal256 GiB diskJetson Xavier NX16 GiB RAMUbuntu 20.04AcceleratorGPUNVIDIA XavierLocal256 GiB diskRaspberry Pi 48 GiB RAMArmbianLocalSD rootLonghorn8 TiB AstreaeLonghorn12 TiB AsteriaRaspberry Pi 48 GiB RAMArmbianLocalSD rootRaspberry Pi 48 GiB RAMArmbianLocalSD rootLonghorn8 TiB AstreaeLonghorn12 TiB AsteriaRaspberry Pi 48 GiB RAMArmbianLocalSD rootLonghorn8 TiB AstreaeLonghorn12 TiB AsteriaRaspberry Pi 48 GiB RAMArmbianLocalSD rootRaspberry Pi 48 GiB RAMArmbianLocalSD rootLonghorn8 TiB AstreaeLonghorn12 TiB AsteriaRaspberry Pi 48 GiB RAMArmbianLocalSD rootRaspberry Pi 58 GiB RAMUbuntu 24.04LocalSD root64 GiB astraiosRaspberry Pi 58 GiB RAMUbuntu 24.04LocalSD root64 GiB astraiosRaspberry Pi 58 GiB RAMUbuntu 24.04LocalSD root64 GiB astraiosRaspberry Pi 58 GiB RAMUbuntu 24.04LocalSD root64 GiB astraiosRaspberry Pi 58 GiB RAMUbuntu 24.04LocalSD root64 GiB astraiosRaspberry Pi 58 GiB RAMUbuntu 24.04LocalSD root64 GiB astraiosRaspberry Pi 58 GiB RAMUbuntu 24.04Local500 GiB boot SSDRaspberry Pi 58 GiB RAMUbuntu 24.04Local500 GiB boot SSDRaspberry Pi 58 GiB RAMUbuntu 24.04Local500 GiB boot SSDASUS RT-AX88URouterCisco CBS110-24T1 Gbps switchTRENDnet 9-port2.5 Gbps switchPower and NUTTelemetry and environmentAdministration and recoveryProtective shutdownLocal attachmentShared storageGPU1 Gbps2.5 GbpsExternal networkAC Infinity accountInternetenvironment metricsHA PostgreSQLadministrationadministrationremote controlsame physical hostNUTNUTpower metricspower metricsdatabase and cluster recoverylow-battery shutdownenvironment data \ No newline at end of file diff --git a/mermaid/ServiceAccessArchitecture.mmd b/mermaid/ServiceAccessArchitecture.mmd new file mode 100644 index 000000000..af951ee93 --- /dev/null +++ b/mermaid/ServiceAccessArchitecture.mmd @@ -0,0 +1,705 @@ +%% Atlas service access architecture. +%% Domains, identity profiles, entry services, and selected internal dependencies. +%% Node placement and short labels carry the detail. +%%{init: {"flowchart": {"defaultRenderer": "elk", "curve": "stepAfter", "nodeSpacing": 30, "rankSpacing": 65, "useMaxWidth": false}, "elk": {"mergeEdges": true, "nodePlacementStrategy": "LINEAR_SEGMENTS", "forceNodeModelOrder": true, "considerModelOrder": "NODES_AND_EDGES"}, "themeVariables": {"background": "#000000", "lineColor": "#8b95a5", "primaryTextColor": "#ffffff", "clusterBkg": "#03040d", "clusterBorder": "#6d7485"}, "themeCSS": "& { background-color: #000000 !important; }"}}%% +flowchart TB + subgraph system["Atlas Service Access Architecture"] + direction TB + + subgraph legend["Legend"] + direction LR + + subgraph node_key["Nodes"] + direction LR + key_domain["DNS name"]:::domain + key_access["OIDC access"]:::access + key_oauth["Access proxy"]:::oauth + key_directory["LDAP or synced account"]:::directory + key_entry["Entry service"]:::user + key_internal["Internal service"]:::support + key_data["Data service"]:::data + key_job["Job or worker"]:::ephemeral + key_external["Outside Kubernetes"]:::external + end + + subgraph link_key["Links"] + direction LR + key_ingress["BlueDomain to identity"]:::linkIngress + key_service["GreenIdentity to service"]:::linkService + key_direct["GoldDirect access"]:::linkDirect + key_auth["PurpleIdentity control"]:::linkAuth + key_data_link["VioletData flow"]:::linkData + key_telemetry["TealTelemetry"]:::linkTelemetry + key_control["OrangeDelivery and control"]:::linkControl + key_internal_link["GrayInternal flow"]:::linkInternal + end + end + + subgraph application_band["Applications and Communications"] + direction LR + + subgraph application_domains["Domains"] + direction TB + portal_domain["bstein.dev"]:::domain + portal_chat_domain["chat.ai.bstein.dev"]:::domain + cassandra_domain["cassandra.bstein.dev"]:::domain + element_domain["live.bstein.dev"]:::domain + matrix_domain["matrix.live.bstein.dev"]:::domain + call_domain["call.live.bstein.dev"]:::domain + livekit_domain["kit.live.bstein.dev"]:::domain + turn_domain["turn.live.bstein.dev"]:::domain + end + + subgraph application_access["Keycloak Access"] + direction LR + + subgraph application_atlas_access["atlas realm"] + direction TB + portal_oidc_access["Portal APIOIDC token"]:::access + portal_chat_oidc_access["Portal ChatOIDC"]:::access + element_oidc_access["Element WebOIDC through MAS"]:::access + matrix_oidc_access["MatrixOIDC through MAS"]:::access + end + + subgraph application_cassandra_access["cassandra realm"] + direction TB + cassandra_oidc_access["CassandraOIDC"]:::access + end + end + + subgraph application_services["Cluster Services"] + direction TB + + application_delivery["Flux deliveryApplication workloads"]:::control + application_state_clients["Shared PostgreSQLPortal and Matrix"]:::control + + subgraph website_ns["bstein-dev-home"] + direction LR + website_frontend["Portal"]:::user + website_chat_gateway["Chat gateway"]:::user + website_backend["Backend"]:::support + + website_frontend --> website_backend + website_chat_gateway --> website_backend + end + + subgraph cassandra_ns["cassandra"] + direction LR + cassandra_frontend["Cassandra UI"]:::user + cassandra_backend["API"]:::support + cassandra_postgres["PostgreSQL"]:::data + cassandra_generator["Generator"]:::ephemeral + cassandra_simulation["Simulation jobs"]:::ephemeral + cassandra_retention["Retention job"]:::ephemeral + cassandra_artifacts["Artifacts"]:::data + + cassandra_frontend --> cassandra_backend + cassandra_backend --> cassandra_postgres + cassandra_generator --> cassandra_backend + cassandra_simulation --> cassandra_backend + cassandra_simulation --> cassandra_artifacts + cassandra_retention --> cassandra_artifacts + end + + subgraph comms_ns["comms"] + direction LR + comms_element_web["Element Web"]:::user + comms_element_call["Element Call"]:::user + comms_wellknown["Matrix discovery"]:::support + comms_guest["Guest registration"]:::support + comms_mas["Matrix auth service"]:::support + comms_synapse["Synapse"]:::support + comms_replication["Synapse replication"]:::support + comms_redis["Redis"]:::data + comms_livekit_token["LiveKit token service"]:::support + comms_livekit["LiveKit"]:::support + comms_coturn["Coturn"]:::support + comms_atlasbot["Atlasbot"]:::support + + comms_element_web --> comms_mas + comms_element_web --> comms_synapse + comms_element_call --> comms_livekit_token + comms_livekit_token --> comms_livekit + comms_mas --> comms_synapse + comms_synapse --> comms_replication + comms_synapse --> comms_redis + comms_guest --> comms_synapse + comms_atlasbot --> comms_synapse + end + end + + portal_domain portal_identity@-->|HTTPS| portal_oidc_access + portal_oidc_access portal_entry@--> website_frontend + portal_chat_domain portal_chat_identity@-->|HTTPS| portal_chat_oidc_access + portal_chat_oidc_access portal_chat_entry@--> website_chat_gateway + cassandra_domain cassandra_identity@-->|HTTPS| cassandra_oidc_access + cassandra_oidc_access cassandra_entry@--> cassandra_frontend + element_domain element_identity@-->|HTTPS| element_oidc_access + element_oidc_access element_entry@--> comms_element_web + matrix_domain matrix_identity@-->|HTTPS| matrix_oidc_access + matrix_oidc_access matrix_entry@--> comms_synapse + matrix_domain matrix_api@-->|Matrix API| comms_synapse + call_domain call_entry@-->|HTTPS| comms_element_call + livekit_domain livekit_entry@-->|HTTPS and WebRTC| comms_livekit + turn_domain turn_entry@-->|TURN| comms_coturn + end + + subgraph personal_band["Personal Services"] + direction LR + + subgraph personal_domains["Domains"] + direction LR + + subgraph personal_domains_a["Accounts and Health"] + direction TB + budget_domain["budget.bstein.dev"]:::domain + firefly_domain["money.bstein.dev"]:::domain + wolf_domain["wolf.bstein.dev"]:::domain + moonlight_domain["moonlight.bstein.dev"]:::domain + wger_domain["health.bstein.dev"]:::domain + chat_domain["chat.bstein.dev"]:::domain + end + + subgraph personal_domains_b["Media and Productivity"] + direction TB + jellyfin_domain["stream.bstein.dev"]:::domain + pegasus_domain["pegasus.bstein.dev"]:::domain + mailu_domain["mail.bstein.dev"]:::domain + cloud_domain["cloud.bstein.dev"]:::domain + office_domain["office.bstein.dev"]:::domain + outline_domain["notes.bstein.dev"]:::domain + planka_domain["tasks.bstein.dev"]:::domain + vaultwarden_domain["vault.bstein.dev"]:::domain + monero_domain["monero.bstein.dev"]:::domain + end + end + + subgraph personal_access["atlas realm and directory access"] + direction LR + + subgraph personal_access_a["Accounts"] + direction TB + budget_oidc_access["Actual BudgetOpenID"]:::access + firefly_synced_access["FireflySynced account"]:::directory + wolf_oauth_access["WolfAccess proxy"]:::oauth + wger_synced_access["WgerSynced account"]:::directory + chat_oidc_access["Hermes ChatOIDC"]:::access + end + + subgraph personal_access_b["Media and Productivity"] + direction TB + jellyfin_ldap_access["JellyfinLDAP"]:::directory + cloud_oidc_access["NextcloudOIDC"]:::access + outline_oidc_access["OutlineOIDC"]:::access + planka_oidc_access["PlankaOIDC"]:::access + end + end + + subgraph personal_services["Cluster Services"] + direction LR + + personal_delivery["Flux deliveryPersonal workloads"]:::control + personal_state_clients["Shared PostgreSQLPersonal services"]:::control + + subgraph personal_services_a["Accounts, Health, and Media"] + direction TB + + subgraph finance_ns["finance"] + direction LR + finance_budget["Actual Budget"]:::user + finance_firefly["Firefly"]:::user + finance_sync["Account sync"]:::ephemeral + finance_import["Import job"]:::ephemeral + finance_sync --> finance_firefly + finance_import --> finance_firefly + end + + subgraph game_ns["game-stream"] + direction LR + game_proxy["Wolf access proxy"]:::oauth + game_manager["Wolf manager"]:::support + game_api["Wolf API"]:::support + game_wolf["Wolf"]:::support + game_gatekeeper["Gatekeeper"]:::support + game_moonlight["Moonlight"]:::user + game_proxy --> game_manager + game_manager --> game_api + game_api --> game_wolf + game_gatekeeper --> game_wolf + game_moonlight --> game_wolf + end + + subgraph health_ns["health"] + direction LR + health_wger["Wger"]:::user + health_sync["Account sync"]:::ephemeral + health_admin["Admin sync"]:::ephemeral + health_sync --> health_wger + health_admin --> health_wger + end + + subgraph hermes_chat_ns["hermes-chat"] + direction LR + hermes_chat["Hermes Chat"]:::user + end + + subgraph jellyfin_ns["jellyfin"] + direction LR + streaming_pegasus["Pegasus"]:::user + streaming_jellyfin["Jellyfin"]:::user + streaming_pegasus --> streaming_jellyfin + end + end + + subgraph personal_services_b["Mail and Productivity"] + direction TB + + subgraph mail_ns["mailu-mailserver"] + direction LR + mail_front["Mail web"]:::user + mail_protocols["Mail protocols"]:::user + mail_admin["Admin"]:::support + mail_dovecot["Dovecot"]:::support + mail_postfix["Postfix"]:::support + mail_rspamd["Rspamd"]:::support + mail_clamav["ClamAV"]:::support + mail_extractors["Tika and oletools"]:::support + mail_redis["Redis"]:::data + mail_front --> mail_admin + mail_protocols --> mail_dovecot + mail_protocols --> mail_postfix + mail_postfix --> mail_rspamd + mail_rspamd --> mail_clamav + mail_rspamd --> mail_extractors + mail_admin --> mail_redis + end + + subgraph cloud_ns["nextcloud"] + direction LR + cloud_nextcloud["Nextcloud"]:::user + cloud_collabora["Collabora"]:::support + cloud_mail_sync["Mail sync"]:::ephemeral + cloud_maintenance["Maintenance job"]:::ephemeral + cloud_nextcloud --> cloud_collabora + cloud_mail_sync --> cloud_nextcloud + cloud_maintenance --> cloud_nextcloud + end + + subgraph notes_tasks_ns["Notes and Tasks"] + direction LR + outline_service["Outline"]:::user + outline_redis["Redis"]:::data + planka_service["Planka"]:::user + outline_service --> outline_redis + end + + subgraph vaultwarden_ns["vaultwarden"] + direction LR + vaultwarden_service["Vaultwarden"]:::user + end + + subgraph crypto_ns["crypto"] + direction LR + crypto_wallet["Wallet RPC"]:::support + crypto_p2pool["P2Pool"]:::support + crypto_monerod["Monerod"]:::user + crypto_wallet --> crypto_monerod + crypto_p2pool --> crypto_monerod + end + end + end + + budget_domain budget_identity@-->|HTTPS| budget_oidc_access + budget_oidc_access budget_entry@--> finance_budget + firefly_domain firefly_identity@-->|HTTPS| firefly_synced_access + firefly_synced_access firefly_entry@--> finance_firefly + wolf_domain wolf_identity@-->|HTTPS| wolf_oauth_access + wolf_oauth_access wolf_entry@--> game_manager + moonlight_domain moonlight_entry@-->|Streaming| game_moonlight + wger_domain wger_identity@-->|HTTPS| wger_synced_access + wger_synced_access wger_entry@--> health_wger + chat_domain chat_identity@-->|HTTPS| chat_oidc_access + chat_oidc_access chat_entry@--> hermes_chat + jellyfin_domain jellyfin_identity@-->|HTTPS| jellyfin_ldap_access + jellyfin_ldap_access jellyfin_entry@--> streaming_jellyfin + pegasus_domain pegasus_entry@-->|HTTPS| streaming_pegasus + mailu_domain mail_web_entry@-->|HTTPS| mail_front + mailu_domain mail_protocol_entry@-->|Mail protocols| mail_protocols + cloud_domain cloud_identity@-->|HTTPS| cloud_oidc_access + cloud_oidc_access cloud_entry@--> cloud_nextcloud + office_domain office_entry@-->|WOPI| cloud_collabora + outline_domain outline_identity@-->|HTTPS| outline_oidc_access + outline_oidc_access outline_entry@--> outline_service + planka_domain planka_identity@-->|HTTPS| planka_oidc_access + planka_oidc_access planka_entry@--> planka_service + vaultwarden_domain vaultwarden_entry@-->|HTTPS and local auth| vaultwarden_service + monero_domain monero_entry@-->|RPC| crypto_monerod + end + + subgraph platform_band["Platform Services"] + direction LR + + subgraph platform_domains["Domains"] + direction LR + + subgraph platform_domains_a["Delivery"] + direction TB + gitops_domain["cd.bstein.dev"]:::domain + gitea_domain["scm.bstein.dev"]:::domain + harbor_domain["registry.bstein.dev"]:::domain + hermes_domain["agent.bstein.dev"]:::domain + jenkins_domain["ci.bstein.dev"]:::domain + end + + subgraph platform_domains_b["Operations"] + direction TB + logs_domain["logs.bstein.dev"]:::domain + longhorn_domain["longhorn.bstein.dev"]:::domain + grafana_domain["metrics.bstein.dev"]:::domain + alerts_domain["alerts.bstein.dev"]:::domain + quality_domain["quality.bstein.dev"]:::domain + keycloak_domain["sso.bstein.dev"]:::domain + vault_domain["secret.bstein.dev"]:::domain + end + end + + subgraph platform_access["Keycloak Access"] + direction LR + + subgraph platform_access_a["atlas realm delivery"] + direction TB + gitops_oidc_access["Weave GitOpsOIDC"]:::access + gitea_atlas_oidc_access["Giteaatlas realm"]:::access + harbor_oidc_access["Harbor UIOIDC"]:::access + hermes_oidc_access["Hermes AgentOIDC"]:::access + jenkins_oidc_access["JenkinsOIDC"]:::access + end + + subgraph platform_access_b["atlas realm operations"] + direction TB + logs_oauth_access["OpenSearch DashboardsAccess proxy"]:::oauth + longhorn_oauth_access["LonghornAdmin proxy"]:::oauth + grafana_oidc_access["GrafanaOIDC"]:::access + quality_oauth_access["SonarQubeAdmin and developer proxy"]:::oauth + keycloak_admin_access["Keycloak consoleRealm admin"]:::access + vault_oidc_access["VaultAdmin OIDC"]:::access + end + + subgraph platform_access_c["cassandra realm client"] + direction TB + gitea_cassandra_oidc_access["GiteaOIDC"]:::access + end + end + + subgraph platform_services["Cluster Services"] + direction LR + + platform_delivery["Flux deliveryPlatform workloads"]:::control + platform_state_clients["Shared PostgreSQLPlatform services"]:::control + + subgraph delivery_services["Delivery and Automation"] + direction TB + + subgraph flux_ns["flux-system"] + direction LR + flux_source["Source controller"]:::support + flux_kustomize["Kustomize controller"]:::support + flux_helm["Helm controller"]:::support + flux_image_reflector["Image reflector"]:::support + flux_image_automation["Image automation"]:::support + flux_notification["Notification controller"]:::support + flux_webhook["Webhook receiver"]:::support + flux_weave["Weave GitOps"]:::user + flux_source --> flux_kustomize + flux_source --> flux_helm + flux_image_reflector --> flux_image_automation + flux_webhook --> flux_notification + flux_weave --> flux_source + end + + subgraph gitea_ns["gitea"] + direction LR + gitea_http["Gitea web"]:::user + gitea_ssh["Gitea SSH"]:::support + end + + subgraph harbor_ns["harbor"] + direction LR + harbor_portal["Harbor portal"]:::user + harbor_core["Harbor core"]:::support + harbor_jobservice["Job service"]:::support + harbor_registry["OCI registry"]:::data + harbor_redis["Redis"]:::data + harbor_portal --> harbor_core + harbor_jobservice --> harbor_core + harbor_core --> harbor_registry + harbor_core --> harbor_redis + end + + subgraph hermes_ns["hermes"] + direction LR + hermes_agent["Hermes Agent"]:::user + hermes_model_gate["Model gate"]:::support + hermes_gpt_oss["gpt-oss:20bFallback model"]:::support + hermes_agent --> hermes_model_gate + hermes_model_gate --> hermes_gpt_oss + end + + subgraph jenkins_ns["jenkins"] + direction LR + jenkins_service["Jenkins"]:::user + jenkins_agents["Build agents"]:::ephemeral + jenkins_service --> jenkins_agents + end + end + + subgraph operations_services["Operations"] + direction TB + + subgraph logging_ns["logging"] + direction LR + logging_oauth_proxy["Dashboard proxy"]:::oauth + logging_dashboards["OpenSearch Dashboards"]:::user + logging_opensearch["OpenSearch"]:::data + logging_fluent_bit["Fluent Bit"]:::support + logging_otel["OpenTelemetry"]:::support + logging_data_prepper["Data Prepper"]:::support + logging_oauth_proxy --> logging_dashboards + logging_dashboards --> logging_opensearch + logging_fluent_bit --> logging_opensearch + logging_otel --> logging_data_prepper + logging_data_prepper --> logging_opensearch + end + + subgraph longhorn_ns["longhorn-system"] + direction LR + longhorn_oauth_proxy["Longhorn proxy"]:::oauth + longhorn_frontend["Longhorn UI"]:::user + longhorn_backend["Longhorn manager"]:::data + longhorn_webhooks["Admission and recovery"]:::support + longhorn_oauth_proxy --> longhorn_frontend + longhorn_frontend --> longhorn_backend + longhorn_webhooks --> longhorn_backend + end + + subgraph monitoring_ns["monitoring"] + direction LR + monitoring_grafana["Grafana"]:::user + monitoring_victoria["VictoriaMetrics"]:::data + monitoring_exporters["Cluster and node exporters"]:::support + monitoring_gpu_exporters["GPU exporters"]:::support + monitoring_quality_gateway["Quality gateway"]:::support + monitoring_postmark["Postmark exporter"]:::support + monitoring_vmalert["vmalert"]:::support + monitoring_alertmanager["Alertmanager"]:::user + monitoring_exporters --> monitoring_victoria + monitoring_gpu_exporters --> monitoring_victoria + monitoring_quality_gateway --> monitoring_victoria + monitoring_postmark --> monitoring_victoria + monitoring_victoria --> monitoring_grafana + monitoring_vmalert --> monitoring_alertmanager + end + end + + subgraph security_services["Identity and Security"] + direction TB + + subgraph quality_ns["quality"] + direction LR + quality_oauth_proxy["SonarQube proxy"]:::oauth + quality_sonarqube["SonarQube"]:::user + quality_exporter["Quality exporter"]:::support + quality_oauth_proxy --> quality_sonarqube + quality_exporter --> quality_sonarqube + end + + subgraph sso_ns["sso"] + direction LR + sso_oauth_proxy["Shared access proxy"]:::oauth + sso_keycloak["Keycloak"]:::user + atlas_realm["atlas realm"]:::control + cassandra_realm["cassandra realm"]:::control + sso_openldap["OpenLDAP"]:::directory + sso_jobs["Realm bootstrap and checks"]:::ephemeral + sso_keycloak --> atlas_realm + sso_keycloak --> cassandra_realm + sso_jobs --> sso_keycloak + end + + subgraph vault_ns["vault"] + direction LR + vault_service["Vault"]:::user + vault_internal["Vault cluster service"]:::support + vault_injector["Secret injector"]:::support + vault_jobs["Configuration jobs"]:::ephemeral + vault_service --> vault_internal + vault_injector --> vault_service + vault_jobs --> vault_service + end + end + end + + gitops_domain gitops_identity@-->|HTTPS| gitops_oidc_access + gitops_oidc_access gitops_entry@--> flux_weave + gitea_domain gitea_atlas_identity@-->|HTTPS| gitea_atlas_oidc_access + gitea_atlas_oidc_access gitea_atlas_entry@--> gitea_http + gitea_domain gitea_cassandra_identity@-->|HTTPS| gitea_cassandra_oidc_access + gitea_cassandra_oidc_access gitea_cassandra_entry@--> gitea_http + gitea_domain gitea_ssh_entry@-->|SSH| gitea_ssh + harbor_domain harbor_identity@-->|HTTPS| harbor_oidc_access + harbor_oidc_access harbor_entry@--> harbor_portal + harbor_domain harbor_registry_entry@-->|OCI| harbor_registry + hermes_domain hermes_identity@-->|HTTPS| hermes_oidc_access + hermes_oidc_access hermes_entry@--> hermes_agent + jenkins_domain jenkins_identity@-->|HTTPS| jenkins_oidc_access + jenkins_oidc_access jenkins_entry@--> jenkins_service + logs_domain logs_identity@-->|HTTPS| logs_oauth_access + logs_oauth_access logs_entry@--> logging_oauth_proxy + longhorn_domain longhorn_identity@-->|HTTPS| longhorn_oauth_access + longhorn_oauth_access longhorn_entry@--> longhorn_oauth_proxy + grafana_domain grafana_identity@-->|HTTPS| grafana_oidc_access + grafana_oidc_access grafana_entry@--> monitoring_grafana + alerts_domain alerts_entry@-->|HTTPS| monitoring_alertmanager + quality_domain quality_identity@-->|HTTPS| quality_oauth_access + quality_oauth_access quality_entry@--> quality_oauth_proxy + keycloak_domain keycloak_identity@-->|HTTPS| keycloak_admin_access + keycloak_admin_access keycloak_entry@--> sso_keycloak + vault_domain vault_identity@-->|HTTPS| vault_oidc_access + vault_oidc_access vault_entry@--> vault_service + end + + subgraph shared_plane["Shared Cluster Services"] + direction LR + + subgraph ingress_plane["Ingress and Networking"] + direction TB + metallb_control["MetalLBService addresses"]:::control + traefik_service["TraefikLoad balancer"]:::support + traefik_controller["TraefikTLS and routing"]:::support + cert_manager["cert-manager"]:::support + cert_webhooks["Certificate webhooks"]:::support + metallb_control --> traefik_service + traefik_service --> traefik_controller + cert_webhooks --> cert_manager + cert_manager --> traefik_controller + end + + subgraph shared_state["Shared State and Models"] + direction TB + postgres_service["Shared PostgreSQLApplication and platform databases"]:::data + ai_ollama["OllamaLocal model service"]:::support + default_zot_proxy["Zot access proxy"]:::oauth + end + + subgraph maintenance_ns["maintenance"] + direction TB + maintenance_ariadne["Ariadne"]:::support + maintenance_metis_proxy["Metis proxy"]:::oauth + maintenance_metis["Metis"]:::support + maintenance_soteria_proxy["Soteria proxy"]:::oauth + maintenance_soteria["Soteria"]:::support + maintenance_node_ops["Node operations"]:::ephemeral + maintenance_jobs["Repair and migration jobs"]:::ephemeral + maintenance_metis_proxy --> maintenance_metis + maintenance_soteria_proxy --> maintenance_soteria + maintenance_ariadne --> maintenance_node_ops + maintenance_ariadne --> maintenance_jobs + end + + subgraph telemetry_services["Additional Telemetry"] + direction TB + climate_typhon["TyphonTent climate"]:::support + sui_metrics["SUI metrics"]:::support + end + end + + subgraph external_systems["Host and Physical Systems"] + direction LR + ananke_hosts["Ananketitan-db and titan-24"]:::external + pyrphoros["Pyrphoros UPS"]:::external + statera["Statera UPS"]:::external + tent_system["AC InfinityController and cloud"]:::external + ananke_hosts --> pyrphoros + ananke_hosts --> statera + end + + firefly_synced_access firefly_directory@-.-> sso_openldap + wger_synced_access wger_directory@-.-> sso_openldap + jellyfin_ldap_access jellyfin_directory@-.-> sso_openldap + + website_backend website_model@-.-> ai_ollama + website_backend website_automation@-.-> maintenance_ariadne + hermes_chat hermes_chat_model@-.-> hermes_model_gate + hermes_agent hermes_jenkins@-.-> jenkins_service + hermes_agent hermes_metrics@-.-> monitoring_victoria + hermes_agent hermes_ariadne@-.-> maintenance_ariadne + + gitea_http gitea_jenkins@-.->|SCM webhook| jenkins_service + gitea_http gitea_flux@-.->|Flux webhook| flux_webhook + jenkins_agents jenkins_gitea@-.->|Clone and fetch| gitea_http + jenkins_agents jenkins_quality@-.->|Quality scan| quality_sonarqube + jenkins_agents jenkins_harbor@-.->|Images and artifacts| harbor_registry + flux_source flux_gitea@-.->|Desired state| gitea_ssh + flux_image_reflector flux_harbor@-.->|Image metadata| harbor_registry + flux_image_automation flux_commit@-.->|Manifest update| gitea_ssh + flux_kustomize flux_apps@-.-> application_delivery + flux_kustomize flux_personal@-.-> personal_delivery + flux_kustomize flux_platform@-.-> platform_delivery + + application_state_clients app_postgres@-.-> postgres_service + personal_state_clients personal_postgres@-.-> postgres_service + platform_state_clients platform_postgres@-.-> postgres_service + cloud_nextcloud nextcloud_mail@-.->|Mail delivery| mail_protocols + + quality_exporter quality_metrics@-.-> monitoring_victoria + sui_metrics sui_telemetry@-.-> monitoring_victoria + monitoring_victoria ananke_telemetry@-.-> ananke_hosts + climate_typhon climate_source@--> tent_system + climate_typhon climate_telemetry@-.-> monitoring_victoria + + class portal_identity,portal_chat_identity,cassandra_identity,element_identity,matrix_identity,budget_identity,firefly_identity,wolf_identity,wger_identity,chat_identity,jellyfin_identity,cloud_identity,outline_identity,planka_identity,gitops_identity,gitea_atlas_identity,gitea_cassandra_identity,harbor_identity,hermes_identity,jenkins_identity,logs_identity,longhorn_identity,grafana_identity,quality_identity,keycloak_identity,vault_identity routeIngress + class portal_entry,portal_chat_entry,cassandra_entry,element_entry,matrix_entry,budget_entry,firefly_entry,wolf_entry,wger_entry,chat_entry,jellyfin_entry,cloud_entry,outline_entry,planka_entry,gitops_entry,gitea_atlas_entry,gitea_cassandra_entry,harbor_entry,hermes_entry,jenkins_entry,logs_entry,longhorn_entry,grafana_entry,quality_entry,keycloak_entry,vault_entry routeService + class matrix_api,call_entry,livekit_entry,turn_entry,moonlight_entry,pegasus_entry,mail_web_entry,mail_protocol_entry,office_entry,vaultwarden_entry,monero_entry,gitea_ssh_entry,harbor_registry_entry,alerts_entry routeDirect + class firefly_directory,wger_directory,jellyfin_directory routeAuth + class app_postgres,personal_postgres,platform_postgres,nextcloud_mail,climate_source routeData + class quality_metrics,sui_telemetry,ananke_telemetry,climate_telemetry routeTelemetry + class website_automation,hermes_ariadne,gitea_jenkins,gitea_flux,jenkins_gitea,jenkins_quality,jenkins_harbor,flux_gitea,flux_harbor,flux_commit,flux_apps,flux_personal,flux_platform routeControl + class website_model,hermes_chat_model,hermes_jenkins,hermes_metrics routeInternal + end + + classDef domain fill:#16324f,stroke:#6cb6ff,color:#ffffff + classDef user fill:#173f2b,stroke:#61d095,color:#ffffff + classDef support fill:#30343b,stroke:#aab2bf,color:#ffffff + classDef data fill:#3b2f52,stroke:#b79cff,color:#ffffff + classDef ephemeral fill:#4a301e,stroke:#f0a35b,color:#ffffff,stroke-dasharray:6 3 + classDef control fill:#3b354e,stroke:#c1a7ff,color:#ffffff + classDef access fill:#213a56,stroke:#6cb6ff,color:#ffffff + classDef oauth fill:#3b2f52,stroke:#c1a7ff,color:#ffffff + classDef directory fill:#344a2d,stroke:#8ed081,color:#ffffff + classDef external fill:#44301f,stroke:#ffb86c,color:#ffffff + + classDef linkIngress fill:#101820,stroke:#4ea1ff,color:#ffffff + classDef linkService fill:#101820,stroke:#61d095,color:#ffffff + classDef linkDirect fill:#101820,stroke:#e4bd55,color:#ffffff + classDef linkAuth fill:#101820,stroke:#c1a7ff,color:#ffffff + classDef linkData fill:#101820,stroke:#b79cff,color:#ffffff + classDef linkTelemetry fill:#101820,stroke:#55c8d3,color:#ffffff + classDef linkControl fill:#101820,stroke:#f0a35b,color:#ffffff + classDef linkInternal fill:#101820,stroke:#aab2bf,color:#ffffff + + classDef routeIngress stroke:#4ea1ff,stroke-width:2.5px,color:#4ea1ff + classDef routeService stroke:#61d095,stroke-width:2.5px,color:#61d095 + classDef routeDirect stroke:#e4bd55,stroke-width:2.5px,color:#e4bd55 + classDef routeAuth stroke:#c1a7ff,stroke-width:2.2px,color:#c1a7ff,stroke-dasharray:6 4 + classDef routeData stroke:#b79cff,stroke-width:2.2px,color:#b79cff,stroke-dasharray:6 4 + classDef routeTelemetry stroke:#55c8d3,stroke-width:2.2px,color:#55c8d3,stroke-dasharray:6 4 + classDef routeControl stroke:#f0a35b,stroke-width:2.2px,color:#f0a35b,stroke-dasharray:6 4 + classDef routeInternal stroke:#aab2bf,stroke-width:2px,color:#aab2bf,stroke-dasharray:5 4 + + style system fill:#000000,stroke:#8b95a5,stroke-width:2px + style legend fill:#050505,stroke:#6d7485,stroke-width:1.5px + style application_band fill:#02030d,stroke:#55c8d3,stroke-width:2px + style personal_band fill:#06030d,stroke:#8ed081,stroke-width:2px + style platform_band fill:#07040c,stroke:#c1a7ff,stroke-width:2px + style shared_plane fill:#080604,stroke:#e4bd55,stroke-width:2px + style external_systems fill:#080402,stroke:#ffb86c,stroke-width:2px diff --git a/mermaid/ServiceAccessArchitecture.svg b/mermaid/ServiceAccessArchitecture.svg new file mode 100644 index 000000000..59c1f622c --- /dev/null +++ b/mermaid/ServiceAccessArchitecture.svg @@ -0,0 +1,67 @@ +Atlas Service Access ArchitectureHost and Physical SystemsShared Cluster ServicesPlatform ServicesPersonal ServicesApplications and CommunicationsLegendAdditional TelemetrymaintenanceShared State and ModelsIngress and NetworkingCluster ServicesKeycloak AccessDomainsCluster Servicesatlas realm and directory accessDomainsCluster ServicesKeycloak AccessDomainsLinksNodesIdentity and SecurityOperationsDelivery and Automationcassandra realm clientatlas realm operationsatlas realm deliveryOperationsDeliveryMail and ProductivityAccounts, Health, and MediaMedia and ProductivityAccountsMedia and ProductivityAccounts and Healthcommscassandrabstein-dev-homecassandra realmatlas realmvaultssoqualitymonitoringlonghorn-systemloggingjenkinshermesharborgiteaflux-systemcryptovaultwardenNotes and Tasksnextcloudmailu-mailserverjellyfinhermes-chathealthgame-streamfinanceAnanketitan-db and titan-24Pyrphoros UPSStatera UPSAC InfinityController and cloudTyphonTent climateSUI metricsAriadneMetis proxyMetisSoteria proxySoteriaNode operationsRepair and migration jobsShared PostgreSQLApplication and platform databasesOllamaLocal model serviceZot access proxyMetalLBService addressesTraefikLoad balancerTraefikTLS and routingcert-managerCertificate webhooksVaultVault cluster serviceSecret injectorConfiguration jobsShared access proxyKeycloakatlas realmcassandra realmOpenLDAPRealm bootstrap and checksSonarQube proxySonarQubeQuality exporterGrafanaVictoriaMetricsCluster and node exportersGPU exportersQuality gatewayPostmark exportervmalertAlertmanagerLonghorn proxyLonghorn UILonghorn managerAdmission and recoveryDashboard proxyOpenSearch DashboardsOpenSearchFluent BitOpenTelemetryData PrepperJenkinsBuild agentsHermes AgentModel gategpt-oss:20bFallback modelHarbor portalHarbor coreJob serviceOCI registryRedisGitea webGitea SSHSource controllerKustomize controllerHelm controllerImage reflectorImage automationNotification controllerWebhook receiverWeave GitOpsFlux deliveryPlatform workloadsShared PostgreSQLPlatform servicesGiteaOIDCOpenSearch DashboardsAccess proxyLonghornAdmin proxyGrafanaOIDCSonarQubeAdmin and developer proxyKeycloak consoleRealm adminVaultAdmin OIDCWeave GitOpsOIDCGiteaatlas realmHarbor UIOIDCHermes AgentOIDCJenkinsOIDClogs.bstein.devlonghorn.bstein.devmetrics.bstein.devalerts.bstein.devquality.bstein.devsso.bstein.devsecret.bstein.devcd.bstein.devscm.bstein.devregistry.bstein.devagent.bstein.devci.bstein.devWallet RPCP2PoolMonerodVaultwardenOutlineRedisPlankaNextcloudCollaboraMail syncMaintenance jobMail webMail protocolsAdminDovecotPostfixRspamdClamAVTika and oletoolsRedisPegasusJellyfinHermes ChatWgerAccount syncAdmin syncWolf access proxyWolf managerWolf APIWolfGatekeeperMoonlightActual BudgetFireflyAccount syncImport jobFlux deliveryPersonal workloadsShared PostgreSQLPersonal servicesJellyfinLDAPNextcloudOIDCOutlineOIDCPlankaOIDCActual BudgetOpenIDFireflySynced accountWolfAccess proxyWgerSynced accountHermes ChatOIDCstream.bstein.devpegasus.bstein.devmail.bstein.devcloud.bstein.devoffice.bstein.devnotes.bstein.devtasks.bstein.devvault.bstein.devmonero.bstein.devbudget.bstein.devmoney.bstein.devwolf.bstein.devmoonlight.bstein.devhealth.bstein.devchat.bstein.devElement WebElement CallMatrix discoveryGuest registrationMatrix auth serviceSynapseSynapse replicationRedisLiveKit token serviceLiveKitCoturnAtlasbotCassandra UIAPIPostgreSQLGeneratorSimulation jobsRetention jobArtifactsPortalChat gatewayBackendFlux deliveryApplication workloadsShared PostgreSQLPortal and MatrixCassandraOIDCPortal APIOIDC tokenPortal ChatOIDCElement WebOIDC through MASMatrixOIDC through MASbstein.devchat.ai.bstein.devcassandra.bstein.devlive.bstein.devmatrix.live.bstein.devcall.live.bstein.devkit.live.bstein.devturn.live.bstein.devBlueDomain to identityGreenIdentity to serviceGoldDirect accessPurpleIdentity controlVioletData flowTealTelemetryOrangeDelivery and controlGrayInternal flowDNS nameOIDC accessAccess proxyLDAP or synced accountEntry serviceInternal serviceData serviceJob or workerOutside KubernetesHTTPSHTTPSHTTPSHTTPSHTTPSMatrix APIHTTPSHTTPS and WebRTCTURNHTTPSHTTPSHTTPSStreamingHTTPSHTTPSHTTPSHTTPSHTTPSMail protocolsHTTPSWOPIHTTPSHTTPSHTTPS and local authRPCHTTPSHTTPSHTTPSSSHHTTPSOCIHTTPSHTTPSHTTPSHTTPSHTTPSHTTPSHTTPSHTTPSHTTPSSCM webhookFlux webhookClone and fetchQuality scanImages and artifactsDesired stateImage metadataManifest updateMail delivery \ No newline at end of file diff --git a/mermaid/TestAutomation.mmd b/mermaid/TestAutomation.mmd new file mode 100644 index 000000000..2d6feaf2d --- /dev/null +++ b/mermaid/TestAutomation.mmd @@ -0,0 +1,213 @@ +%% Automatic test failure triage and response. +%% Hermes reads and recommends. Ariadne validates and performs every write. +%% Relationships carry the detail; node text stays concise. +%%{init: {"flowchart": {"defaultRenderer": "elk", "curve": "stepAfter", "nodeSpacing": 32, "rankSpacing": 48, "useMaxWidth": false}, "elk": {"mergeEdges": true, "nodePlacementStrategy": "LINEAR_SEGMENTS", "forceNodeModelOrder": true, "considerModelOrder": "NODES_AND_EDGES"}, "themeVariables": {"background": "#000000"}, "themeCSS": "& { background-color: #000000 !important; }"}}%% +flowchart TD + + subgraph system["Hermes Test Failure Triage"] + direction TB + + subgraph main_row["Main flow"] + direction TB + + subgraph upper_flow["Evidence and analysis"] + direction LR + + subgraph reference["Legend"] + direction TB + + key_build["BlueBuild and validation"]:::build + key_evidence["GreenEvidence"]:::evidence + key_ariadne["TealAriadne orchestration"]:::ariadne + key_hermes["PurpleHermes"]:::hermes + key_policy["GoldPolicy and action"]:::policy + key_human["RedHuman required"]:::human + key_limit["Dashed grayCurrent boundary"]:::limited + end + + subgraph intake["Detect and gather"] + direction TB + + detector["Jenkins detectorAllowlisted jobsTerminal failures only"]:::ariadne + evidence_sources["Evidence sourcesJenkins and OpenSearchMetrics, Kubernetes, FluxGitea and Grafana"]:::evidence + collector["Console readerFull console2 MB cap"]:::ariadne + failure_ranker["Failure rankerStrong evidence firstTool output alone is neutral"]:::ariadne + context_filter["Context filterPassing quotes removedRepeats and overlaps merged"]:::ariadne + bundle["Incident bundleFailures, logs, metricsHealth, revisions, links"]:::evidence + + detector --> evidence_sources + evidence_sources --> collector + collector --> failure_ranker + failure_ranker --> context_filter + context_filter --> bundle + end + + subgraph hermes_plane["Hermes analysis"] + direction TB + + hermes_access["Read-only accessJenkins, metrics, KubernetesFlux, Gitea, GrafanaInvestigation by incident ID"]:::hermes + model_gate["Model gateopenai-codex/gpt-5.6-terralocal gpt-oss:20b fallback"]:::model + skills["Triage skillsJenkins evidenceQuality and cluster healthFlux and Git correlation"]:::skill + recommendation["Structured recommendationClassification and confidenceSourced factsAction request or patch data"]:::hermes + tool_stream["Agent event streamEvidence and tool calls"]:::audit + + hermes_access --> skills + model_gate -.-> skills + skills --> recommendation + hermes_access -.-> tool_stream + end + end + + subgraph lower_flow["Policy and response"] + direction LR + + subgraph controls["Ariadne policy gates"] + direction TB + + response_check["Response checkSchema, incident, sourcesConfidence and action"]:::policy + repair_guard["Scoped repair guardClassification and actionmust match the owning job"]:::policy + marker_check["Transient marker checkDNS, connection, TLSimage pull, upstream 5xxDisk full is excluded"]:::policy + authorizer["Action authorizerAllowlist, evidence, confidenceOne action, kill switch"]:::policy + + response_check -->|scoped repair| repair_guard + repair_guard --> authorizer + response_check -->|transient claim| marker_check + marker_check -->|marker confirmed| authorizer + response_check -->|other result| authorizer + end + + subgraph response["Ariadne response"] + direction LR + + subgraph response_paths["Response paths"] + direction TB + + route{"Policy result"}:::decision + + subgraph immediate_paths["Action or escalation"] + direction LR + + subgraph operational_path["Allowlisted action"] + direction TB + + registry["Action registry"]:::policy + repair_fixture["Scoped ConfigMap repairIn-process patchNo pod created"]:::action + retry_infra["Transient retryOne Jenkins rebuildNo cluster write"]:::action + operational_result["Action resultOne attemptOne validation build"]:::action + + registry --> repair_fixture + registry --> retry_infra + repair_fixture --> operational_result + retry_infra --> operational_result + end + + subgraph escalation_path["Human-required response"] + direction TB + + human_required["Diagnosis and next checksIncident stays human required"]:::human + gitea_issue["Ariadne opens an issueEvidence and suggested fix"]:::human + + human_required --> gitea_issue + end + end + + route -->|authorized action| registry + route -->|human required| human_required + operational_result -->|action failed| human_required + end + + subgraph code_path["Optional source proposal"] + direction TB + + subgraph proposal_stage["Prepare and check"] + direction TB + + duplicate_guard["Open proposal checkExisting repair branch"]:::policy + candidate_files["Candidate filesPath and line hintsRead failing test"]:::evidence + source_target["Patch targetFollow test importsTests remain read only"]:::policy + patch_proposal["Hermes patch dataPath, anchor, replacementReason"]:::hermes + patch_validator["Patch validatorAllowed path and branch20 lines, 4 KBExact anchor"]:::policy + + duplicate_guard --> candidate_files + candidate_files --> source_target + source_target --> patch_proposal + patch_proposal --> patch_validator + end + + subgraph pr_stage["Deliver for review"] + direction TB + + gitea_pr["Ariadne opens a pull requesthermes-repair branchAriadne holds the token"]:::git + branch_build["Branch validationConfigured repositories only"]:::limited + human_merge["Human review and mergeNo automatic merge"]:::human + flux_delivery["Flux deliveryAfter human merge"]:::git + + gitea_pr -.->|where configured| branch_build + branch_build --> human_merge + gitea_pr -->|otherwise| human_merge + human_merge --> flux_delivery + end + + patch_validator -->|validated patch| gitea_pr + end + + response_paths -.->|eligible source defect| code_path + end + + subgraph outputs["Inspectable outputs"] + direction TB + + output_entry["Ariadne records every outcome"]:::audit + audit_events["Audit eventsIncident, diagnosis, actionPatch proposal and agent IDs"]:::audit + metrics_output["Triage metricsVictoriaMetrics and Grafana"]:::metrics + alert_output["Narrow alertsFailed repairEscalation untouched for six hours"]:::metrics + issue_output["Gitea issueHuman-required incidentWritten by Ariadne"]:::git + pr_output["Gitea pull requestSource proposalWritten by Ariadne"]:::git + + output_entry --> audit_events + output_entry --> metrics_output + metrics_output --> alert_output + end + end + + reference ~~~ intake + intake ==>|incident bundle| hermes_plane + controls ==>|policy result| response + response ==>|records and artifacts| outputs + upper_flow ==>|recommendation| lower_flow + end + + end + + classDef build fill:#16324f,stroke:#6cb6ff,color:#ffffff + classDef evidence fill:#173f2b,stroke:#61d095,color:#ffffff + classDef ariadne fill:#24414a,stroke:#69c5d1,color:#ffffff + classDef hermes fill:#3c3155,stroke:#c1a7ff,color:#ffffff + classDef skill fill:#42345b,stroke:#c1a7ff,color:#ffffff + classDef model fill:#342b4f,stroke:#a78bfa,color:#ffffff + classDef policy fill:#3d3525,stroke:#e4bd55,color:#ffffff + classDef decision fill:#47391c,stroke:#e4bd55,color:#ffffff,stroke-width:3px + classDef action fill:#4a3b16,stroke:#e4bd55,color:#ffffff + classDef human fill:#4a2428,stroke:#ff6b78,color:#ffffff + classDef git fill:#253f35,stroke:#78c89a,color:#ffffff + classDef metrics fill:#243750,stroke:#65a9e8,color:#ffffff + classDef audit fill:#353125,stroke:#d9b55b,color:#ffffff + classDef limited fill:#1f2227,stroke:#9ba4b1,color:#c4c9d1,stroke-width:2px,stroke-dasharray:8 6 + + style system fill:#030303,stroke:#6b7280,stroke-width:3px + style main_row fill:#050607,stroke:#6b7280,stroke-width:2px + style upper_flow fill:#050607,stroke:#61d095,stroke-width:2px + style lower_flow fill:#070605,stroke:#e4bd55,stroke-width:2px + style reference fill:#07090c,stroke:#9ba4b1,stroke-width:2px + style intake fill:#070d09,stroke:#61d095,stroke-width:2px + style hermes_plane fill:#0c0912,stroke:#c1a7ff,stroke-width:3px + style controls fill:#0d0b07,stroke:#e4bd55,stroke-width:2px + style response fill:#090806,stroke:#e4bd55,stroke-width:3px + style response_paths fill:#070707,stroke:#6b7280,stroke-width:1px + style immediate_paths fill:#080706,stroke:#8b8170,stroke-width:1px + style operational_path fill:#0d0b07,stroke:#e4bd55,stroke-width:2px + style escalation_path fill:#0d090a,stroke:#ff6b78,stroke-width:2px + style code_path fill:#0b090d,stroke:#c1a7ff,stroke-width:2px + style proposal_stage fill:#09080b,stroke:#9f86da,stroke-width:1px + style pr_stage fill:#07100a,stroke:#78c89a,stroke-width:1px + style outputs fill:#07100d,stroke:#78c89a,stroke-width:2px diff --git a/mermaid/TestAutomation.svg b/mermaid/TestAutomation.svg new file mode 100644 index 000000000..c091556cd --- /dev/null +++ b/mermaid/TestAutomation.svg @@ -0,0 +1,67 @@ +Hermes Test Failure TriageMain flowPolicy and responseEvidence and analysisInspectable outputsAriadne responseAriadne policy gatesHermes analysisDetect and gatherLegendOptional source proposalResponse pathsDeliver for reviewPrepare and checkAction or escalationHuman-required responseAllowlisted actionAriadne records every outcomeAudit eventsIncident, diagnosis, actionPatch proposal and agent IDsTriage metricsVictoriaMetrics and GrafanaNarrow alertsFailed repairEscalation untouched for six hoursGitea issueHuman-required incidentWritten by AriadneGitea pull requestSource proposalWritten by AriadneAriadne opens a pull requesthermes-repair branchAriadne holds the tokenBranch validationConfigured repositories onlyHuman review and mergeNo automatic mergeFlux deliveryAfter human mergeOpen proposal checkExisting repair branchCandidate filesPath and line hintsRead failing testPatch targetFollow test importsTests remain read onlyHermes patch dataPath, anchor, replacementReasonPatch validatorAllowed path and branch20 lines, 4 KBExact anchorDiagnosis and next checksIncident stays human requiredAriadne opens an issueEvidence and suggested fixAction registryScoped ConfigMap repairIn-process patchNo pod createdTransient retryOne Jenkins rebuildNo cluster writeAction resultOne attemptOne validation buildPolicy resultResponse checkSchema, incident, sourcesConfidence and actionScoped repair guardClassification and actionmust match the owning jobTransient marker checkDNS, connection, TLSimage pull, upstream 5xxDisk full is excludedAction authorizerAllowlist, evidence, confidenceOne action, kill switchRead-only accessJenkins, metrics, KubernetesFlux, Gitea, GrafanaInvestigation by incident IDModel gateopenai-codex/gpt-5.6-terralocal gpt-oss:20b fallbackTriage skillsJenkins evidenceQuality and cluster healthFlux and Git correlationStructured recommendationClassification and confidenceSourced factsAction request or patch dataAgent event streamEvidence and tool callsJenkins detectorAllowlisted jobsTerminal failures onlyEvidence sourcesJenkins and OpenSearchMetrics, Kubernetes, FluxGitea and GrafanaConsole readerFull console2 MB capFailure rankerStrong evidence firstTool output alone is neutralContext filterPassing quotes removedRepeats and overlaps mergedIncident bundleFailures, logs, metricsHealth, revisions, linksBlueBuild and validationGreenEvidenceTealAriadne orchestrationPurpleHermesGoldPolicy and actionRedHuman requiredDashed grayCurrent boundaryscoped repairtransient claimmarker confirmedother resultauthorized actionhuman requiredaction failedwhere configuredotherwisevalidated patcheligible source defectincident bundlepolicy resultrecords and artifactsrecommendation \ No newline at end of file
Titan Lab
Power and enclosure
Lab systems outside the Atlas cluster
Atlas Kubernetes cluster
Network fabric
Link colors
Enclosure cooling
UPS protection
Boards awaiting replacement
Support and host-level services
Cluster telemetry
Virtual resource pools
Workers
High-availability control plane, ARM64
Operations
Resources
Network
Statera
Pyrphoros
titan-jh
titan-db
Kubernetes GPU pool
Longhorn storage classes
Accelerators and high-capacity workers
Older workers, ARM64 Raspberry Pi 4
Newer workers, ARM64 Raspberry Pi 5
titan-0c
titan-0b
titan-0a
x86_64 systems
ARM64 NVIDIA Jetson
titan-24, Tethys
titan-23, Oceanus
titan-22
titan-21
titan-20
titan-19
titan-18
titan-17
titan-15
titan-14
titan-13
titan-12
titan-11
titan-08
titan-07
titan-06
titan-05
titan-04
Filtered equipment tentAC-cooled intakeControlled exhaust
AC Infinity controllerTemperatureHumidityPressure
Controlled intakeand exhaust fans
CyberPower1500PFCLCD
Protected loadsTRENDnet switchtitan-23, titan-24, titan-jh
CyberPower850 VA UPS
Protected loadsRouter and Cisco switchControl plane and Pi workersJetsons, titan-22, titan-dbCooling equipment
titan-09Raspberry Pi 5
titan-10Raspberry Pi 5
titan-16Raspberry Pi 4
Raspberry Pi 58 GiB RAMArch Linux ARMJump host
Local256 GiB boot SSD
LesavkaRemote control for Tethys
Raspberry Pi 58 GiB RAMUbuntu 24.04
Local500 GiB boot SSD
PostgreSQLHA control-plane database
NUT and AnankeHost servicesAutomatic recovery
NUT and Ananke on titan-24Host services outside KubernetesUPS telemetry and safe shutdown
TyphonKubernetes workload
VictoriaMetrics
Grafana
NVIDIA ARM64titan-20 and titan-21
NVIDIA x86_64titan-22 and titan-24
Astreae4 x 8 TiB32 TiB
Asteria4 x 12 TiB48 TiB
Ryzen 9 3900X24 threads, 64 GiB RAMDebian 13
GPUNVIDIA RTX 3080
Local500 GiB disk
Local500 GiB home500 GiB temporary
EPYC 74F324 cores, 48 threads256 GiB RAMDebian 13
ASPEED graphicsNot pooled
Local1 TiB disk
Local4 TiB Veles4 TiB SUI
X830 mini PCCore i9-12900H32 GiB RAMDebian 13
GPUNVIDIA RTX 3050 Ti
Intel Iris XeNot pooled
Jetson Xavier NX16 GiB RAMUbuntu 20.04Accelerator
GPUNVIDIA Xavier
Local256 GiB disk
Raspberry Pi 48 GiB RAMArmbian
LocalSD root
Longhorn8 TiB Astreae
Longhorn12 TiB Asteria
LocalSD root64 GiB astraios
ASUS RT-AX88URouter
Cisco CBS110-24T1 Gbps switch
TRENDnet 9-port2.5 Gbps switch
Power and NUT
Telemetry and environment
Administration and recovery
Protective shutdown
Local attachment
Shared storage
GPU
1 Gbps
2.5 Gbps
External network
AC Infinity account
Internet
environment metrics
HA PostgreSQL
administration
remote control
same physical host
NUT
power metrics
database and cluster recovery
low-battery shutdown
environment data
Atlas Service Access Architecture
Host and Physical Systems
Shared Cluster Services
Platform Services
Personal Services
Applications and Communications
Legend
Additional Telemetry
maintenance
Shared State and Models
Ingress and Networking
Cluster Services
Keycloak Access
Domains
atlas realm and directory access
Links
Nodes
Identity and Security
Delivery and Automation
cassandra realm client
atlas realm operations
atlas realm delivery
Delivery
Mail and Productivity
Accounts, Health, and Media
Media and Productivity
Accounts
Accounts and Health
comms
cassandra
bstein-dev-home
cassandra realm
atlas realm
vault
sso
quality
monitoring
longhorn-system
logging
jenkins
hermes
harbor
gitea
flux-system
crypto
vaultwarden
Notes and Tasks
nextcloud
mailu-mailserver
jellyfin
hermes-chat
health
game-stream
finance
Ananketitan-db and titan-24
Pyrphoros UPS
Statera UPS
AC InfinityController and cloud
TyphonTent climate
SUI metrics
Ariadne
Metis proxy
Metis
Soteria proxy
Soteria
Node operations
Repair and migration jobs
Shared PostgreSQLApplication and platform databases
OllamaLocal model service
Zot access proxy
MetalLBService addresses
TraefikLoad balancer
TraefikTLS and routing
cert-manager
Certificate webhooks
Vault
Vault cluster service
Secret injector
Configuration jobs
Shared access proxy
Keycloak
OpenLDAP
Realm bootstrap and checks
SonarQube proxy
SonarQube
Quality exporter
Cluster and node exporters
GPU exporters
Quality gateway
Postmark exporter
vmalert
Alertmanager
Longhorn proxy
Longhorn UI
Longhorn manager
Admission and recovery
Dashboard proxy
OpenSearch Dashboards
OpenSearch
Fluent Bit
OpenTelemetry
Data Prepper
Jenkins
Build agents
Hermes Agent
Model gate
gpt-oss:20bFallback model
Harbor portal
Harbor core
Job service
OCI registry
Redis
Gitea web
Gitea SSH
Source controller
Kustomize controller
Helm controller
Image reflector
Image automation
Notification controller
Webhook receiver
Weave GitOps
Flux deliveryPlatform workloads
Shared PostgreSQLPlatform services
GiteaOIDC
OpenSearch DashboardsAccess proxy
LonghornAdmin proxy
GrafanaOIDC
SonarQubeAdmin and developer proxy
Keycloak consoleRealm admin
VaultAdmin OIDC
Weave GitOpsOIDC
Giteaatlas realm
Harbor UIOIDC
Hermes AgentOIDC
JenkinsOIDC
logs.bstein.dev
longhorn.bstein.dev
metrics.bstein.dev
alerts.bstein.dev
quality.bstein.dev
sso.bstein.dev
secret.bstein.dev
cd.bstein.dev
scm.bstein.dev
registry.bstein.dev
agent.bstein.dev
ci.bstein.dev
Wallet RPC
P2Pool
Monerod
Vaultwarden
Outline
Planka
Nextcloud
Collabora
Mail sync
Maintenance job
Mail web
Mail protocols
Admin
Dovecot
Postfix
Rspamd
ClamAV
Tika and oletools
Pegasus
Jellyfin
Hermes Chat
Wger
Account sync
Admin sync
Wolf access proxy
Wolf manager
Wolf API
Wolf
Gatekeeper
Moonlight
Actual Budget
Firefly
Import job
Flux deliveryPersonal workloads
Shared PostgreSQLPersonal services
JellyfinLDAP
NextcloudOIDC
OutlineOIDC
PlankaOIDC
Actual BudgetOpenID
FireflySynced account
WolfAccess proxy
WgerSynced account
Hermes ChatOIDC
stream.bstein.dev
pegasus.bstein.dev
mail.bstein.dev
cloud.bstein.dev
office.bstein.dev
notes.bstein.dev
tasks.bstein.dev
vault.bstein.dev
monero.bstein.dev
budget.bstein.dev
money.bstein.dev
wolf.bstein.dev
moonlight.bstein.dev
health.bstein.dev
chat.bstein.dev
Element Web
Element Call
Matrix discovery
Guest registration
Matrix auth service
Synapse
Synapse replication
LiveKit token service
LiveKit
Coturn
Atlasbot
Cassandra UI
API
PostgreSQL
Generator
Simulation jobs
Retention job
Artifacts
Portal
Chat gateway
Backend
Flux deliveryApplication workloads
Shared PostgreSQLPortal and Matrix
CassandraOIDC
Portal APIOIDC token
Portal ChatOIDC
Element WebOIDC through MAS
MatrixOIDC through MAS
bstein.dev
chat.ai.bstein.dev
cassandra.bstein.dev
live.bstein.dev
matrix.live.bstein.dev
call.live.bstein.dev
kit.live.bstein.dev
turn.live.bstein.dev
BlueDomain to identity
GreenIdentity to service
GoldDirect access
PurpleIdentity control
VioletData flow
TealTelemetry
OrangeDelivery and control
GrayInternal flow
DNS name
OIDC access
Access proxy
LDAP or synced account
Entry service
Internal service
Data service
Job or worker
Outside Kubernetes
HTTPS
Matrix API
HTTPS and WebRTC
TURN
Streaming
WOPI
HTTPS and local auth
RPC
SSH
OCI
SCM webhook
Flux webhook
Clone and fetch
Quality scan
Images and artifacts
Desired state
Image metadata
Manifest update
Mail delivery
Hermes Test Failure Triage
Main flow
Policy and response
Evidence and analysis
Inspectable outputs
Ariadne response
Ariadne policy gates
Hermes analysis
Detect and gather
Optional source proposal
Response paths
Deliver for review
Prepare and check
Action or escalation
Human-required response
Allowlisted action
Ariadne records every outcome
Audit eventsIncident, diagnosis, actionPatch proposal and agent IDs
Triage metricsVictoriaMetrics and Grafana
Narrow alertsFailed repairEscalation untouched for six hours
Gitea issueHuman-required incidentWritten by Ariadne
Gitea pull requestSource proposalWritten by Ariadne
Ariadne opens a pull requesthermes-repair branchAriadne holds the token
Branch validationConfigured repositories only
Human review and mergeNo automatic merge
Flux deliveryAfter human merge
Open proposal checkExisting repair branch
Candidate filesPath and line hintsRead failing test
Patch targetFollow test importsTests remain read only
Hermes patch dataPath, anchor, replacementReason
Patch validatorAllowed path and branch20 lines, 4 KBExact anchor
Diagnosis and next checksIncident stays human required
Ariadne opens an issueEvidence and suggested fix
Action registry
Scoped ConfigMap repairIn-process patchNo pod created
Transient retryOne Jenkins rebuildNo cluster write
Action resultOne attemptOne validation build
Policy result
Response checkSchema, incident, sourcesConfidence and action
Scoped repair guardClassification and actionmust match the owning job
Transient marker checkDNS, connection, TLSimage pull, upstream 5xxDisk full is excluded
Action authorizerAllowlist, evidence, confidenceOne action, kill switch
Read-only accessJenkins, metrics, KubernetesFlux, Gitea, GrafanaInvestigation by incident ID
Model gateopenai-codex/gpt-5.6-terralocal gpt-oss:20b fallback
Triage skillsJenkins evidenceQuality and cluster healthFlux and Git correlation
Structured recommendationClassification and confidenceSourced factsAction request or patch data
Agent event streamEvidence and tool calls
Jenkins detectorAllowlisted jobsTerminal failures only
Evidence sourcesJenkins and OpenSearchMetrics, Kubernetes, FluxGitea and Grafana
Console readerFull console2 MB cap
Failure rankerStrong evidence firstTool output alone is neutral
Context filterPassing quotes removedRepeats and overlaps merged
Incident bundleFailures, logs, metricsHealth, revisions, links
BlueBuild and validation
GreenEvidence
TealAriadne orchestration
PurpleHermes
GoldPolicy and action
RedHuman required
Dashed grayCurrent boundary
scoped repair
transient claim
marker confirmed
other result
authorized action
human required
action failed
where configured
otherwise
validated patch
eligible source defect
incident bundle
policy result
records and artifacts
recommendation