From 6c0be8563ddb621e551c1c90a65195a53f2b985a Mon Sep 17 00:00:00 2001 From: Andrew Stoltz Date: Tue, 16 Jun 2026 22:24:23 -0500 Subject: [PATCH] gx10-gitops: capture live manifests for 32 product namespaces (ArgoCD adoption source) --- .../certificate-aistation-web-tls.json | 18 + .../configmap-aistation-web-config.json | 29 ++ .../deployment-aistation-web.json | 111 ++++++ .../ingressroute-aistation-web.json | 28 ++ .../fc-aistation/service-aistation-web.json | 28 ++ .../fc-chat/configmap-chat-web-config.json | 54 +++ apps-gx10/fc-chat/deployment-chat-web.json | 159 +++++++++ .../fc-chat/ingressroute-chat-web-public.json | 29 ++ apps-gx10/fc-chat/ingressroute-chat-web.json | 29 ++ apps-gx10/fc-chat/service-chat-web.json | 28 ++ .../certificate-remotedesktop-tls.json | 18 + .../deployment-remotedesktop-operator.json | 93 +++++ .../deployment-remotedesktop-web.json | 299 ++++++++++++++++ .../ingressroute-remotedesktop-web.json | 29 ++ .../fc-desktop/service-remotedesktop-web.json | 24 ++ ...serviceaccount-remotedesktop-operator.json | 8 + .../serviceaccount-remotedesktop-web.json | 8 + .../deployment-fc-devicemgmt-operator.json | 183 ++++++++++ .../deployment-fc-devicemgmt-web.json | 211 ++++++++++++ .../ingressroute-devicemgmt.json | 28 ++ .../service-fc-devicemgmt-web.json | 33 ++ ...serviceaccount-fc-devicemgmt-operator.json | 16 + .../deployment-fc-distribution.json | 265 ++++++++++++++ .../ingressroute-fc-distribution-public.json | 29 ++ .../ingressroute-fc-distribution.json | 29 ++ .../service-fc-distribution.json | 28 ++ .../fc-dms/configmap-dms-web-config.json | 28 ++ apps-gx10/fc-dms/deployment-dms-web.json | 169 +++++++++ apps-gx10/fc-dms/ingressroute-dms-web.json | 29 ++ apps-gx10/fc-dms/service-dms-web.json | 34 ++ .../configmap-library-web-config.json | 20 ++ .../fc-library/deployment-library-web.json | 110 ++++++ .../fc-library/ingressroute-library-web.json | 29 ++ apps-gx10/fc-library/service-library-web.json | 29 ++ .../deployment-fc-llm-bridge.json | 292 ++++++++++++++++ .../ingressroute-fc-llm-bridge.json | 29 ++ .../fc-llm-bridge/service-fc-llm-bridge.json | 25 ++ .../fc-media/configmap-fc-media-config.json | 11 + .../fc-media/deployment-fc-media-web.json | 242 +++++++++++++ .../fc-media/ingressroute-fc-media-web.json | 29 ++ apps-gx10/fc-media/service-fc-media-web.json | 29 ++ .../configmap-menuboard-web-config.json | 18 + .../deployment-menuboard-web.json | 112 ++++++ .../ingressroute-menuboard-web.json | 29 ++ .../fc-menuboard/service-menuboard-web.json | 28 ++ .../configmap-messageboard-web-config.json | 18 + .../deployment-messageboard-web.json | 118 +++++++ .../ingressroute-messageboard-web.json | 29 ++ .../service-messageboard-web.json | 25 ++ .../fc-mysql/configmap-mysql-web-config.json | 11 + apps-gx10/fc-mysql/deployment-mysql-web.json | 209 +++++++++++ .../fc-mysql/ingressroute-mysql-web.json | 29 ++ apps-gx10/fc-mysql/service-mysql-web.json | 23 ++ .../fc-mysql/serviceaccount-mysql-web.json | 8 + .../certificate-fc-network-web-tls.json | 18 + .../fc-network/deployment-fc-network-web.json | 210 +++++++++++ .../ingressroute-fc-network-web.json | 29 ++ .../fc-network/service-fc-network-web.json | 33 ++ .../fc-php/configmap-php-web-config.json | 11 + apps-gx10/fc-php/deployment-php-web.json | 209 +++++++++++ apps-gx10/fc-php/service-php-web.json | 23 ++ apps-gx10/fc-php/serviceaccount-php-web.json | 8 + .../configmap-presentations-web-config.json | 22 ++ .../deployment-presentations-web.json | 143 ++++++++ .../ingressroute-presentations-web.json | 29 ++ .../service-presentations-web.json | 28 ++ .../configmap-retail-web-config.json | 20 ++ .../fc-retail/deployment-retail-web.json | 111 ++++++ .../fc-retail/ingressroute-retail-web.json | 29 ++ apps-gx10/fc-retail/service-retail-web.json | 29 ++ .../configmap-scoreboard-web-config.json | 21 ++ .../deployment-scoreboard-web.json | 132 +++++++ .../ingressroute-scoreboard-web.json | 29 ++ .../fc-scoreboard/service-scoreboard-web.json | 28 ++ .../configmap-segmentdisplay-web-config.json | 19 + .../deployment-segmentdisplay-web.json | 113 ++++++ .../ingressroute-segmentdisplay-web.json | 29 ++ .../service-segmentdisplay-web.json | 28 ++ .../deployment-signage-replay-web.json | 151 ++++++++ .../fc-signage/deployment-signage-web.json | 230 ++++++++++++ .../ingressroute-signage-replay-web.json | 29 ++ .../fc-signage/ingressroute-signage-web.json | 29 ++ .../service-signage-replay-web.json | 24 ++ apps-gx10/fc-signage/service-signage-web.json | 24 ++ .../deployment-signalcontrol-web.json | 133 +++++++ .../ingressroute-signalcontrol-web.json | 29 ++ .../service-signalcontrol-web.json | 28 ++ .../fc-system/configmap-fc-landing-html.json | 11 + .../configmap-fc-landing-nginx-conf.json | 11 + .../fc-system/configmap-kiosk-web-config.json | 11 + .../fc-system/deployment-fc-landing.json | 119 +++++++ apps-gx10/fc-system/deployment-kiosk-web.json | 275 +++++++++++++++ .../fc-system/deployment-mysql-operator.json | 117 +++++++ .../fc-system/deployment-php-operator.json | 134 +++++++ .../ingressroute-fc-landing-public.json | 29 ++ .../fc-system/ingressroute-kiosk-web.json | 29 ++ apps-gx10/fc-system/service-fc-landing.json | 27 ++ apps-gx10/fc-system/service-kiosk-web.json | 34 ++ .../serviceaccount-mysql-operator.json | 15 + .../serviceaccount-php-operator.json | 15 + .../configmap-andrew-web-html.json | 11 + .../configmap-andrew-web-nginx-conf.json | 11 + .../deployment-andrew-web.json | 119 +++++++ .../ingressroute-andrew-web.json | 29 ++ .../fc-tenant-andrew/service-andrew-web.json | 24 ++ .../configmap-dustin-web-html.json | 11 + .../configmap-dustin-web-nginx-conf.json | 11 + .../deployment-dustin-web.json | 119 +++++++ .../ingressroute-dustin-web.json | 29 ++ .../fc-tenant-dustin/service-dustin-web.json | 24 ++ .../configmap-erik-web-html.json | 11 + .../configmap-erik-web-nginx-conf.json | 11 + .../fc-tenant-erik/deployment-erik-web.json | 119 +++++++ .../fc-tenant-erik/ingressroute-erik-web.json | 29 ++ .../fc-tenant-erik/service-erik-web.json | 24 ++ .../fc-tenant-fit/configmap-fit-web-html.json | 11 + .../configmap-fit-web-nginx-conf.json | 11 + .../fc-tenant-fit/deployment-fit-web.json | 119 +++++++ .../fc-tenant-fit/ingressroute-fit-web.json | 29 ++ apps-gx10/fc-tenant-fit/service-fit-web.json | 24 ++ .../configmap-matt-web-html.json | 11 + .../configmap-matt-web-nginx-conf.json | 11 + .../fc-tenant-matt/deployment-matt-web.json | 119 +++++++ .../fc-tenant-matt/ingressroute-matt-web.json | 29 ++ .../fc-tenant-matt/service-matt-web.json | 24 ++ .../deployment-ttsreader-web.json | 293 ++++++++++++++++ .../ingressroute-ttsreader-web.json | 29 ++ .../fc-ttsreader/service-ttsreader-web.json | 25 ++ .../deployment-updatecenter-web.json | 273 +++++++++++++++ .../ingressroute-updatecenter-web-gx10.json | 29 ++ ...sroute-updatecenter-web-internal-gx10.json | 29 ++ ...essroute-updatecenter-web-public-gx10.json | 29 ++ .../fc-updater/service-updatecenter-web.json | 29 ++ .../deployment-worldbuilder-web.json | 214 ++++++++++++ .../ingressroute-worldbuilder-web.json | 29 ++ .../service-worldbuilder-web.json | 32 ++ .../intranet/configmap-intranet-config.json | 12 + .../intranet/deployment-intranet-web.json | 160 +++++++++ .../intranet/ingressroute-intranet-web.json | 29 ++ apps-gx10/intranet/service-intranet-web.json | 25 ++ .../certificate-yealink-provision-tls.json | 18 + .../telephony/configmap-asterisk-config.json | 17 + .../telephony/configmap-telephony-config.json | 11 + .../configmap-yealink-provisioning.json | 18 + apps-gx10/telephony/deployment-asterisk.json | 326 ++++++++++++++++++ .../telephony/deployment-telephony-web.json | 259 ++++++++++++++ .../deployment-yealink-provision.json | 100 ++++++ .../ingressroute-telephony-web-gx10.json | 40 +++ ...ressroute-telephony-web-internal-gx10.json | 29 ++ .../ingressroute-yealink-provision.json | 29 ++ apps-gx10/telephony/service-asterisk-ari.json | 24 ++ apps-gx10/telephony/service-asterisk-sip.json | 259 ++++++++++++++ .../telephony/service-telephony-web.json | 25 ++ .../telephony/service-yealink-provision.json | 27 ++ apps-gx10/tts/deployment-gx10-tts.json | 106 ++++++ apps-gx10/tts/service-gx10-tts.json | 29 ++ 156 files changed, 9955 insertions(+) create mode 100644 apps-gx10/fc-aistation/certificate-aistation-web-tls.json create mode 100644 apps-gx10/fc-aistation/configmap-aistation-web-config.json create mode 100644 apps-gx10/fc-aistation/deployment-aistation-web.json create mode 100644 apps-gx10/fc-aistation/ingressroute-aistation-web.json create mode 100644 apps-gx10/fc-aistation/service-aistation-web.json create mode 100644 apps-gx10/fc-chat/configmap-chat-web-config.json create mode 100644 apps-gx10/fc-chat/deployment-chat-web.json create mode 100644 apps-gx10/fc-chat/ingressroute-chat-web-public.json create mode 100644 apps-gx10/fc-chat/ingressroute-chat-web.json create mode 100644 apps-gx10/fc-chat/service-chat-web.json create mode 100644 apps-gx10/fc-desktop/certificate-remotedesktop-tls.json create mode 100644 apps-gx10/fc-desktop/deployment-remotedesktop-operator.json create mode 100644 apps-gx10/fc-desktop/deployment-remotedesktop-web.json create mode 100644 apps-gx10/fc-desktop/ingressroute-remotedesktop-web.json create mode 100644 apps-gx10/fc-desktop/service-remotedesktop-web.json create mode 100644 apps-gx10/fc-desktop/serviceaccount-remotedesktop-operator.json create mode 100644 apps-gx10/fc-desktop/serviceaccount-remotedesktop-web.json create mode 100644 apps-gx10/fc-devicemgmt/deployment-fc-devicemgmt-operator.json create mode 100644 apps-gx10/fc-devicemgmt/deployment-fc-devicemgmt-web.json create mode 100644 apps-gx10/fc-devicemgmt/ingressroute-devicemgmt.json create mode 100644 apps-gx10/fc-devicemgmt/service-fc-devicemgmt-web.json create mode 100644 apps-gx10/fc-devicemgmt/serviceaccount-fc-devicemgmt-operator.json create mode 100644 apps-gx10/fc-distribution/deployment-fc-distribution.json create mode 100644 apps-gx10/fc-distribution/ingressroute-fc-distribution-public.json create mode 100644 apps-gx10/fc-distribution/ingressroute-fc-distribution.json create mode 100644 apps-gx10/fc-distribution/service-fc-distribution.json create mode 100644 apps-gx10/fc-dms/configmap-dms-web-config.json create mode 100644 apps-gx10/fc-dms/deployment-dms-web.json create mode 100644 apps-gx10/fc-dms/ingressroute-dms-web.json create mode 100644 apps-gx10/fc-dms/service-dms-web.json create mode 100644 apps-gx10/fc-library/configmap-library-web-config.json create mode 100644 apps-gx10/fc-library/deployment-library-web.json create mode 100644 apps-gx10/fc-library/ingressroute-library-web.json create mode 100644 apps-gx10/fc-library/service-library-web.json create mode 100644 apps-gx10/fc-llm-bridge/deployment-fc-llm-bridge.json create mode 100644 apps-gx10/fc-llm-bridge/ingressroute-fc-llm-bridge.json create mode 100644 apps-gx10/fc-llm-bridge/service-fc-llm-bridge.json create mode 100644 apps-gx10/fc-media/configmap-fc-media-config.json create mode 100644 apps-gx10/fc-media/deployment-fc-media-web.json create mode 100644 apps-gx10/fc-media/ingressroute-fc-media-web.json create mode 100644 apps-gx10/fc-media/service-fc-media-web.json create mode 100644 apps-gx10/fc-menuboard/configmap-menuboard-web-config.json create mode 100644 apps-gx10/fc-menuboard/deployment-menuboard-web.json create mode 100644 apps-gx10/fc-menuboard/ingressroute-menuboard-web.json create mode 100644 apps-gx10/fc-menuboard/service-menuboard-web.json create mode 100644 apps-gx10/fc-messageboard/configmap-messageboard-web-config.json create mode 100644 apps-gx10/fc-messageboard/deployment-messageboard-web.json create mode 100644 apps-gx10/fc-messageboard/ingressroute-messageboard-web.json create mode 100644 apps-gx10/fc-messageboard/service-messageboard-web.json create mode 100644 apps-gx10/fc-mysql/configmap-mysql-web-config.json create mode 100644 apps-gx10/fc-mysql/deployment-mysql-web.json create mode 100644 apps-gx10/fc-mysql/ingressroute-mysql-web.json create mode 100644 apps-gx10/fc-mysql/service-mysql-web.json create mode 100644 apps-gx10/fc-mysql/serviceaccount-mysql-web.json create mode 100644 apps-gx10/fc-network/certificate-fc-network-web-tls.json create mode 100644 apps-gx10/fc-network/deployment-fc-network-web.json create mode 100644 apps-gx10/fc-network/ingressroute-fc-network-web.json create mode 100644 apps-gx10/fc-network/service-fc-network-web.json create mode 100644 apps-gx10/fc-php/configmap-php-web-config.json create mode 100644 apps-gx10/fc-php/deployment-php-web.json create mode 100644 apps-gx10/fc-php/service-php-web.json create mode 100644 apps-gx10/fc-php/serviceaccount-php-web.json create mode 100644 apps-gx10/fc-presentations/configmap-presentations-web-config.json create mode 100644 apps-gx10/fc-presentations/deployment-presentations-web.json create mode 100644 apps-gx10/fc-presentations/ingressroute-presentations-web.json create mode 100644 apps-gx10/fc-presentations/service-presentations-web.json create mode 100644 apps-gx10/fc-retail/configmap-retail-web-config.json create mode 100644 apps-gx10/fc-retail/deployment-retail-web.json create mode 100644 apps-gx10/fc-retail/ingressroute-retail-web.json create mode 100644 apps-gx10/fc-retail/service-retail-web.json create mode 100644 apps-gx10/fc-scoreboard/configmap-scoreboard-web-config.json create mode 100644 apps-gx10/fc-scoreboard/deployment-scoreboard-web.json create mode 100644 apps-gx10/fc-scoreboard/ingressroute-scoreboard-web.json create mode 100644 apps-gx10/fc-scoreboard/service-scoreboard-web.json create mode 100644 apps-gx10/fc-segmentdisplay/configmap-segmentdisplay-web-config.json create mode 100644 apps-gx10/fc-segmentdisplay/deployment-segmentdisplay-web.json create mode 100644 apps-gx10/fc-segmentdisplay/ingressroute-segmentdisplay-web.json create mode 100644 apps-gx10/fc-segmentdisplay/service-segmentdisplay-web.json create mode 100644 apps-gx10/fc-signage/deployment-signage-replay-web.json create mode 100644 apps-gx10/fc-signage/deployment-signage-web.json create mode 100644 apps-gx10/fc-signage/ingressroute-signage-replay-web.json create mode 100644 apps-gx10/fc-signage/ingressroute-signage-web.json create mode 100644 apps-gx10/fc-signage/service-signage-replay-web.json create mode 100644 apps-gx10/fc-signage/service-signage-web.json create mode 100644 apps-gx10/fc-signalcontrol/deployment-signalcontrol-web.json create mode 100644 apps-gx10/fc-signalcontrol/ingressroute-signalcontrol-web.json create mode 100644 apps-gx10/fc-signalcontrol/service-signalcontrol-web.json create mode 100644 apps-gx10/fc-system/configmap-fc-landing-html.json create mode 100644 apps-gx10/fc-system/configmap-fc-landing-nginx-conf.json create mode 100644 apps-gx10/fc-system/configmap-kiosk-web-config.json create mode 100644 apps-gx10/fc-system/deployment-fc-landing.json create mode 100644 apps-gx10/fc-system/deployment-kiosk-web.json create mode 100644 apps-gx10/fc-system/deployment-mysql-operator.json create mode 100644 apps-gx10/fc-system/deployment-php-operator.json create mode 100644 apps-gx10/fc-system/ingressroute-fc-landing-public.json create mode 100644 apps-gx10/fc-system/ingressroute-kiosk-web.json create mode 100644 apps-gx10/fc-system/service-fc-landing.json create mode 100644 apps-gx10/fc-system/service-kiosk-web.json create mode 100644 apps-gx10/fc-system/serviceaccount-mysql-operator.json create mode 100644 apps-gx10/fc-system/serviceaccount-php-operator.json create mode 100644 apps-gx10/fc-tenant-andrew/configmap-andrew-web-html.json create mode 100644 apps-gx10/fc-tenant-andrew/configmap-andrew-web-nginx-conf.json create mode 100644 apps-gx10/fc-tenant-andrew/deployment-andrew-web.json create mode 100644 apps-gx10/fc-tenant-andrew/ingressroute-andrew-web.json create mode 100644 apps-gx10/fc-tenant-andrew/service-andrew-web.json create mode 100644 apps-gx10/fc-tenant-dustin/configmap-dustin-web-html.json create mode 100644 apps-gx10/fc-tenant-dustin/configmap-dustin-web-nginx-conf.json create mode 100644 apps-gx10/fc-tenant-dustin/deployment-dustin-web.json create mode 100644 apps-gx10/fc-tenant-dustin/ingressroute-dustin-web.json create mode 100644 apps-gx10/fc-tenant-dustin/service-dustin-web.json create mode 100644 apps-gx10/fc-tenant-erik/configmap-erik-web-html.json create mode 100644 apps-gx10/fc-tenant-erik/configmap-erik-web-nginx-conf.json create mode 100644 apps-gx10/fc-tenant-erik/deployment-erik-web.json create mode 100644 apps-gx10/fc-tenant-erik/ingressroute-erik-web.json create mode 100644 apps-gx10/fc-tenant-erik/service-erik-web.json create mode 100644 apps-gx10/fc-tenant-fit/configmap-fit-web-html.json create mode 100644 apps-gx10/fc-tenant-fit/configmap-fit-web-nginx-conf.json create mode 100644 apps-gx10/fc-tenant-fit/deployment-fit-web.json create mode 100644 apps-gx10/fc-tenant-fit/ingressroute-fit-web.json create mode 100644 apps-gx10/fc-tenant-fit/service-fit-web.json create mode 100644 apps-gx10/fc-tenant-matt/configmap-matt-web-html.json create mode 100644 apps-gx10/fc-tenant-matt/configmap-matt-web-nginx-conf.json create mode 100644 apps-gx10/fc-tenant-matt/deployment-matt-web.json create mode 100644 apps-gx10/fc-tenant-matt/ingressroute-matt-web.json create mode 100644 apps-gx10/fc-tenant-matt/service-matt-web.json create mode 100644 apps-gx10/fc-ttsreader/deployment-ttsreader-web.json create mode 100644 apps-gx10/fc-ttsreader/ingressroute-ttsreader-web.json create mode 100644 apps-gx10/fc-ttsreader/service-ttsreader-web.json create mode 100644 apps-gx10/fc-updater/deployment-updatecenter-web.json create mode 100644 apps-gx10/fc-updater/ingressroute-updatecenter-web-gx10.json create mode 100644 apps-gx10/fc-updater/ingressroute-updatecenter-web-internal-gx10.json create mode 100644 apps-gx10/fc-updater/ingressroute-updatecenter-web-public-gx10.json create mode 100644 apps-gx10/fc-updater/service-updatecenter-web.json create mode 100644 apps-gx10/fc-worldbuilder/deployment-worldbuilder-web.json create mode 100644 apps-gx10/fc-worldbuilder/ingressroute-worldbuilder-web.json create mode 100644 apps-gx10/fc-worldbuilder/service-worldbuilder-web.json create mode 100644 apps-gx10/intranet/configmap-intranet-config.json create mode 100644 apps-gx10/intranet/deployment-intranet-web.json create mode 100644 apps-gx10/intranet/ingressroute-intranet-web.json create mode 100644 apps-gx10/intranet/service-intranet-web.json create mode 100644 apps-gx10/telephony/certificate-yealink-provision-tls.json create mode 100644 apps-gx10/telephony/configmap-asterisk-config.json create mode 100644 apps-gx10/telephony/configmap-telephony-config.json create mode 100644 apps-gx10/telephony/configmap-yealink-provisioning.json create mode 100644 apps-gx10/telephony/deployment-asterisk.json create mode 100644 apps-gx10/telephony/deployment-telephony-web.json create mode 100644 apps-gx10/telephony/deployment-yealink-provision.json create mode 100644 apps-gx10/telephony/ingressroute-telephony-web-gx10.json create mode 100644 apps-gx10/telephony/ingressroute-telephony-web-internal-gx10.json create mode 100644 apps-gx10/telephony/ingressroute-yealink-provision.json create mode 100644 apps-gx10/telephony/service-asterisk-ari.json create mode 100644 apps-gx10/telephony/service-asterisk-sip.json create mode 100644 apps-gx10/telephony/service-telephony-web.json create mode 100644 apps-gx10/telephony/service-yealink-provision.json create mode 100644 apps-gx10/tts/deployment-gx10-tts.json create mode 100644 apps-gx10/tts/service-gx10-tts.json diff --git a/apps-gx10/fc-aistation/certificate-aistation-web-tls.json b/apps-gx10/fc-aistation/certificate-aistation-web-tls.json new file mode 100644 index 0000000..22eb47c --- /dev/null +++ b/apps-gx10/fc-aistation/certificate-aistation-web-tls.json @@ -0,0 +1,18 @@ +{ + "apiVersion": "cert-manager.io/v1", + "kind": "Certificate", + "metadata": { + "name": "aistation-web-tls", + "namespace": "fc-aistation" + }, + "spec": { + "dnsNames": [ + "aistation.iamworkin.lan" + ], + "issuerRef": { + "kind": "ClusterIssuer", + "name": "step-ca-acme" + }, + "secretName": "aistation-web-tls" + } +} diff --git a/apps-gx10/fc-aistation/configmap-aistation-web-config.json b/apps-gx10/fc-aistation/configmap-aistation-web-config.json new file mode 100644 index 0000000..2e09cd8 --- /dev/null +++ b/apps-gx10/fc-aistation/configmap-aistation-web-config.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "v1", + "data": { + "ASPNETCORE_ENVIRONMENT": "Production", + "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true", + "ASPNETCORE_URLS": "http://+:5000", + "AiStation__Appliance__FallbackEdition": "gx10", + "FLOWERCORE_AISTATION_EDITION": "gx10", + "FlowerCore__AgentZero__Enabled": "false", + "FlowerCore__DataDirectory": "/data", + "FlowerCore__Database__ConnectionStrings__Sqlite": "Data Source=/data/aistation.db", + "FlowerCore__Database__Provider": "Sqlite", + "FlowerCore__Editions__ProfileDirectory": "/app/editions", + "FlowerCore__Ollama__BaseUrl": "http://10.0.57.201:11434", + "FlowerCore__Operator__Enabled": "true", + "OTEL_EXPORTER_OTLP_ENDPOINT": "http://otel-collector.monitoring.svc.cluster.local:4317", + "OTEL_EXPORTER_OTLP_PROTOCOL": "grpc", + "OTEL_SERVICE_NAME": "FlowerCore.AiStation" + }, + "kind": "ConfigMap", + "metadata": { + "labels": { + "app.kubernetes.io/name": "aistation-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "aistation-web-config", + "namespace": "fc-aistation" + } +} diff --git a/apps-gx10/fc-aistation/deployment-aistation-web.json b/apps-gx10/fc-aistation/deployment-aistation-web.json new file mode 100644 index 0000000..ca43887 --- /dev/null +++ b/apps-gx10/fc-aistation/deployment-aistation-web.json @@ -0,0 +1,111 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/name": "aistation-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "aistation-web", + "namespace": "fc-aistation" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 3, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "aistation-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "kubectl.kubernetes.io/restartedAt": "2026-06-16T14:00:18-05:00", + "prometheus.io/path": "/metrics/prometheus", + "prometheus.io/port": "5000", + "prometheus.io/scrape": "true" + }, + "labels": { + "app.kubernetes.io/name": "aistation-web", + "app.kubernetes.io/part-of": "flowercore" + } + }, + "spec": { + "containers": [ + { + "envFrom": [ + { + "configMapRef": { + "name": "aistation-web-config" + } + } + ], + "image": "localhost/fc-aistation-web:v20260616-ai6-gx10-websurface-a8a3e9d-2f9f89e", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 5000, + "scheme": "HTTP" + }, + "initialDelaySeconds": 30, + "periodSeconds": 30, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "name": "aistation-web", + "ports": [ + { + "containerPort": 5000, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 6, + "httpGet": { + "path": "/healthz", + "port": 5000, + "scheme": "HTTP" + }, + "initialDelaySeconds": 10, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "nodeSelector": { + "kubernetes.io/arch": "arm64" + }, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "aistation-web-data" + } + } + ] + } + } + } +} diff --git a/apps-gx10/fc-aistation/ingressroute-aistation-web.json b/apps-gx10/fc-aistation/ingressroute-aistation-web.json new file mode 100644 index 0000000..d95cb6c --- /dev/null +++ b/apps-gx10/fc-aistation/ingressroute-aistation-web.json @@ -0,0 +1,28 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "aistation-web", + "namespace": "fc-aistation" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`aistation.iamworkin.lan`)", + "services": [ + { + "name": "aistation-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "aistation-web-tls" + } + } +} diff --git a/apps-gx10/fc-aistation/service-aistation-web.json b/apps-gx10/fc-aistation/service-aistation-web.json new file mode 100644 index 0000000..975c47f --- /dev/null +++ b/apps-gx10/fc-aistation/service-aistation-web.json @@ -0,0 +1,28 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app.kubernetes.io/name": "aistation-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "aistation-web", + "namespace": "fc-aistation" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 5000 + } + ], + "selector": { + "app.kubernetes.io/name": "aistation-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-chat/configmap-chat-web-config.json b/apps-gx10/fc-chat/configmap-chat-web-config.json new file mode 100644 index 0000000..47daac8 --- /dev/null +++ b/apps-gx10/fc-chat/configmap-chat-web-config.json @@ -0,0 +1,54 @@ +{ + "apiVersion": "v1", + "data": { + "ASPNETCORE_ENVIRONMENT": "Production", + "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true", + "ASPNETCORE_URLS": "http://+:8080", + "ChatOptions__BehaviorRuleEngine__FallbackOllamaBaseUrl": "http://10.0.57.201:11434", + "ChatOptions__BehaviorRuleEngine__ModelName": "gemma3:4b", + "ChatOptions__BehaviorRuleEngine__OllamaBaseUrl": "http://10.0.57.201:11434", + "FlowerCore__AI__DefaultModelName": "gemma3:12b", + "FlowerCore__AI__Helpdesk__SentimentEscalation__Enabled": "true", + "FlowerCore__AI__IrcBridge__AllowActionExecution": "false", + "FlowerCore__AI__IrcBridge__DefaultProfileSlug": "it-helpdesk", + "FlowerCore__AI__IrcBridge__Enabled": "true", + "FlowerCore__AI__IrcBridge__MentionProfileSlug": "it-helpdesk", + "FlowerCore__AI__IrcBridge__MentionReactiveMode": "mentions-only", + "FlowerCore__AI__Memory__EmbeddingModel": "nomic-embed-text", + "FlowerCore__AI__Memory__EnableSharedIndexingBackfill": "true", + "FlowerCore__AI__Memory__SharedIndexingDatabasePath": "/data/chat-memory-index.db", + "FlowerCore__AI__Memory__UseOllamaEmbeddings": "true", + "FlowerCore__AI__Memory__UseSharedIndexingAdapter": "true", + "FlowerCore__AI__OllamaBaseUrl": "http://10.0.57.201:11434", + "FlowerCore__AI__Skills__Intranet__IntranetBaseUrl": "http://intranet-web.intranet.svc.cluster.local", + "FlowerCore__AI__Skills__Intranet__PublicBaseUrl": "https://intranet.iamworkin.lan", + "FlowerCore__AI__Skills__Intranet__SearchBaseUrl": "https://intranet.iamworkin.lan", + "FlowerCore__AI__Skills__Library__LibraryApiUrl": "http://library-web.fc-library.svc.cluster.local", + "FlowerCore__AI__Skills__Print__PrintMcpBaseUrl": "http://10.0.57.16:5200", + "FlowerCore__AI__Skills__Retail__RetailApiUrl": "http://retail-web.fc-retail.svc.cluster.local", + "FlowerCore__AI__Voice__OutputRoot": "/data/audio", + "FlowerCore__AI__Voice__Piper__Host": "10.0.57.17", + "FlowerCore__AI__Voice__Piper__Port": "10400", + "FlowerCore__AI__Voice__RetentionDays": "30", + "FlowerCore__Anthropic__BaseUrl": "https://api.anthropic.com", + "FlowerCore__Anthropic__CheapModel": "claude-haiku-4-5-20251001", + "FlowerCore__Anthropic__DeepModel": "claude-opus-4-7", + "FlowerCore__Anthropic__DefaultModel": "claude-sonnet-4-6", + "FlowerCore__Anthropic__Enabled": "false", + "FlowerCore__Auth__Enabled": "false", + "FlowerCore__Auth__Oidc__Audience": "chat", + "FlowerCore__Auth__Oidc__Authority": "https://id.iamworkin.lan/application/o/chat/", + "FlowerCore__Auth__Oidc__ClientId": "chat", + "FlowerCore__Auth__Oidc__Enabled": "true", + "FlowerCore__Budget__ResponseCacheEnabled": "true", + "FlowerCore__Database__ConnectionStrings__Sqlite": "Data Source=/data/chat.db", + "OTEL_EXPORTER_OTLP_ENDPOINT": "http://otel-collector.monitoring.svc.cluster.local:4317", + "OTEL_EXPORTER_OTLP_PROTOCOL": "grpc", + "OTEL_SERVICE_NAME": "FlowerCore.Chat" + }, + "kind": "ConfigMap", + "metadata": { + "name": "chat-web-config", + "namespace": "fc-chat" + } +} diff --git a/apps-gx10/fc-chat/deployment-chat-web.json b/apps-gx10/fc-chat/deployment-chat-web.json new file mode 100644 index 0000000..dd23cc5 --- /dev/null +++ b/apps-gx10/fc-chat/deployment-chat-web.json @@ -0,0 +1,159 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/name": "chat-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "chat-web", + "namespace": "fc-chat" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "chat-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "fc.flowercore.io/healthz-anon": "true", + "fc.flowercore.io/probe-path": "/healthz", + "prometheus.io/path": "/metrics/prometheus", + "prometheus.io/port": "8080", + "prometheus.io/scrape": "true" + }, + "labels": { + "app.kubernetes.io/name": "chat-web", + "app.kubernetes.io/part-of": "flowercore" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "FlowerCore__Auth__Oidc__Authority", + "valueFrom": { + "secretKeyRef": { + "key": "issuer_url", + "name": "chat-oidc-client", + "optional": true + } + } + }, + { + "name": "FlowerCore__Auth__Oidc__ClientId", + "valueFrom": { + "secretKeyRef": { + "key": "client_id", + "name": "chat-oidc-client", + "optional": true + } + } + }, + { + "name": "FlowerCore__Auth__Oidc__ClientSecret", + "valueFrom": { + "secretKeyRef": { + "key": "client_secret", + "name": "chat-oidc-client", + "optional": true + } + } + } + ], + "envFrom": [ + { + "configMapRef": { + "name": "chat-web-config" + } + }, + { + "secretRef": { + "name": "chat-web-secret", + "optional": true + } + } + ], + "image": "localhost/fc-chat-web:v20260616-chat-md-a812a81", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 30, + "periodSeconds": 30, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "name": "chat-web", + "ports": [ + { + "containerPort": 8080, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 6, + "httpGet": { + "path": "/healthz", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 10, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "resources": { + "limits": { + "cpu": "500m", + "memory": "512Mi" + }, + "requests": { + "cpu": "100m", + "memory": "128Mi" + } + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": { + "fsGroup": 1654, + "fsGroupChangePolicy": "OnRootMismatch" + }, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "chat-web-data" + } + } + ] + } + } + } +} diff --git a/apps-gx10/fc-chat/ingressroute-chat-web-public.json b/apps-gx10/fc-chat/ingressroute-chat-web-public.json new file mode 100644 index 0000000..72b3db4 --- /dev/null +++ b/apps-gx10/fc-chat/ingressroute-chat-web-public.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "chat-web-public", + "namespace": "fc-chat" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`chat.flowercore.io`) && (Path(`/`) || Path(`/chat`) || PathPrefix(`/_blazor`) || PathPrefix(`/_framework`) || PathPrefix(`/_content`) || PathPrefix(`/avatars`) || PathPrefix(`/css`) || PathPrefix(`/js`) || PathPrefix(`/favicon`) || PathPrefix(`/chathub`)) && (Method(`GET`) || Method(`HEAD`) || Method(`POST`) || Method(`OPTIONS`))", + "priority": 100, + "services": [ + { + "name": "chat-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "cf-origin-flowercore-io" + } + } +} diff --git a/apps-gx10/fc-chat/ingressroute-chat-web.json b/apps-gx10/fc-chat/ingressroute-chat-web.json new file mode 100644 index 0000000..3408ebd --- /dev/null +++ b/apps-gx10/fc-chat/ingressroute-chat-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "chat-web", + "namespace": "fc-chat" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`chat.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "chat-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "chat-web-tls" + } + } +} diff --git a/apps-gx10/fc-chat/service-chat-web.json b/apps-gx10/fc-chat/service-chat-web.json new file mode 100644 index 0000000..6070a75 --- /dev/null +++ b/apps-gx10/fc-chat/service-chat-web.json @@ -0,0 +1,28 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app.kubernetes.io/name": "chat-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "chat-web", + "namespace": "fc-chat" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 8080 + } + ], + "selector": { + "app.kubernetes.io/name": "chat-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-desktop/certificate-remotedesktop-tls.json b/apps-gx10/fc-desktop/certificate-remotedesktop-tls.json new file mode 100644 index 0000000..66f5d56 --- /dev/null +++ b/apps-gx10/fc-desktop/certificate-remotedesktop-tls.json @@ -0,0 +1,18 @@ +{ + "apiVersion": "cert-manager.io/v1", + "kind": "Certificate", + "metadata": { + "name": "remotedesktop-tls", + "namespace": "fc-desktop" + }, + "spec": { + "dnsNames": [ + "desktop.iamworkin.lan" + ], + "issuerRef": { + "kind": "ClusterIssuer", + "name": "step-ca-acme" + }, + "secretName": "remotedesktop-tls" + } +} diff --git a/apps-gx10/fc-desktop/deployment-remotedesktop-operator.json b/apps-gx10/fc-desktop/deployment-remotedesktop-operator.json new file mode 100644 index 0000000..16b0f4f --- /dev/null +++ b/apps-gx10/fc-desktop/deployment-remotedesktop-operator.json @@ -0,0 +1,93 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/name": "remotedesktop-operator", + "app.kubernetes.io/part-of": "flowercore-remotedesktop" + }, + "name": "remotedesktop-operator", + "namespace": "fc-desktop" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "remotedesktop-operator" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%" + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "labels": { + "app.kubernetes.io/name": "remotedesktop-operator", + "app.kubernetes.io/part-of": "flowercore-remotedesktop" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "RemoteDesktop__WebUrl", + "value": "http://remotedesktop-web.fc-desktop.svc.cluster.local.:8080" + } + ], + "image": "localhost/fc-remotedesktop-operator:gx10-v1", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": "http", + "scheme": "HTTP" + }, + "initialDelaySeconds": 15, + "periodSeconds": 30, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "name": "operator", + "ports": [ + { + "containerPort": 8080, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": "http", + "scheme": "HTTP" + }, + "initialDelaySeconds": 5, + "periodSeconds": 15, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "remotedesktop-operator", + "serviceAccountName": "remotedesktop-operator", + "terminationGracePeriodSeconds": 30 + } + } + } +} diff --git a/apps-gx10/fc-desktop/deployment-remotedesktop-web.json b/apps-gx10/fc-desktop/deployment-remotedesktop-web.json new file mode 100644 index 0000000..5f3a912 --- /dev/null +++ b/apps-gx10/fc-desktop/deployment-remotedesktop-web.json @@ -0,0 +1,299 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/name": "remotedesktop-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "remotedesktop-web", + "namespace": "fc-desktop" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "remotedesktop-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "labels": { + "app.kubernetes.io/name": "remotedesktop-web", + "app.kubernetes.io/part-of": "flowercore" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "ASPNETCORE_URLS", + "value": "http://+:8080" + }, + { + "name": "ASPNETCORE_ENVIRONMENT", + "value": "Production" + }, + { + "name": "FlowerCore__Database__ConnectionStrings__Sqlite", + "value": "Data Source=/app/data/remotedesktop.db" + }, + { + "name": "RemoteDesktop__Mode", + "value": "Remote" + }, + { + "name": "RemoteDesktop__EnableApiDocs", + "value": "true" + }, + { + "name": "RemoteDesktop__PoolWarmupEnabled", + "value": "false" + }, + { + "name": "RemoteDesktop__PoolWarmupIntervalSeconds", + "value": "60" + }, + { + "name": "RemoteDesktop__OrphanReconciler__Enabled", + "value": "true" + }, + { + "name": "RemoteDesktop__OrphanReconciler__IntervalSeconds", + "value": "300" + }, + { + "name": "RemoteDesktop__OrphanReconciler__GraceSeconds", + "value": "600" + }, + { + "name": "RemoteDesktop__Audit__Enabled", + "value": "true" + }, + { + "name": "RemoteDesktop__Audit__DualWrite", + "value": "true" + }, + { + "name": "RemoteDesktop__UserVolumeClaimInitializer", + "value": "KubernetesExec" + }, + { + "name": "RemoteDesktop__KubernetesNamespace", + "value": "fc-desktop" + }, + { + "name": "RemoteDesktop__GuacamoleUrl", + "value": "http://guacamole.guacamole.svc.cluster.local.:8080/guacamole" + }, + { + "name": "RemoteDesktop__GuacamolePublicUrl", + "value": "https://desktop.iamworkin.lan/guacamole" + }, + { + "name": "RemoteDesktop__GuacamoleAdminUser", + "value": "guacadmin" + }, + { + "name": "RemoteDesktop__GuacamoleJsonSecretKey", + "valueFrom": { + "secretKeyRef": { + "key": "password", + "name": "remotedesktop-guacamole-json-auth" + } + } + }, + { + "name": "RemoteDesktop__TraefikClusterIp", + "value": "10.43.234.103" + }, + { + "name": "RemoteDesktop__TraefikHostAliases__0", + "value": "chat.iamworkin.lan" + }, + { + "name": "RemoteDesktop__TraefikHostAliases__1", + "value": "desktop.iamworkin.lan" + }, + { + "name": "RemoteDesktop__TraefikHostAliases__2", + "value": "gitea.iamworkin.lan" + }, + { + "name": "RemoteDesktop__TraefikHostAliases__3", + "value": "intranet.iamworkin.lan" + }, + { + "name": "RemoteDesktop__TraefikHostAliases__4", + "value": "print.iamworkin.lan" + }, + { + "name": "RemoteDesktop__TraefikHostAliases__5", + "value": "selenium.iamworkin.lan" + }, + { + "name": "RemoteDesktop__NfsServer", + "value": "10.0.58.3" + }, + { + "name": "RemoteDesktop__NfsBasePath", + "value": "/volume1/kubernetes/remotedesktop/users" + }, + { + "name": "RemoteDesktop__SessionRecordingBasePath", + "value": "/var/lib/guacamole/recordings" + }, + { + "name": "RemoteDesktop__MaxSessionsPerUser", + "value": "3" + }, + { + "name": "FlowerCore__Auth__Oidc__Authority", + "valueFrom": { + "secretKeyRef": { + "key": "issuer_url", + "name": "remotedesktop-oidc-client", + "optional": true + } + } + }, + { + "name": "FlowerCore__Auth__Oidc__ClientId", + "valueFrom": { + "secretKeyRef": { + "key": "client_id", + "name": "remotedesktop-oidc-client", + "optional": true + } + } + }, + { + "name": "FlowerCore__Auth__Oidc__ClientSecret", + "valueFrom": { + "secretKeyRef": { + "key": "client_secret", + "name": "remotedesktop-oidc-client", + "optional": true + } + } + }, + { + "name": "FlowerCore__Auth__Enabled", + "value": "false" + }, + { + "name": "FlowerCore__Auth__Oidc__Enabled", + "value": "false" + } + ], + "envFrom": [ + { + "secretRef": { + "name": "remotedesktop-secrets", + "optional": true + } + } + ], + "image": "localhost/fc-remotedesktop-web:gx10-v1", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 15, + "periodSeconds": 30, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "name": "web", + "ports": [ + { + "containerPort": 8080, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 5, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "500m", + "memory": "512Mi" + }, + "requests": { + "cpu": "100m", + "memory": "256Mi" + } + }, + "startupProbe": { + "failureThreshold": 60, + "httpGet": { + "path": "/health", + "port": 8080, + "scheme": "HTTP" + }, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/app/data", + "name": "data" + }, + { + "mountPath": "/var/lib/guacamole/recordings", + "name": "recordings", + "readOnly": true, + "subPath": "guacamole/recordings" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "remotedesktop-web", + "serviceAccountName": "remotedesktop-web", + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "remotedesktop-data" + } + }, + { + "name": "recordings", + "nfs": { + "path": "/volume1/kubernetes", + "server": "10.0.58.3" + } + } + ] + } + } + } +} diff --git a/apps-gx10/fc-desktop/ingressroute-remotedesktop-web.json b/apps-gx10/fc-desktop/ingressroute-remotedesktop-web.json new file mode 100644 index 0000000..4eb7a48 --- /dev/null +++ b/apps-gx10/fc-desktop/ingressroute-remotedesktop-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "remotedesktop-web", + "namespace": "fc-desktop" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`desktop.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "remotedesktop-web", + "port": 8080 + } + ] + } + ], + "tls": { + "secretName": "remotedesktop-tls" + } + } +} diff --git a/apps-gx10/fc-desktop/service-remotedesktop-web.json b/apps-gx10/fc-desktop/service-remotedesktop-web.json new file mode 100644 index 0000000..702c17b --- /dev/null +++ b/apps-gx10/fc-desktop/service-remotedesktop-web.json @@ -0,0 +1,24 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "name": "remotedesktop-web", + "namespace": "fc-desktop" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 8080, + "protocol": "TCP", + "targetPort": 8080 + } + ], + "selector": { + "app.kubernetes.io/name": "remotedesktop-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-desktop/serviceaccount-remotedesktop-operator.json b/apps-gx10/fc-desktop/serviceaccount-remotedesktop-operator.json new file mode 100644 index 0000000..952484b --- /dev/null +++ b/apps-gx10/fc-desktop/serviceaccount-remotedesktop-operator.json @@ -0,0 +1,8 @@ +{ + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": { + "name": "remotedesktop-operator", + "namespace": "fc-desktop" + } +} diff --git a/apps-gx10/fc-desktop/serviceaccount-remotedesktop-web.json b/apps-gx10/fc-desktop/serviceaccount-remotedesktop-web.json new file mode 100644 index 0000000..d42a703 --- /dev/null +++ b/apps-gx10/fc-desktop/serviceaccount-remotedesktop-web.json @@ -0,0 +1,8 @@ +{ + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": { + "name": "remotedesktop-web", + "namespace": "fc-desktop" + } +} diff --git a/apps-gx10/fc-devicemgmt/deployment-fc-devicemgmt-operator.json b/apps-gx10/fc-devicemgmt/deployment-fc-devicemgmt-operator.json new file mode 100644 index 0000000..8b45c7c --- /dev/null +++ b/apps-gx10/fc-devicemgmt/deployment-fc-devicemgmt-operator.json @@ -0,0 +1,183 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "fc-devicemgmt-operator", + "app.kubernetes.io/component": "operator", + "app.kubernetes.io/managed-by": "argocd", + "app.kubernetes.io/name": "fc-devicemgmt-operator", + "app.kubernetes.io/part-of": "flowercore", + "flowercore.io/created-by": "bluejay-infra", + "flowercore.io/tenant-id": "system" + }, + "name": "fc-devicemgmt-operator", + "namespace": "fc-devicemgmt" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 3, + "selector": { + "matchLabels": { + "app": "fc-devicemgmt-operator" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%" + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "annotations": { + "flowercore.io/audit-trace-id": "runtime-activity-trace", + "prometheus.io/path": "/metrics", + "prometheus.io/port": "8080", + "prometheus.io/scrape": "true" + }, + "labels": { + "app": "fc-devicemgmt-operator", + "app.kubernetes.io/component": "operator", + "app.kubernetes.io/managed-by": "argocd", + "app.kubernetes.io/name": "fc-devicemgmt-operator", + "app.kubernetes.io/part-of": "flowercore", + "flowercore.io/created-by": "bluejay-infra", + "flowercore.io/tenant-id": "system" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "ASPNETCORE_ENVIRONMENT", + "value": "Production" + }, + { + "name": "DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", + "value": "false" + }, + { + "name": "POD_NAME", + "valueFrom": { + "fieldRef": { + "apiVersion": "v1", + "fieldPath": "metadata.name" + } + } + }, + { + "name": "POD_NAMESPACE", + "valueFrom": { + "fieldRef": { + "apiVersion": "v1", + "fieldPath": "metadata.namespace" + } + } + }, + { + "name": "FLOWERCORE_KUBERNETES_OWNER_DEPLOYMENT", + "value": "fc-devicemgmt-operator" + }, + { + "name": "FlowerCore__Service__Name", + "value": "FlowerCore.DeviceManagement.Operator" + }, + { + "name": "FlowerCore__DeviceManagement__DefaultTenantId", + "value": "system" + } + ], + "image": "localhost/fc-devicemgmt-operator:gx10-v1", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "failureThreshold": 3, + "initialDelaySeconds": 20, + "periodSeconds": 30, + "successThreshold": 1, + "tcpSocket": { + "port": 8080 + }, + "timeoutSeconds": 1 + }, + "name": "operator", + "ports": [ + { + "containerPort": 8080, + "name": "metrics", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "initialDelaySeconds": 5, + "periodSeconds": 10, + "successThreshold": 1, + "tcpSocket": { + "port": 8080 + }, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "500m", + "memory": "512Mi" + }, + "requests": { + "cpu": "50m", + "memory": "128Mi" + } + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true, + "runAsGroup": 1654, + "runAsNonRoot": true, + "runAsUser": 1654 + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/tmp", + "name": "tmp" + }, + { + "mountPath": "/app/logs", + "name": "logs" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": { + "fsGroup": 1654, + "fsGroupChangePolicy": "OnRootMismatch" + }, + "serviceAccount": "fc-devicemgmt-operator", + "serviceAccountName": "fc-devicemgmt-operator", + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "emptyDir": {}, + "name": "tmp" + }, + { + "emptyDir": {}, + "name": "logs" + } + ] + } + } + } +} diff --git a/apps-gx10/fc-devicemgmt/deployment-fc-devicemgmt-web.json b/apps-gx10/fc-devicemgmt/deployment-fc-devicemgmt-web.json new file mode 100644 index 0000000..60e6a7d --- /dev/null +++ b/apps-gx10/fc-devicemgmt/deployment-fc-devicemgmt-web.json @@ -0,0 +1,211 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "fc-devicemgmt-web", + "app.kubernetes.io/component": "web", + "app.kubernetes.io/managed-by": "argocd", + "app.kubernetes.io/name": "fc-devicemgmt-web", + "app.kubernetes.io/part-of": "flowercore", + "flowercore.io/created-by": "bluejay-infra", + "flowercore.io/tenant-id": "system" + }, + "name": "fc-devicemgmt-web", + "namespace": "fc-devicemgmt" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 3, + "selector": { + "matchLabels": { + "app": "fc-devicemgmt-web" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": 0, + "maxUnavailable": 1 + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "annotations": { + "fc.flowercore.io/healthz-anon": "true", + "fc.flowercore.io/probe-path": "/healthz", + "flowercore.io/audit-trace-id": "runtime-activity-trace", + "kubectl.kubernetes.io/restartedAt": "2026-05-20T11:29:46-05:00", + "operator.1password.io/last-restarted": "2026-05-20T16:29:03Z", + "prometheus.io/path": "/metrics", + "prometheus.io/port": "8080", + "prometheus.io/scrape": "true" + }, + "labels": { + "app": "fc-devicemgmt-web", + "app.kubernetes.io/component": "web", + "app.kubernetes.io/managed-by": "argocd", + "app.kubernetes.io/name": "fc-devicemgmt-web", + "app.kubernetes.io/part-of": "flowercore", + "flowercore.io/created-by": "bluejay-infra", + "flowercore.io/tenant-id": "system" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "ASPNETCORE_URLS", + "value": "http://+:8080" + }, + { + "name": "ASPNETCORE_ENVIRONMENT", + "value": "Production" + }, + { + "name": "DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", + "value": "false" + }, + { + "name": "HOME", + "value": "/data" + }, + { + "name": "FlowerCore__Service__Name", + "value": "FlowerCore.DeviceManagement.Web" + }, + { + "name": "FlowerCore__DeviceManagement__DefaultTenantId", + "value": "system" + }, + { + "name": "FlowerCore__Database__Provider", + "value": "Sqlite" + }, + { + "name": "FlowerCore__Database__ConnectionStrings__Sqlite", + "value": "Data Source=/data/devicemgmt.db" + }, + { + "name": "FlowerCore__Database__Password", + "valueFrom": { + "secretKeyRef": { + "key": "DB-Password", + "name": "fc-devicemgmt-runtime" + } + } + }, + { + "name": "FlowerCore__EventBus__Redis__Configuration", + "value": "redis.fc-redis.svc:6379" + } + ], + "image": "localhost/fc-devicemgmt-web:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "initialDelaySeconds": 30, + "periodSeconds": 30, + "successThreshold": 1, + "tcpSocket": { + "port": 8080 + }, + "timeoutSeconds": 1 + }, + "name": "web", + "ports": [ + { + "containerPort": 8080, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "periodSeconds": 10, + "successThreshold": 1, + "tcpSocket": { + "port": 8080 + }, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "1", + "memory": "768Mi" + }, + "requests": { + "cpu": "100m", + "memory": "256Mi" + } + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true, + "runAsGroup": 1654, + "runAsNonRoot": true, + "runAsUser": 1654 + }, + "startupProbe": { + "failureThreshold": 30, + "initialDelaySeconds": 5, + "periodSeconds": 5, + "successThreshold": 1, + "tcpSocket": { + "port": 8080 + }, + "timeoutSeconds": 1 + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + }, + { + "mountPath": "/tmp", + "name": "tmp" + }, + { + "mountPath": "/app/logs", + "name": "logs" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": { + "fsGroup": 1654, + "fsGroupChangePolicy": "OnRootMismatch" + }, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "fc-devicemgmt-web-data" + } + }, + { + "emptyDir": {}, + "name": "tmp" + }, + { + "emptyDir": {}, + "name": "logs" + } + ] + } + } + } +} diff --git a/apps-gx10/fc-devicemgmt/ingressroute-devicemgmt.json b/apps-gx10/fc-devicemgmt/ingressroute-devicemgmt.json new file mode 100644 index 0000000..d9507e9 --- /dev/null +++ b/apps-gx10/fc-devicemgmt/ingressroute-devicemgmt.json @@ -0,0 +1,28 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "devicemgmt", + "namespace": "fc-devicemgmt" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`devices.iamworkin.lan`)", + "services": [ + { + "name": "fc-devicemgmt-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "fc-devicemgmt-web-tls" + } + } +} diff --git a/apps-gx10/fc-devicemgmt/service-fc-devicemgmt-web.json b/apps-gx10/fc-devicemgmt/service-fc-devicemgmt-web.json new file mode 100644 index 0000000..ea6bc7a --- /dev/null +++ b/apps-gx10/fc-devicemgmt/service-fc-devicemgmt-web.json @@ -0,0 +1,33 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app": "fc-devicemgmt-web", + "app.kubernetes.io/component": "web", + "app.kubernetes.io/managed-by": "argocd", + "app.kubernetes.io/name": "fc-devicemgmt-web", + "app.kubernetes.io/part-of": "flowercore", + "flowercore.io/created-by": "bluejay-infra", + "flowercore.io/tenant-id": "system" + }, + "name": "fc-devicemgmt-web", + "namespace": "fc-devicemgmt" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 8080 + } + ], + "selector": { + "app": "fc-devicemgmt-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-devicemgmt/serviceaccount-fc-devicemgmt-operator.json b/apps-gx10/fc-devicemgmt/serviceaccount-fc-devicemgmt-operator.json new file mode 100644 index 0000000..2d17ef2 --- /dev/null +++ b/apps-gx10/fc-devicemgmt/serviceaccount-fc-devicemgmt-operator.json @@ -0,0 +1,16 @@ +{ + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": { + "labels": { + "app.kubernetes.io/component": "operator", + "app.kubernetes.io/managed-by": "argocd", + "app.kubernetes.io/name": "fc-devicemgmt-operator", + "app.kubernetes.io/part-of": "flowercore", + "flowercore.io/created-by": "bluejay-infra", + "flowercore.io/tenant-id": "system" + }, + "name": "fc-devicemgmt-operator", + "namespace": "fc-devicemgmt" + } +} diff --git a/apps-gx10/fc-distribution/deployment-fc-distribution.json b/apps-gx10/fc-distribution/deployment-fc-distribution.json new file mode 100644 index 0000000..b4f9d26 --- /dev/null +++ b/apps-gx10/fc-distribution/deployment-fc-distribution.json @@ -0,0 +1,265 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/name": "fc-distribution", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "fc-distribution", + "namespace": "fc-distribution" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 3, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "fc-distribution" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "flowercore.io/healthz-auth-policy": "allow-anonymous", + "prometheus.io/path": "/metrics", + "prometheus.io/port": "8080", + "prometheus.io/scrape": "true" + }, + "labels": { + "app.kubernetes.io/name": "fc-distribution", + "app.kubernetes.io/part-of": "flowercore" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "ASPNETCORE_URLS", + "value": "http://+:8080" + }, + { + "name": "ASPNETCORE_ENVIRONMENT", + "value": "Production" + }, + { + "name": "DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", + "value": "false" + }, + { + "name": "FlowerCore__Auth__Enabled", + "value": "true" + }, + { + "name": "FlowerCore__Auth__Oidc__Enabled", + "value": "true" + }, + { + "name": "FlowerCore__Auth__Oidc__Authority", + "value": "https://id.iamworkin.lan/application/o/distribution/" + }, + { + "name": "FlowerCore__Auth__Oidc__Audience", + "value": "distribution" + }, + { + "name": "FlowerCore__Auth__Oidc__ClientId", + "value": "distribution" + }, + { + "name": "FlowerCore__Auth__Oidc__ClientSecret", + "valueFrom": { + "secretKeyRef": { + "key": "client_secret", + "name": "distribution-oidc-client", + "optional": true + } + } + }, + { + "name": "FlowerCore__Database__Provider", + "value": "Sqlite" + }, + { + "name": "FlowerCore__Database__ConnectionStrings__Sqlite", + "value": "Data Source=/data/distribution.db" + }, + { + "name": "FlowerCore__Distribution__Blobs__Root", + "value": "/blobs" + }, + { + "name": "FlowerCore__Distribution__Signing__EditionCerts__kiosk-standard__CertPath", + "value": "/signing/kiosk-standard/chain.pem" + }, + { + "name": "FlowerCore__Distribution__Signing__EditionCerts__kiosk-standard__KeyPath", + "value": "/signing/kiosk-standard/private-key.pem" + }, + { + "name": "FlowerCore__Distribution__Signing__EditionCerts__aistation-field__CertPath", + "value": "/signing/aistation-field/chain.pem" + }, + { + "name": "FlowerCore__Distribution__Signing__EditionCerts__aistation-field__KeyPath", + "value": "/signing/aistation-field/private-key.pem" + }, + { + "name": "FlowerCore__Distribution__EntitlementPublic__PublicEditions__0", + "value": "*" + } + ], + "image": "localhost/fc-distribution:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "initialDelaySeconds": 30, + "periodSeconds": 30, + "successThreshold": 1, + "tcpSocket": { + "port": 8080 + }, + "timeoutSeconds": 1 + }, + "name": "web", + "ports": [ + { + "containerPort": 8080, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 8080, + "scheme": "HTTP" + }, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "500m", + "memory": "512Mi" + }, + "requests": { + "cpu": "100m", + "memory": "256Mi" + } + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true, + "runAsGroup": 1654, + "runAsNonRoot": true, + "runAsUser": 1654 + }, + "startupProbe": { + "failureThreshold": 30, + "httpGet": { + "path": "/healthz", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 5, + "periodSeconds": 5, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "sqlite", + "subPath": "distribution/data" + }, + { + "mountPath": "/blobs", + "name": "blobs", + "subPath": "distribution/blobs" + }, + { + "mountPath": "/tmp", + "name": "tmp" + }, + { + "mountPath": "/app/logs", + "name": "logs" + }, + { + "mountPath": "/signing/kiosk-standard", + "name": "kiosk-standard", + "readOnly": true + }, + { + "mountPath": "/signing/aistation-field", + "name": "aistation-field", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": { + "fsGroup": 1654, + "fsGroupChangePolicy": "OnRootMismatch", + "runAsNonRoot": true + }, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "sqlite", + "nfs": { + "path": "/volume1/kubernetes", + "server": "10.0.58.3" + } + }, + { + "name": "blobs", + "nfs": { + "path": "/volume1/kubernetes", + "server": "10.0.58.3" + } + }, + { + "emptyDir": {}, + "name": "tmp" + }, + { + "emptyDir": {}, + "name": "logs" + }, + { + "name": "kiosk-standard", + "secret": { + "defaultMode": 256, + "secretName": "edition-kiosk-standard" + } + }, + { + "name": "aistation-field", + "secret": { + "defaultMode": 256, + "secretName": "edition-aistation-field" + } + } + ] + } + } + } +} diff --git a/apps-gx10/fc-distribution/ingressroute-fc-distribution-public.json b/apps-gx10/fc-distribution/ingressroute-fc-distribution-public.json new file mode 100644 index 0000000..091b15e --- /dev/null +++ b/apps-gx10/fc-distribution/ingressroute-fc-distribution-public.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "fc-distribution-public", + "namespace": "fc-distribution" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`dist.flowercore.io`) && (Method(`GET`) || Method(`HEAD`))", + "priority": 100, + "services": [ + { + "name": "fc-distribution", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "cf-origin-flowercore-io" + } + } +} diff --git a/apps-gx10/fc-distribution/ingressroute-fc-distribution.json b/apps-gx10/fc-distribution/ingressroute-fc-distribution.json new file mode 100644 index 0000000..7c96f6e --- /dev/null +++ b/apps-gx10/fc-distribution/ingressroute-fc-distribution.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "fc-distribution", + "namespace": "fc-distribution" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`dist.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "fc-distribution", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "fc-distribution-tls-secret" + } + } +} diff --git a/apps-gx10/fc-distribution/service-fc-distribution.json b/apps-gx10/fc-distribution/service-fc-distribution.json new file mode 100644 index 0000000..3113417 --- /dev/null +++ b/apps-gx10/fc-distribution/service-fc-distribution.json @@ -0,0 +1,28 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app.kubernetes.io/name": "fc-distribution", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "fc-distribution", + "namespace": "fc-distribution" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 8080 + } + ], + "selector": { + "app.kubernetes.io/name": "fc-distribution" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-dms/configmap-dms-web-config.json b/apps-gx10/fc-dms/configmap-dms-web-config.json new file mode 100644 index 0000000..395d4b2 --- /dev/null +++ b/apps-gx10/fc-dms/configmap-dms-web-config.json @@ -0,0 +1,28 @@ +{ + "apiVersion": "v1", + "data": { + "ASPNETCORE_ENVIRONMENT": "Production", + "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true", + "ASPNETCORE_URLS": "http://+:8080", + "Dms__AutoMessageDaemon__PollIntervalMinutes": "5", + "Dms__Weather__CacheFilePath": "/data/noaa-cache.json", + "Dms__Weather__State": "MN", + "FlowerCore__Auth__AcceptLegacyApiKey": "true", + "FlowerCore__Auth__AcceptLegacyJwt": "false", + "FlowerCore__Auth__Provider": "Oidc", + "FlowerCore__Auth__RoleClaimType": "fc:roles", + "FlowerCore__Database__ConnectionStrings__Sqlite": "Data Source=/data/dms.db", + "FlowerCore__Database__Provider": "Sqlite", + "FlowerCore__Tenant__DefaultTenantHosts__0": "dms.iamworkin.lan", + "FlowerCore__Tenant__JwtClaimsEnabled": "false", + "OTEL_EXPORTER_OTLP_ENDPOINT": "http://otel-collector.monitoring.svc.cluster.local:4317", + "OTEL_EXPORTER_OTLP_PROTOCOL": "grpc", + "OTEL_SERVICE_NAME": "FlowerCore.DMS", + "Security__AllowedOrigins__0": "https://dms.iamworkin.lan" + }, + "kind": "ConfigMap", + "metadata": { + "name": "dms-web-config", + "namespace": "fc-dms" + } +} diff --git a/apps-gx10/fc-dms/deployment-dms-web.json b/apps-gx10/fc-dms/deployment-dms-web.json new file mode 100644 index 0000000..617eb69 --- /dev/null +++ b/apps-gx10/fc-dms/deployment-dms-web.json @@ -0,0 +1,169 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/name": "dms-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "dms-web", + "namespace": "fc-dms" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "dms-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "kubectl.kubernetes.io/restartedAt": "2026-06-12T16:05:19-05:00", + "prometheus.io/path": "/metrics/prometheus", + "prometheus.io/port": "8080", + "prometheus.io/scrape": "true" + }, + "labels": { + "app.kubernetes.io/name": "dms-web", + "app.kubernetes.io/part-of": "flowercore" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "Kestrel__Endpoints__Http__Url", + "value": "http://+:8080" + }, + { + "name": "Kestrel__Endpoints__Http__Protocols", + "value": "Http1" + }, + { + "name": "Kestrel__Endpoints__Grpc__Url", + "value": "http://+:8081" + }, + { + "name": "Kestrel__Endpoints__Grpc__Protocols", + "value": "Http2" + }, + { + "name": "FlowerCore__Auth__OidcClientId", + "valueFrom": { + "secretKeyRef": { + "key": "client_id", + "name": "dms-oidc-client", + "optional": true + } + } + }, + { + "name": "FlowerCore__Auth__OidcClientSecret", + "valueFrom": { + "secretKeyRef": { + "key": "client_secret", + "name": "dms-oidc-client", + "optional": true + } + } + }, + { + "name": "FlowerCore__Auth__OidcAuthority", + "valueFrom": { + "secretKeyRef": { + "key": "issuer_url", + "name": "dms-oidc-client", + "optional": true + } + } + } + ], + "envFrom": [ + { + "configMapRef": { + "name": "dms-web-config" + } + }, + { + "secretRef": { + "name": "dms-web-secrets" + } + } + ], + "image": "localhost/fc-dms-web:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 180, + "periodSeconds": 30, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "name": "dms-web", + "ports": [ + { + "containerPort": 8080, + "name": "http", + "protocol": "TCP" + }, + { + "containerPort": 8081, + "name": "grpc", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 18, + "httpGet": { + "path": "/health", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 30, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": { + "fsGroup": 1654, + "fsGroupChangePolicy": "OnRootMismatch" + }, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "dms-web-data" + } + } + ] + } + } + } +} diff --git a/apps-gx10/fc-dms/ingressroute-dms-web.json b/apps-gx10/fc-dms/ingressroute-dms-web.json new file mode 100644 index 0000000..4cacb92 --- /dev/null +++ b/apps-gx10/fc-dms/ingressroute-dms-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "dms-web", + "namespace": "fc-dms" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`dms.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "dms-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "dms-web-tls" + } + } +} diff --git a/apps-gx10/fc-dms/service-dms-web.json b/apps-gx10/fc-dms/service-dms-web.json new file mode 100644 index 0000000..f6d63f1 --- /dev/null +++ b/apps-gx10/fc-dms/service-dms-web.json @@ -0,0 +1,34 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app.kubernetes.io/name": "dms-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "dms-web", + "namespace": "fc-dms" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 8080 + }, + { + "name": "grpc", + "port": 8081, + "protocol": "TCP", + "targetPort": 8081 + } + ], + "selector": { + "app.kubernetes.io/name": "dms-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-library/configmap-library-web-config.json b/apps-gx10/fc-library/configmap-library-web-config.json new file mode 100644 index 0000000..7603423 --- /dev/null +++ b/apps-gx10/fc-library/configmap-library-web-config.json @@ -0,0 +1,20 @@ +{ + "apiVersion": "v1", + "data": { + "ASPNETCORE_ENVIRONMENT": "Production", + "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true", + "ASPNETCORE_URLS": "http://+:5000", + "FlowerCore__Database__ConnectionStrings__Sqlite": "Data Source=/data/library.db", + "FlowerCore__Database__Provider": "Sqlite", + "FlowerCore__Library__BaseUrl": "https://library.iamworkin.lan", + "OTEL_EXPORTER_OTLP_ENDPOINT": "http://otel-collector.monitoring.svc.cluster.local:4317", + "OTEL_EXPORTER_OTLP_PROTOCOL": "grpc", + "OTEL_SERVICE_NAME": "FlowerCore.Library", + "PrintService__BaseUrl": "http://print.iamworkin.lan:5200" + }, + "kind": "ConfigMap", + "metadata": { + "name": "library-web-config", + "namespace": "fc-library" + } +} diff --git a/apps-gx10/fc-library/deployment-library-web.json b/apps-gx10/fc-library/deployment-library-web.json new file mode 100644 index 0000000..be7a4a0 --- /dev/null +++ b/apps-gx10/fc-library/deployment-library-web.json @@ -0,0 +1,110 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/managed-by": "argocd", + "app.kubernetes.io/name": "library-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "library-web", + "namespace": "fc-library" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 3, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "library-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "fc.flowercore.io/healthz-anon": "true", + "fc.flowercore.io/probe-path": "/health", + "prometheus.io/path": "/metrics/prometheus", + "prometheus.io/port": "5000", + "prometheus.io/scrape": "true" + }, + "labels": { + "app.kubernetes.io/name": "library-web", + "app.kubernetes.io/part-of": "flowercore" + } + }, + "spec": { + "containers": [ + { + "envFrom": [ + { + "configMapRef": { + "name": "library-web-config" + } + } + ], + "image": "localhost/fc-library-web:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 5000, + "scheme": "HTTP" + }, + "initialDelaySeconds": 30, + "periodSeconds": 30, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "name": "library-web", + "ports": [ + { + "containerPort": 5000, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 6, + "httpGet": { + "path": "/health", + "port": 5000, + "scheme": "HTTP" + }, + "initialDelaySeconds": 10, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "library-web-data" + } + } + ] + } + } + } +} diff --git a/apps-gx10/fc-library/ingressroute-library-web.json b/apps-gx10/fc-library/ingressroute-library-web.json new file mode 100644 index 0000000..65a466a --- /dev/null +++ b/apps-gx10/fc-library/ingressroute-library-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "library-web", + "namespace": "fc-library" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`library.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "library-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "library-web-tls" + } + } +} diff --git a/apps-gx10/fc-library/service-library-web.json b/apps-gx10/fc-library/service-library-web.json new file mode 100644 index 0000000..5ce0041 --- /dev/null +++ b/apps-gx10/fc-library/service-library-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app.kubernetes.io/managed-by": "argocd", + "app.kubernetes.io/name": "library-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "library-web", + "namespace": "fc-library" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 5000 + } + ], + "selector": { + "app.kubernetes.io/name": "library-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-llm-bridge/deployment-fc-llm-bridge.json b/apps-gx10/fc-llm-bridge/deployment-fc-llm-bridge.json new file mode 100644 index 0000000..757ed46 --- /dev/null +++ b/apps-gx10/fc-llm-bridge/deployment-fc-llm-bridge.json @@ -0,0 +1,292 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/name": "fc-llm-bridge", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "fc-llm-bridge", + "namespace": "fc-llm-bridge" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 3, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "fc-llm-bridge" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "fc.flowercore.io/healthz-anon": "true", + "fc.flowercore.io/probe-path": "/healthz", + "kubectl.kubernetes.io/restartedAt": "2026-06-14T15:12:25-05:00", + "prometheus.io/path": "/metrics", + "prometheus.io/port": "8080", + "prometheus.io/scrape": "true" + }, + "labels": { + "app.kubernetes.io/name": "fc-llm-bridge", + "app.kubernetes.io/part-of": "flowercore" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "ASPNETCORE_URLS", + "value": "http://+:8080" + }, + { + "name": "ASPNETCORE_ENVIRONMENT", + "value": "Production" + }, + { + "name": "DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", + "value": "false" + }, + { + "name": "FlowerCore__LlmBridge__SqliteConnectionString", + "value": "Data Source=/data/llm-bridge.db" + }, + { + "name": "FlowerCore__LlmBridge__DefaultTenantId", + "value": "default" + }, + { + "name": "FlowerCore__LlmBridge__DefaultAppName", + "value": "agent-zero" + }, + { + "name": "FlowerCore__LlmBridge__UtilModel", + "value": "qwen2.5:1.5b" + }, + { + "name": "FlowerCore__LlmBridge__EmbedModel", + "value": "nomic-embed-text" + }, + { + "name": "FlowerCore__LlmBridge__ApiKeys__agent-zero-ws", + "valueFrom": { + "secretKeyRef": { + "key": "agent-zero-ws", + "name": "fc-llm-bridge-api-keys", + "optional": true + } + } + }, + { + "name": "FlowerCore__LlmBridge__ApiKeys__agent-zero-k8s", + "valueFrom": { + "secretKeyRef": { + "key": "agent-zero-k8s", + "name": "fc-llm-bridge-api-keys", + "optional": true + } + } + }, + { + "name": "FlowerCore__LlmBridge__ApiKeys__spare-1", + "valueFrom": { + "secretKeyRef": { + "key": "spare-1", + "name": "fc-llm-bridge-api-keys", + "optional": true + } + } + }, + { + "name": "FlowerCore__LlmBridge__ApiKeys__spare-2", + "valueFrom": { + "secretKeyRef": { + "key": "spare-2", + "name": "fc-llm-bridge-api-keys", + "optional": true + } + } + }, + { + "name": "FlowerCore__Chat__OllamaBaseUrl", + "value": "http://10.0.56.14:30976" + }, + { + "name": "FlowerCore__Chat__HttpTimeout", + "value": "00:05:00" + }, + { + "name": "FlowerCore__Chat__ModelRouter__DefaultRoutes__Balanced__Provider", + "value": "Ollama" + }, + { + "name": "FlowerCore__Chat__ModelRouter__DefaultRoutes__Balanced__Model", + "value": "qwen2.5:14b" + }, + { + "name": "FlowerCore__Chat__ModelRouter__DefaultRoutes__Cheap__Provider", + "value": "Ollama" + }, + { + "name": "FlowerCore__Chat__ModelRouter__DefaultRoutes__Cheap__Model", + "value": "qwen2.5:7b" + }, + { + "name": "FlowerCore__Chat__Anthropic__Enabled", + "value": "true" + }, + { + "name": "FlowerCore__Chat__Anthropic__ApiKey", + "valueFrom": { + "secretKeyRef": { + "key": "password", + "name": "anthropic-api-key" + } + } + }, + { + "name": "FlowerCore__Chat__Anthropic__OrganizationId", + "valueFrom": { + "secretKeyRef": { + "key": "organization_id", + "name": "anthropic-api-key", + "optional": true + } + } + }, + { + "name": "FlowerCore__Chat__Anthropic__BaseUrl", + "value": "https://api.anthropic.com" + }, + { + "name": "FlowerCore__Chat__Anthropic__DefaultModel", + "value": "claude-sonnet-4-6" + }, + { + "name": "FlowerCore__Chat__Anthropic__AnthropicVersion", + "value": "2023-06-01" + }, + { + "name": "FlowerCore__Chat__Anthropic__Timeout", + "value": "00:05:00" + } + ], + "image": "localhost/fc-llm-bridge:gx10-v2", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "initialDelaySeconds": 15, + "periodSeconds": 30, + "successThreshold": 1, + "tcpSocket": { + "port": 8080 + }, + "timeoutSeconds": 1 + }, + "name": "web", + "ports": [ + { + "containerPort": 8080, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "initialDelaySeconds": 5, + "periodSeconds": 10, + "successThreshold": 1, + "tcpSocket": { + "port": 8080 + }, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "1", + "memory": "768Mi" + }, + "requests": { + "cpu": "100m", + "memory": "256Mi" + } + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true, + "runAsGroup": 1654, + "runAsNonRoot": true, + "runAsUser": 1654 + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + }, + { + "mountPath": "/tmp", + "name": "tmp" + }, + { + "mountPath": "/app/data", + "name": "app-data" + } + ] + } + ], + "dnsConfig": { + "nameservers": [ + "10.43.0.10" + ], + "options": [ + { + "name": "ndots", + "value": "2" + } + ], + "searches": [ + "fc-llm-bridge.svc.cluster.local", + "svc.cluster.local", + "cluster.local" + ] + }, + "dnsPolicy": "None", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": { + "fsGroup": 1654, + "fsGroupChangePolicy": "OnRootMismatch" + }, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "fc-llm-bridge-data" + } + }, + { + "emptyDir": {}, + "name": "tmp" + }, + { + "emptyDir": {}, + "name": "app-data" + } + ] + } + } + } +} diff --git a/apps-gx10/fc-llm-bridge/ingressroute-fc-llm-bridge.json b/apps-gx10/fc-llm-bridge/ingressroute-fc-llm-bridge.json new file mode 100644 index 0000000..dbb77e8 --- /dev/null +++ b/apps-gx10/fc-llm-bridge/ingressroute-fc-llm-bridge.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "fc-llm-bridge", + "namespace": "fc-llm-bridge" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`fc-llm-bridge.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "fc-llm-bridge", + "port": 8080 + } + ] + } + ], + "tls": { + "secretName": "fc-llm-bridge-tls" + } + } +} diff --git a/apps-gx10/fc-llm-bridge/service-fc-llm-bridge.json b/apps-gx10/fc-llm-bridge/service-fc-llm-bridge.json new file mode 100644 index 0000000..50ef513 --- /dev/null +++ b/apps-gx10/fc-llm-bridge/service-fc-llm-bridge.json @@ -0,0 +1,25 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": {}, + "name": "fc-llm-bridge", + "namespace": "fc-llm-bridge" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 8080, + "protocol": "TCP", + "targetPort": 8080 + } + ], + "selector": { + "app.kubernetes.io/name": "fc-llm-bridge" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-media/configmap-fc-media-config.json b/apps-gx10/fc-media/configmap-fc-media-config.json new file mode 100644 index 0000000..16d9cbe --- /dev/null +++ b/apps-gx10/fc-media/configmap-fc-media-config.json @@ -0,0 +1,11 @@ +{ + "apiVersion": "v1", + "data": { + "appsettings.Production.json": "{\n \"DatabaseProvider\": \"Sqlite\",\n \"ConnectionStrings\": {\n \"Sqlite\": \"Data Source=/data/media.db\"\n },\n \"FlowerCore\": {\n \"Auth\": {\n \"Enabled\": true,\n \"Oidc\": {\n \"Authority\": \"https://id.iamworkin.lan/application/o/media/\",\n \"ClientId\": \"media\",\n \"ClientSecret\": \"\",\n \"Audience\": \"media\",\n \"RequireHttpsMetadata\": true\n }\n },\n \"Tenant\": {\n \"JwtClaimsEnabled\": false,\n \"DefaultTenantHosts\": [ \"media.iamworkin.lan\" ]\n }\n },\n \"Media\": {\n \"LibraryRoot\": \"/media/library\",\n \"Sources\": [\n {\n \"Name\": \"BlueJayNAS Video\",\n \"Driver\": \"Nfs\",\n \"MountedPath\": \"/media/library\",\n \"RemotePath\": \"nfs://10.0.58.3/volume1/video\",\n \"IsEnabled\": true,\n \"IsDefault\": true,\n \"Notes\": \"Synology NFS media share mounted read-only inside the cluster.\"\n }\n ],\n \"GeneratedRoot\": \"/data/generated\",\n \"TranscodeRoot\": \"/data/transcodes\",\n \"InboxPath\": \"/media/inbox\",\n \"InboxScanIntervalMinutes\": 5,\n \"ScanOnStartup\": false,\n \"ComputeChecksums\": false,\n \"FfmpegCommand\": \"ffmpeg\",\n \"FfprobeCommand\": \"ffprobe\",\n \"Hls\": {\n \"MaxConcurrentJobs\": 1\n },\n \"DefaultViewerName\": \"BlueJay\",\n \"Dlna\": {\n \"IsEnabled\": true,\n \"MulticastAddress\": \"239.255.255.250\",\n \"Port\": 1900,\n \"DiscoveryTimeoutSeconds\": 2,\n \"DescriptionFetchTimeoutSeconds\": 2,\n \"MaxResponsesPerSearchTarget\": 32,\n \"SearchTargets\": [\n \"urn:schemas-upnp-org:device:MediaRenderer:1\",\n \"urn:schemas-upnp-org:device:MediaServer:1\"\n ]\n }\n }\n}\n" + }, + "kind": "ConfigMap", + "metadata": { + "name": "fc-media-config", + "namespace": "fc-media" + } +} diff --git a/apps-gx10/fc-media/deployment-fc-media-web.json b/apps-gx10/fc-media/deployment-fc-media-web.json new file mode 100644 index 0000000..0ebd98f --- /dev/null +++ b/apps-gx10/fc-media/deployment-fc-media-web.json @@ -0,0 +1,242 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "fc-media-web", + "app.kubernetes.io/name": "fc-media-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "fc-media-web", + "namespace": "fc-media" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "fc-media-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "flowercore.io/healthz-auth-policy": "allow-anonymous", + "kubectl.kubernetes.io/restartedAt": "2026-04-05T14:14:28-05:00", + "prometheus.io/path": "/metrics", + "prometheus.io/port": "5200", + "prometheus.io/scrape": "true" + }, + "labels": { + "app": "fc-media-web", + "app.kubernetes.io/name": "fc-media-web", + "app.kubernetes.io/part-of": "flowercore" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "ASPNETCORE_ENVIRONMENT", + "value": "Production" + }, + { + "name": "ASPNETCORE_URLS", + "value": "http://+:5200" + }, + { + "name": "FlowerCore__Auth__Enabled", + "value": "true" + }, + { + "name": "FlowerCore__Auth__Oidc__Enabled", + "value": "true" + }, + { + "name": "FlowerCore__Auth__Oidc__Audience", + "value": "media" + }, + { + "name": "FlowerCore__Auth__Oidc__ClientId", + "valueFrom": { + "secretKeyRef": { + "key": "client_id", + "name": "media-oidc-client", + "optional": true + } + } + }, + { + "name": "FlowerCore__Auth__Oidc__ClientSecret", + "valueFrom": { + "secretKeyRef": { + "key": "client_secret", + "name": "media-oidc-client", + "optional": true + } + } + }, + { + "name": "FlowerCore__Auth__Oidc__Authority", + "valueFrom": { + "secretKeyRef": { + "key": "issuer_url", + "name": "media-oidc-client", + "optional": true + } + } + } + ], + "image": "localhost/fc-media-web:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "httpHeaders": [ + { + "name": "X-Forwarded-Proto", + "value": "https" + } + ], + "path": "/healthz", + "port": 5200, + "scheme": "HTTP" + }, + "initialDelaySeconds": 30, + "periodSeconds": 30, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "name": "fc-media-web", + "ports": [ + { + "containerPort": 5200, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "httpHeaders": [ + { + "name": "X-Forwarded-Proto", + "value": "https" + } + ], + "path": "/healthz", + "port": 5200, + "scheme": "HTTP" + }, + "initialDelaySeconds": 5, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "4", + "memory": "4Gi" + }, + "requests": { + "cpu": "500m", + "memory": "1Gi" + } + }, + "startupProbe": { + "failureThreshold": 18, + "httpGet": { + "httpHeaders": [ + { + "name": "X-Forwarded-Proto", + "value": "https" + } + ], + "path": "/healthz", + "port": 5200, + "scheme": "HTTP" + }, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/app/appsettings.Production.json", + "name": "config", + "readOnly": true, + "subPath": "appsettings.Production.json" + }, + { + "mountPath": "/data", + "name": "data" + }, + { + "mountPath": "/data/transcodes", + "name": "transcodes" + }, + { + "mountPath": "/media/library", + "name": "media-library", + "readOnly": true + }, + { + "mountPath": "/media/inbox", + "name": "media-inbox" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "configMap": { + "defaultMode": 420, + "name": "fc-media-config" + }, + "name": "config" + }, + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "fc-media-data" + } + }, + { + "name": "transcodes", + "nfs": { + "path": "/volume1/kubernetes/fc-media-transcodes", + "server": "10.0.58.3" + } + }, + { + "name": "media-inbox", + "nfs": { + "path": "/volume1/kubernetes/fc-media-inbox", + "server": "10.0.58.3" + } + }, + { + "name": "media-library", + "nfs": { + "path": "/volume1/video", + "readOnly": true, + "server": "10.0.58.3" + } + } + ] + } + } + } +} diff --git a/apps-gx10/fc-media/ingressroute-fc-media-web.json b/apps-gx10/fc-media/ingressroute-fc-media-web.json new file mode 100644 index 0000000..68f4405 --- /dev/null +++ b/apps-gx10/fc-media/ingressroute-fc-media-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "fc-media-web", + "namespace": "fc-media" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`media.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "fc-media-web", + "port": 5200 + } + ] + } + ], + "tls": { + "secretName": "fc-media-tls" + } + } +} diff --git a/apps-gx10/fc-media/service-fc-media-web.json b/apps-gx10/fc-media/service-fc-media-web.json new file mode 100644 index 0000000..37798eb --- /dev/null +++ b/apps-gx10/fc-media/service-fc-media-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app": "fc-media-web", + "app.kubernetes.io/name": "fc-media-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "fc-media-web", + "namespace": "fc-media" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 5200, + "protocol": "TCP", + "targetPort": 5200 + } + ], + "selector": { + "app": "fc-media-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-menuboard/configmap-menuboard-web-config.json b/apps-gx10/fc-menuboard/configmap-menuboard-web-config.json new file mode 100644 index 0000000..bb430cb --- /dev/null +++ b/apps-gx10/fc-menuboard/configmap-menuboard-web-config.json @@ -0,0 +1,18 @@ +{ + "apiVersion": "v1", + "data": { + "ASPNETCORE_ENVIRONMENT": "Production", + "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true", + "ASPNETCORE_URLS": "http://+:5000", + "FlowerCore__Database__ConnectionStrings__Sqlite": "Data Source=/data/menuboard.db", + "OTEL_EXPORTER_OTLP_ENDPOINT": "http://otel-collector.monitoring.svc.cluster.local:4317", + "OTEL_EXPORTER_OTLP_PROTOCOL": "grpc", + "OTEL_SERVICE_NAME": "FlowerCore.MenuBoard", + "Security__AllowedOrigins__0": "https://menuboard.iamworkin.lan" + }, + "kind": "ConfigMap", + "metadata": { + "name": "menuboard-web-config", + "namespace": "fc-menuboard" + } +} diff --git a/apps-gx10/fc-menuboard/deployment-menuboard-web.json b/apps-gx10/fc-menuboard/deployment-menuboard-web.json new file mode 100644 index 0000000..a005cf4 --- /dev/null +++ b/apps-gx10/fc-menuboard/deployment-menuboard-web.json @@ -0,0 +1,112 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/name": "menuboard-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "menuboard-web", + "namespace": "fc-menuboard" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "menuboard-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "prometheus.io/path": "/metrics/prometheus", + "prometheus.io/port": "5000", + "prometheus.io/scrape": "true" + }, + "labels": { + "app.kubernetes.io/name": "menuboard-web", + "app.kubernetes.io/part-of": "flowercore" + } + }, + "spec": { + "containers": [ + { + "envFrom": [ + { + "configMapRef": { + "name": "menuboard-web-config" + } + }, + { + "secretRef": { + "name": "menuboard-web-secrets" + } + } + ], + "image": "localhost/fc-menuboard-web:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 5000, + "scheme": "HTTP" + }, + "initialDelaySeconds": 30, + "periodSeconds": 30, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "name": "menuboard-web", + "ports": [ + { + "containerPort": 5000, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 6, + "httpGet": { + "path": "/health", + "port": 5000, + "scheme": "HTTP" + }, + "initialDelaySeconds": 10, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "menuboard-web-data" + } + } + ] + } + } + } +} diff --git a/apps-gx10/fc-menuboard/ingressroute-menuboard-web.json b/apps-gx10/fc-menuboard/ingressroute-menuboard-web.json new file mode 100644 index 0000000..6955add --- /dev/null +++ b/apps-gx10/fc-menuboard/ingressroute-menuboard-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "menuboard-web", + "namespace": "fc-menuboard" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`menuboard.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "menuboard-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "menuboard-web-tls" + } + } +} diff --git a/apps-gx10/fc-menuboard/service-menuboard-web.json b/apps-gx10/fc-menuboard/service-menuboard-web.json new file mode 100644 index 0000000..693b437 --- /dev/null +++ b/apps-gx10/fc-menuboard/service-menuboard-web.json @@ -0,0 +1,28 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app.kubernetes.io/name": "menuboard-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "menuboard-web", + "namespace": "fc-menuboard" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 5000 + } + ], + "selector": { + "app.kubernetes.io/name": "menuboard-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-messageboard/configmap-messageboard-web-config.json b/apps-gx10/fc-messageboard/configmap-messageboard-web-config.json new file mode 100644 index 0000000..1ec04db --- /dev/null +++ b/apps-gx10/fc-messageboard/configmap-messageboard-web-config.json @@ -0,0 +1,18 @@ +{ + "apiVersion": "v1", + "data": { + "ASPNETCORE_ENVIRONMENT": "Production", + "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true", + "ASPNETCORE_URLS": "http://+:8080", + "FlowerCore__Database__ConnectionStrings__Sqlite": "Data Source=/data/messageboard.db", + "OTEL_EXPORTER_OTLP_ENDPOINT": "http://otel-collector.monitoring.svc.cluster.local:4317", + "OTEL_EXPORTER_OTLP_PROTOCOL": "grpc", + "OTEL_SERVICE_NAME": "FlowerCore.MessageBoard", + "Security__AllowedOrigins__0": "https://messageboard.iamworkin.lan" + }, + "kind": "ConfigMap", + "metadata": { + "name": "messageboard-web-config", + "namespace": "fc-messageboard" + } +} diff --git a/apps-gx10/fc-messageboard/deployment-messageboard-web.json b/apps-gx10/fc-messageboard/deployment-messageboard-web.json new file mode 100644 index 0000000..4485f80 --- /dev/null +++ b/apps-gx10/fc-messageboard/deployment-messageboard-web.json @@ -0,0 +1,118 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "messageboard-web" + }, + "name": "messageboard-web", + "namespace": "fc-messageboard" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "messageboard-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "fc.flowercore.io/healthz-anon": "true", + "fc.flowercore.io/probe-path": "/health", + "prometheus.io/path": "/metrics/prometheus", + "prometheus.io/port": "8080", + "prometheus.io/scrape": "true" + }, + "labels": { + "app": "messageboard-web" + } + }, + "spec": { + "containers": [ + { + "envFrom": [ + { + "configMapRef": { + "name": "messageboard-web-config" + } + }, + { + "secretRef": { + "name": "messageboard-web-secrets", + "optional": true + } + } + ], + "image": "localhost/fc-messageboard-web:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "initialDelaySeconds": 10, + "periodSeconds": 30, + "successThreshold": 1, + "tcpSocket": { + "port": 8080 + }, + "timeoutSeconds": 5 + }, + "name": "messageboard-web", + "ports": [ + { + "containerPort": 8080, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 6, + "initialDelaySeconds": 10, + "periodSeconds": 10, + "successThreshold": 1, + "tcpSocket": { + "port": 8080 + }, + "timeoutSeconds": 5 + }, + "resources": { + "limits": { + "cpu": "500m", + "memory": "512Mi" + }, + "requests": { + "cpu": "100m", + "memory": "128Mi" + } + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "messageboard-web-data" + } + } + ] + } + } + } +} diff --git a/apps-gx10/fc-messageboard/ingressroute-messageboard-web.json b/apps-gx10/fc-messageboard/ingressroute-messageboard-web.json new file mode 100644 index 0000000..23a3cad --- /dev/null +++ b/apps-gx10/fc-messageboard/ingressroute-messageboard-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "messageboard-web", + "namespace": "fc-messageboard" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`messageboard.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "messageboard-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "messageboard-web-tls" + } + } +} diff --git a/apps-gx10/fc-messageboard/service-messageboard-web.json b/apps-gx10/fc-messageboard/service-messageboard-web.json new file mode 100644 index 0000000..9402021 --- /dev/null +++ b/apps-gx10/fc-messageboard/service-messageboard-web.json @@ -0,0 +1,25 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": {}, + "name": "messageboard-web", + "namespace": "fc-messageboard" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 8080 + } + ], + "selector": { + "app": "messageboard-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-mysql/configmap-mysql-web-config.json b/apps-gx10/fc-mysql/configmap-mysql-web-config.json new file mode 100644 index 0000000..26f4f8b --- /dev/null +++ b/apps-gx10/fc-mysql/configmap-mysql-web-config.json @@ -0,0 +1,11 @@ +{ + "apiVersion": "v1", + "data": { + "appsettings.Production.json": "{\n \"MySqlManager\": {\n \"CrdNamespace\": \"fc-tenant-default\",\n \"MySqlImage\": \"iwrk-nexus.iamworkin.lan:8444/iwrk-ubuntu-mysql:master\",\n \"PhpMyAdminImage\": \"phpmyadmin/phpmyadmin:latest\",\n \"PhpMyAdminDomain\": \"iamworkin.lan\",\n \"Advisor\": {\n \"DefaultPreset\": \"medium\",\n \"AutoDetectPreset\": true,\n \"MaxAutoPreset\": \"medium\",\n \"PresetOverride\": null\n }\n },\n \"ContainerBackend\": {\n \"Default\": \"Kubernetes\"\n },\n \"FlowerCore\": {\n \"Auth\": {\n \"Provider\": \"Oidc\",\n \"Enabled\": false,\n \"Oidc\": {\n \"Enabled\": true,\n \"Authority\": \"https://id.iamworkin.lan/application/o/mysql/\",\n \"Audience\": \"mysql\",\n \"ClientId\": \"mysql\",\n \"ClientSecret\": \"\"\n }\n },\n \"Tenant\": {\n \"JwtClaimsEnabled\": false,\n \"TenantClaimType\": \"fc:tenant\",\n \"ActorIdClaimType\": \"flowercore_actor_id\"\n },\n \"Database\": {\n \"Provider\": \"Sqlite\",\n \"ConnectionStrings\": {\n \"Sqlite\": \"Data Source=/data/mysql-manager.db\"\n }\n }\n }\n}\n" + }, + "kind": "ConfigMap", + "metadata": { + "name": "mysql-web-config", + "namespace": "fc-mysql" + } +} diff --git a/apps-gx10/fc-mysql/deployment-mysql-web.json b/apps-gx10/fc-mysql/deployment-mysql-web.json new file mode 100644 index 0000000..197bebf --- /dev/null +++ b/apps-gx10/fc-mysql/deployment-mysql-web.json @@ -0,0 +1,209 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/managed-by": "flowercore", + "app.kubernetes.io/name": "mysql-web" + }, + "name": "mysql-web", + "namespace": "fc-mysql" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "mysql-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "kubectl.kubernetes.io/restartedAt": "2026-04-17T19:52:14-05:00", + "prometheus.io/path": "/metrics/prometheus", + "prometheus.io/port": "5300", + "prometheus.io/scrape": "true" + }, + "labels": { + "app.kubernetes.io/name": "mysql-web" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "FlowerCore__Auth__Enabled", + "value": "false" + }, + { + "name": "FlowerCore__Auth__Oidc__Authority", + "valueFrom": { + "secretKeyRef": { + "key": "issuer_url", + "name": "mysql-oidc-client", + "optional": true + } + } + }, + { + "name": "FlowerCore__Auth__Oidc__ClientId", + "valueFrom": { + "secretKeyRef": { + "key": "client_id", + "name": "mysql-oidc-client", + "optional": true + } + } + }, + { + "name": "FlowerCore__Auth__Oidc__ClientSecret", + "valueFrom": { + "secretKeyRef": { + "key": "client_secret", + "name": "mysql-oidc-client", + "optional": true + } + } + }, + { + "name": "FlowerCore__Auth__Oidc__Audience", + "value": "mysql" + } + ], + "image": "localhost/fc-mysql-web:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/metrics/prometheus", + "port": 5300, + "scheme": "HTTP" + }, + "initialDelaySeconds": 20, + "periodSeconds": 30, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "name": "mysql-web", + "ports": [ + { + "containerPort": 5300, + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/metrics/prometheus", + "port": 5300, + "scheme": "HTTP" + }, + "initialDelaySeconds": 10, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "500m", + "memory": "512Mi" + }, + "requests": { + "cpu": "100m", + "memory": "128Mi" + } + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + }, + { + "mountPath": "/tmp", + "name": "tmp" + }, + { + "mountPath": "/app/logs", + "name": "logs" + }, + { + "mountPath": "/app/appsettings.Production.json", + "name": "config", + "readOnly": true, + "subPath": "appsettings.Production.json" + } + ] + } + ], + "dnsConfig": { + "nameservers": [ + "10.43.0.10" + ], + "options": [ + { + "name": "ndots", + "value": "2" + } + ], + "searches": [ + "fc-mysql.svc.cluster.local", + "svc.cluster.local", + "cluster.local" + ] + }, + "dnsPolicy": "None", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": { + "fsGroup": 1654, + "runAsGroup": 1654, + "runAsNonRoot": true, + "runAsUser": 1654 + }, + "serviceAccount": "mysql-web", + "serviceAccountName": "mysql-web", + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "mysql-web-data" + } + }, + { + "emptyDir": {}, + "name": "tmp" + }, + { + "emptyDir": {}, + "name": "logs" + }, + { + "configMap": { + "defaultMode": 420, + "name": "mysql-web-config" + }, + "name": "config" + } + ] + } + } + } +} diff --git a/apps-gx10/fc-mysql/ingressroute-mysql-web.json b/apps-gx10/fc-mysql/ingressroute-mysql-web.json new file mode 100644 index 0000000..04aeba4 --- /dev/null +++ b/apps-gx10/fc-mysql/ingressroute-mysql-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "mysql-web", + "namespace": "fc-mysql" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`mysql.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "mysql-web", + "port": 5300 + } + ] + } + ], + "tls": { + "secretName": "mysql-web-tls" + } + } +} diff --git a/apps-gx10/fc-mysql/service-mysql-web.json b/apps-gx10/fc-mysql/service-mysql-web.json new file mode 100644 index 0000000..754c172 --- /dev/null +++ b/apps-gx10/fc-mysql/service-mysql-web.json @@ -0,0 +1,23 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "name": "mysql-web", + "namespace": "fc-mysql" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "port": 5300, + "protocol": "TCP", + "targetPort": 5300 + } + ], + "selector": { + "app.kubernetes.io/name": "mysql-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-mysql/serviceaccount-mysql-web.json b/apps-gx10/fc-mysql/serviceaccount-mysql-web.json new file mode 100644 index 0000000..1663283 --- /dev/null +++ b/apps-gx10/fc-mysql/serviceaccount-mysql-web.json @@ -0,0 +1,8 @@ +{ + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": { + "name": "mysql-web", + "namespace": "fc-mysql" + } +} diff --git a/apps-gx10/fc-network/certificate-fc-network-web-tls.json b/apps-gx10/fc-network/certificate-fc-network-web-tls.json new file mode 100644 index 0000000..e32e72d --- /dev/null +++ b/apps-gx10/fc-network/certificate-fc-network-web-tls.json @@ -0,0 +1,18 @@ +{ + "apiVersion": "cert-manager.io/v1", + "kind": "Certificate", + "metadata": { + "name": "fc-network-web-tls", + "namespace": "fc-network" + }, + "spec": { + "dnsNames": [ + "network.iamworkin.lan" + ], + "issuerRef": { + "kind": "ClusterIssuer", + "name": "step-ca-acme" + }, + "secretName": "fc-network-web-tls" + } +} diff --git a/apps-gx10/fc-network/deployment-fc-network-web.json b/apps-gx10/fc-network/deployment-fc-network-web.json new file mode 100644 index 0000000..8b4dca4 --- /dev/null +++ b/apps-gx10/fc-network/deployment-fc-network-web.json @@ -0,0 +1,210 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "fc-network-web", + "app.kubernetes.io/component": "web", + "app.kubernetes.io/managed-by": "argocd", + "app.kubernetes.io/name": "fc-network-web", + "app.kubernetes.io/part-of": "flowercore", + "flowercore.io/created-by": "bluejay-infra", + "flowercore.io/tenant-id": "system" + }, + "name": "fc-network-web", + "namespace": "fc-network" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 3, + "selector": { + "matchLabels": { + "app": "fc-network-web" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": 0, + "maxUnavailable": 1 + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "annotations": { + "fc.flowercore.io/healthz-anon": "true", + "fc.flowercore.io/probe-path": "/healthz", + "flowercore.io/audit-trace-id": "runtime-activity-trace", + "prometheus.io/path": "/metrics/prometheus", + "prometheus.io/port": "5340", + "prometheus.io/scrape": "true" + }, + "labels": { + "app": "fc-network-web", + "app.kubernetes.io/component": "web", + "app.kubernetes.io/managed-by": "argocd", + "app.kubernetes.io/name": "fc-network-web", + "app.kubernetes.io/part-of": "flowercore", + "flowercore.io/created-by": "bluejay-infra", + "flowercore.io/tenant-id": "system" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "ASPNETCORE_URLS", + "value": "http://+:5340" + }, + { + "name": "ASPNETCORE_ENVIRONMENT", + "value": "Production" + }, + { + "name": "DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", + "value": "false" + }, + { + "name": "HOME", + "value": "/data" + }, + { + "name": "FlowerCore__Auth__Enabled", + "value": "false" + }, + { + "name": "FlowerCore__Database__Provider", + "value": "Sqlite" + }, + { + "name": "FlowerCore__Database__ConnectionStrings__Sqlite", + "value": "Data Source=/data/network.db" + }, + { + "name": "FlowerCore__Network__SnapshotStore__RootDirectory", + "value": "/data/snapshots" + }, + { + "name": "FlowerCore__Network__SnapshotStore__UseGitHistory", + "value": "true" + }, + { + "name": "FlowerCore__Network__IntendedModel__FilePath", + "value": "/data/intended.json" + } + ], + "image": "localhost/fc-network-web:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 5340, + "scheme": "HTTP" + }, + "initialDelaySeconds": 30, + "periodSeconds": 30, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "name": "web", + "ports": [ + { + "containerPort": 5340, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 5340, + "scheme": "HTTP" + }, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "500m", + "memory": "512Mi" + }, + "requests": { + "cpu": "50m", + "memory": "128Mi" + } + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true, + "runAsGroup": 1654, + "runAsNonRoot": true, + "runAsUser": 1654 + }, + "startupProbe": { + "failureThreshold": 30, + "httpGet": { + "path": "/healthz", + "port": 5340, + "scheme": "HTTP" + }, + "initialDelaySeconds": 5, + "periodSeconds": 5, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + }, + { + "mountPath": "/tmp", + "name": "tmp" + }, + { + "mountPath": "/app/logs", + "name": "logs" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": { + "fsGroup": 1654, + "fsGroupChangePolicy": "OnRootMismatch" + }, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "fc-network-web-data" + } + }, + { + "emptyDir": {}, + "name": "tmp" + }, + { + "emptyDir": {}, + "name": "logs" + } + ] + } + } + } +} diff --git a/apps-gx10/fc-network/ingressroute-fc-network-web.json b/apps-gx10/fc-network/ingressroute-fc-network-web.json new file mode 100644 index 0000000..f385c4a --- /dev/null +++ b/apps-gx10/fc-network/ingressroute-fc-network-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "fc-network-web", + "namespace": "fc-network" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`network.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "fc-network-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "fc-network-web-tls" + } + } +} diff --git a/apps-gx10/fc-network/service-fc-network-web.json b/apps-gx10/fc-network/service-fc-network-web.json new file mode 100644 index 0000000..e6007a8 --- /dev/null +++ b/apps-gx10/fc-network/service-fc-network-web.json @@ -0,0 +1,33 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app": "fc-network-web", + "app.kubernetes.io/component": "web", + "app.kubernetes.io/managed-by": "argocd", + "app.kubernetes.io/name": "fc-network-web", + "app.kubernetes.io/part-of": "flowercore", + "flowercore.io/created-by": "bluejay-infra", + "flowercore.io/tenant-id": "system" + }, + "name": "fc-network-web", + "namespace": "fc-network" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 5340 + } + ], + "selector": { + "app": "fc-network-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-php/configmap-php-web-config.json b/apps-gx10/fc-php/configmap-php-web-config.json new file mode 100644 index 0000000..4b7b73a --- /dev/null +++ b/apps-gx10/fc-php/configmap-php-web-config.json @@ -0,0 +1,11 @@ +{ + "apiVersion": "v1", + "data": { + "appsettings.Production.json": "{\n \"PhpManager\": {\n \"Namespace\": \"fc-php\",\n \"Slowlog\": {\n \"Path\": \"/var/log/apache2/php-fpm-slow.log\",\n \"Sidecar\": {\n \"Enabled\": true,\n \"Image\": \"\"\n }\n },\n \"PoolConfig\": {\n \"StartServers\": null,\n \"MinSpareServers\": null,\n \"MaxSpareServers\": null,\n \"ProcessIdleTimeoutSeconds\": 10,\n \"RequestTerminateTimeoutSeconds\": 30\n },\n \"Certificates\": {\n \"TlsInspector\": {\n \"LogGracefulDegradeWarnings\": false\n }\n },\n \"Backups\": {\n \"StoragePath\": \"/data/backups\"\n }\n },\n \"ApplicationArchives\": {\n \"WordPressCoreUrl\": \"http://php-web.fc-php.svc.cluster.local.:5400/api/v1/application-archives/wordpress/latest.tar.gz\",\n \"WordPressProxySourceUrl\": \"https://wordpress.org/latest.tar.gz\",\n \"WordPressLocalArchivePath\": \"/data/application-archives/latest.tar.gz\",\n \"MyBbCoreUrl\": \"http://php-web.fc-php.svc.cluster.local.:5400/api/v1/application-archives/mybb/latest.zip\",\n \"MyBbProxySourceUrl\": \"https://mybb.com/download/\",\n \"MyBbLocalArchivePath\": \"/data/application-archives/mybb-latest.zip\",\n \"MediaWikiCoreUrl\": \"http://php-web.fc-php.svc.cluster.local.:5400/api/v1/application-archives/mediawiki/latest.tar.gz\",\n \"MediaWikiProxySourceUrl\": \"https://releases.wikimedia.org/mediawiki/1.45/mediawiki-1.45.3.tar.gz\",\n \"MediaWikiLocalArchivePath\": \"/data/application-archives/mediawiki-latest.tar.gz\",\n \"DrupalCoreUrl\": \"http://php-web.fc-php.svc.cluster.local.:5400/api/v1/application-archives/drupal/latest.tar.gz\",\n \"DrupalProxySourceUrl\": \"https://ftp.drupal.org/files/projects/drupal-11.3.8.tar.gz\",\n \"DrupalLocalArchivePath\": \"/data/application-archives/drupal-latest.tar.gz\",\n \"BypassUpstreamTls\": true\n },\n \"ContainerBackend\": {\n \"Default\": \"Kubernetes\"\n },\n \"FlowerCore\": {\n \"Auth\": {\n \"Provider\": \"Oidc\",\n \"Enabled\": false,\n \"Oidc\": {\n \"Enabled\": true,\n \"Authority\": \"https://id.iamworkin.lan/application/o/php/\",\n \"Audience\": \"php\",\n \"ClientId\": \"php\",\n \"ClientSecret\": \"\"\n },\n \"Impersonation\": {\n \"Enabled\": false,\n \"DebugMode\": false\n }\n },\n \"Tenant\": {\n \"StrictMode\": false,\n \"JwtClaimsEnabled\": false,\n \"TenantClaimType\": \"fc:tenant\",\n \"ActorIdClaimType\": \"flowercore_actor_id\"\n },\n \"Account\": {\n \"AppId\": \"php\",\n \"DefaultTenantId\": \"default\",\n \"Impersonation\": {\n \"Enabled\": false,\n \"StrictMode\": false,\n \"TechSupportRoles\": [ \"tech-support\" ],\n \"Targets\": []\n }\n },\n \"Hosting\": {\n \"AutoDns\": {\n \"Enabled\": true,\n \"DnsManagerBaseUrl\": \"https://dns.iamworkin.lan/\",\n \"ZoneName\": \"iamworkin.lan\",\n \"RecordType\": \"A\",\n \"TargetAddress\": \"10.0.56.200\",\n \"Ttl\": 300,\n \"BypassTls\": true\n }\n },\n \"Database\": {\n \"Provider\": \"Sqlite\",\n \"ConnectionStrings\": {\n \"Sqlite\": \"Data Source=/data/php-manager.db\"\n }\n }\n }\n}\n" + }, + "kind": "ConfigMap", + "metadata": { + "name": "php-web-config", + "namespace": "fc-php" + } +} diff --git a/apps-gx10/fc-php/deployment-php-web.json b/apps-gx10/fc-php/deployment-php-web.json new file mode 100644 index 0000000..0292344 --- /dev/null +++ b/apps-gx10/fc-php/deployment-php-web.json @@ -0,0 +1,209 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/managed-by": "flowercore", + "app.kubernetes.io/name": "php-web" + }, + "name": "php-web", + "namespace": "fc-php" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "php-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "kubectl.kubernetes.io/restartedAt": "2026-06-13T01:59:27-05:00", + "prometheus.io/path": "/metrics/prometheus", + "prometheus.io/port": "5400", + "prometheus.io/scrape": "true" + }, + "labels": { + "app.kubernetes.io/name": "php-web" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "FlowerCore__Auth__Enabled", + "value": "false" + }, + { + "name": "FlowerCore__Auth__Oidc__Authority", + "valueFrom": { + "secretKeyRef": { + "key": "issuer_url", + "name": "php-oidc-client", + "optional": true + } + } + }, + { + "name": "FlowerCore__Auth__Oidc__ClientId", + "valueFrom": { + "secretKeyRef": { + "key": "client_id", + "name": "php-oidc-client", + "optional": true + } + } + }, + { + "name": "FlowerCore__Auth__Oidc__ClientSecret", + "valueFrom": { + "secretKeyRef": { + "key": "client_secret", + "name": "php-oidc-client", + "optional": true + } + } + }, + { + "name": "FlowerCore__Auth__Oidc__Audience", + "value": "php" + } + ], + "image": "localhost/fc-php-web:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/metrics/prometheus", + "port": 5400, + "scheme": "HTTP" + }, + "initialDelaySeconds": 20, + "periodSeconds": 30, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "name": "php-web", + "ports": [ + { + "containerPort": 5400, + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/metrics/prometheus", + "port": 5400, + "scheme": "HTTP" + }, + "initialDelaySeconds": 10, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "500m", + "memory": "512Mi" + }, + "requests": { + "cpu": "100m", + "memory": "128Mi" + } + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + }, + { + "mountPath": "/tmp", + "name": "tmp" + }, + { + "mountPath": "/app/logs", + "name": "logs" + }, + { + "mountPath": "/app/appsettings.Production.json", + "name": "config", + "readOnly": true, + "subPath": "appsettings.Production.json" + } + ] + } + ], + "dnsConfig": { + "nameservers": [ + "10.43.0.10" + ], + "options": [ + { + "name": "ndots", + "value": "2" + } + ], + "searches": [ + "fc-php.svc.cluster.local", + "svc.cluster.local", + "cluster.local" + ] + }, + "dnsPolicy": "None", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": { + "fsGroup": 1654, + "runAsGroup": 1654, + "runAsNonRoot": true, + "runAsUser": 1654 + }, + "serviceAccount": "php-web", + "serviceAccountName": "php-web", + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "php-web-data" + } + }, + { + "emptyDir": {}, + "name": "tmp" + }, + { + "emptyDir": {}, + "name": "logs" + }, + { + "configMap": { + "defaultMode": 420, + "name": "php-web-config" + }, + "name": "config" + } + ] + } + } + } +} diff --git a/apps-gx10/fc-php/service-php-web.json b/apps-gx10/fc-php/service-php-web.json new file mode 100644 index 0000000..11cd367 --- /dev/null +++ b/apps-gx10/fc-php/service-php-web.json @@ -0,0 +1,23 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "name": "php-web", + "namespace": "fc-php" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "port": 5400, + "protocol": "TCP", + "targetPort": 5400 + } + ], + "selector": { + "app.kubernetes.io/name": "php-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-php/serviceaccount-php-web.json b/apps-gx10/fc-php/serviceaccount-php-web.json new file mode 100644 index 0000000..0dfa500 --- /dev/null +++ b/apps-gx10/fc-php/serviceaccount-php-web.json @@ -0,0 +1,8 @@ +{ + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": { + "name": "php-web", + "namespace": "fc-php" + } +} diff --git a/apps-gx10/fc-presentations/configmap-presentations-web-config.json b/apps-gx10/fc-presentations/configmap-presentations-web-config.json new file mode 100644 index 0000000..75240e0 --- /dev/null +++ b/apps-gx10/fc-presentations/configmap-presentations-web-config.json @@ -0,0 +1,22 @@ +{ + "apiVersion": "v1", + "data": { + "ASPNETCORE_ENVIRONMENT": "Production", + "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true", + "ASPNETCORE_URLS": "http://+:8080", + "FlowerCore__Database__ConnectionStrings__Sqlite": "Data Source=/data/presentations.db", + "FlowerCore__Database__Provider": "Sqlite", + "OTEL_EXPORTER_OTLP_ENDPOINT": "http://otel-collector.monitoring.svc.cluster.local:4317", + "OTEL_EXPORTER_OTLP_PROTOCOL": "grpc", + "OTEL_SERVICE_NAME": "FlowerCore.Presentations", + "PresentationStorage__HtmlBundlesRelativePath": "uploads/html-bundles", + "PresentationStorage__ImportsRelativePath": "uploads/imports", + "PresentationStorage__SlidesRelativePath": "uploads/slides", + "Security__AllowedOrigins__0": "https://presentations.iamworkin.lan" + }, + "kind": "ConfigMap", + "metadata": { + "name": "presentations-web-config", + "namespace": "fc-presentations" + } +} diff --git a/apps-gx10/fc-presentations/deployment-presentations-web.json b/apps-gx10/fc-presentations/deployment-presentations-web.json new file mode 100644 index 0000000..7aaddc4 --- /dev/null +++ b/apps-gx10/fc-presentations/deployment-presentations-web.json @@ -0,0 +1,143 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/name": "presentations-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "presentations-web", + "namespace": "fc-presentations" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "presentations-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "kubectl.kubernetes.io/restartedAt": "2026-04-23T14:47:39-05:00", + "prometheus.io/path": "/metrics/prometheus", + "prometheus.io/port": "8080", + "prometheus.io/scrape": "true" + }, + "labels": { + "app.kubernetes.io/name": "presentations-web", + "app.kubernetes.io/part-of": "flowercore" + } + }, + "spec": { + "containers": [ + { + "envFrom": [ + { + "configMapRef": { + "name": "presentations-web-config" + } + }, + { + "secretRef": { + "name": "presentations-web-secrets" + } + } + ], + "image": "localhost/fc-presentations:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 30, + "periodSeconds": 30, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "name": "presentations-web", + "ports": [ + { + "containerPort": 8080, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 6, + "httpGet": { + "path": "/health", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 10, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data", + "subPath": "data" + }, + { + "mountPath": "/home/app/wwwroot/uploads", + "name": "data", + "subPath": "uploads" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "initContainers": [ + { + "command": [ + "/bin/sh", + "-lc", + "set -eu\nmkdir -p /mnt/pvc/data /mnt/pvc/uploads\n\nfor file in presentations.db presentations.db-shm presentations.db-wal; do\n if [ -f \"/mnt/pvc/${file}\" ] && [ ! -f \"/mnt/pvc/data/${file}\" ]; then\n mv \"/mnt/pvc/${file}\" \"/mnt/pvc/data/${file}\"\n fi\ndone\n\nif [ -d /mnt/pvc/dp-keys ] && [ ! -d /mnt/pvc/data/dp-keys ]; then\n mv /mnt/pvc/dp-keys /mnt/pvc/data/dp-keys\nfi\n\nfor directory in imports slides html-bundles; do\n if [ -d \"/mnt/pvc/${directory}\" ] && [ ! -d \"/mnt/pvc/uploads/${directory}\" ]; then\n mv \"/mnt/pvc/${directory}\" \"/mnt/pvc/uploads/${directory}\"\n fi\ndone\n\nmkdir -p \\\n /mnt/pvc/data/dp-keys \\\n /mnt/pvc/uploads/imports \\\n /mnt/pvc/uploads/slides \\\n /mnt/pvc/uploads/html-bundles\n" + ], + "image": "localhost/fc-presentations:gx10-v1", + "imagePullPolicy": "Never", + "name": "storage-init", + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/mnt/pvc", + "name": "data" + } + ] + } + ], + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": { + "fsGroup": 1654, + "fsGroupChangePolicy": "OnRootMismatch" + }, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "presentations-web-data" + } + } + ] + } + } + } +} diff --git a/apps-gx10/fc-presentations/ingressroute-presentations-web.json b/apps-gx10/fc-presentations/ingressroute-presentations-web.json new file mode 100644 index 0000000..d9c4556 --- /dev/null +++ b/apps-gx10/fc-presentations/ingressroute-presentations-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "presentations-web", + "namespace": "fc-presentations" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`presentations.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "presentations-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "presentations-web-tls" + } + } +} diff --git a/apps-gx10/fc-presentations/service-presentations-web.json b/apps-gx10/fc-presentations/service-presentations-web.json new file mode 100644 index 0000000..cf418fc --- /dev/null +++ b/apps-gx10/fc-presentations/service-presentations-web.json @@ -0,0 +1,28 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app.kubernetes.io/name": "presentations-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "presentations-web", + "namespace": "fc-presentations" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 8080 + } + ], + "selector": { + "app.kubernetes.io/name": "presentations-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-retail/configmap-retail-web-config.json b/apps-gx10/fc-retail/configmap-retail-web-config.json new file mode 100644 index 0000000..5df5f64 --- /dev/null +++ b/apps-gx10/fc-retail/configmap-retail-web-config.json @@ -0,0 +1,20 @@ +{ + "apiVersion": "v1", + "data": { + "ASPNETCORE_ENVIRONMENT": "Production", + "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true", + "ASPNETCORE_URLS": "http://+:5000", + "FlowerCore__Database__ConnectionStrings__Sqlite": "Data Source=/data/retail.db", + "FlowerCore__Database__Provider": "Sqlite", + "FlowerCore__Retail__BaseUrl": "https://retail.iamworkin.lan", + "OTEL_EXPORTER_OTLP_ENDPOINT": "http://otel-collector.monitoring.svc.cluster.local:4317", + "OTEL_EXPORTER_OTLP_PROTOCOL": "grpc", + "OTEL_SERVICE_NAME": "FlowerCore.Retail", + "PrintService__BaseUrl": "http://print.iamworkin.lan:5200" + }, + "kind": "ConfigMap", + "metadata": { + "name": "retail-web-config", + "namespace": "fc-retail" + } +} diff --git a/apps-gx10/fc-retail/deployment-retail-web.json b/apps-gx10/fc-retail/deployment-retail-web.json new file mode 100644 index 0000000..df467c1 --- /dev/null +++ b/apps-gx10/fc-retail/deployment-retail-web.json @@ -0,0 +1,111 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/managed-by": "argocd", + "app.kubernetes.io/name": "retail-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "retail-web", + "namespace": "fc-retail" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 3, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "retail-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "fc.flowercore.io/healthz-anon": "true", + "fc.flowercore.io/probe-path": "/healthz", + "kubectl.kubernetes.io/restartedAt": "2026-06-02T01:34:08-05:00", + "prometheus.io/path": "/metrics/prometheus", + "prometheus.io/port": "5000", + "prometheus.io/scrape": "true" + }, + "labels": { + "app.kubernetes.io/name": "retail-web", + "app.kubernetes.io/part-of": "flowercore" + } + }, + "spec": { + "containers": [ + { + "envFrom": [ + { + "configMapRef": { + "name": "retail-web-config" + } + } + ], + "image": "localhost/fc-retail-web:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 5000, + "scheme": "HTTP" + }, + "initialDelaySeconds": 30, + "periodSeconds": 30, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "name": "retail-web", + "ports": [ + { + "containerPort": 5000, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 6, + "httpGet": { + "path": "/health", + "port": 5000, + "scheme": "HTTP" + }, + "initialDelaySeconds": 10, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "retail-web-data" + } + } + ] + } + } + } +} diff --git a/apps-gx10/fc-retail/ingressroute-retail-web.json b/apps-gx10/fc-retail/ingressroute-retail-web.json new file mode 100644 index 0000000..9effd81 --- /dev/null +++ b/apps-gx10/fc-retail/ingressroute-retail-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "retail-web", + "namespace": "fc-retail" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`retail.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "retail-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "retail-web-tls" + } + } +} diff --git a/apps-gx10/fc-retail/service-retail-web.json b/apps-gx10/fc-retail/service-retail-web.json new file mode 100644 index 0000000..9b4acf3 --- /dev/null +++ b/apps-gx10/fc-retail/service-retail-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app.kubernetes.io/managed-by": "argocd", + "app.kubernetes.io/name": "retail-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "retail-web", + "namespace": "fc-retail" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 5000 + } + ], + "selector": { + "app.kubernetes.io/name": "retail-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-scoreboard/configmap-scoreboard-web-config.json b/apps-gx10/fc-scoreboard/configmap-scoreboard-web-config.json new file mode 100644 index 0000000..e95a6ad --- /dev/null +++ b/apps-gx10/fc-scoreboard/configmap-scoreboard-web-config.json @@ -0,0 +1,21 @@ +{ + "apiVersion": "v1", + "data": { + "ASPNETCORE_ENVIRONMENT": "Production", + "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true", + "ASPNETCORE_URLS": "http://+:8080", + "Auth__ApiKey": "change-me", + "FlowerCore__Database__ConnectionStrings__Sqlite": "Data Source=/data/scoreboard.db", + "FlowerCore__Database__Provider": "Sqlite", + "OTEL_EXPORTER_OTLP_ENDPOINT": "http://otel-collector.monitoring.svc.cluster.local:4317", + "OTEL_EXPORTER_OTLP_PROTOCOL": "grpc", + "OTEL_SERVICE_NAME": "FlowerCore.Scoreboard", + "Security__AllowedOrigins__0": "https://scoreboard.iamworkin.lan", + "Security__ApiKey": "change-me" + }, + "kind": "ConfigMap", + "metadata": { + "name": "scoreboard-web-config", + "namespace": "fc-scoreboard" + } +} diff --git a/apps-gx10/fc-scoreboard/deployment-scoreboard-web.json b/apps-gx10/fc-scoreboard/deployment-scoreboard-web.json new file mode 100644 index 0000000..ac8d2af --- /dev/null +++ b/apps-gx10/fc-scoreboard/deployment-scoreboard-web.json @@ -0,0 +1,132 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/name": "scoreboard-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "scoreboard-web", + "namespace": "fc-scoreboard" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "scoreboard-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "kubectl.kubernetes.io/restartedAt": "2026-06-12T16:43:22-05:00", + "prometheus.io/path": "/metrics/prometheus", + "prometheus.io/port": "8080", + "prometheus.io/scrape": "true" + }, + "labels": { + "app.kubernetes.io/name": "scoreboard-web", + "app.kubernetes.io/part-of": "flowercore" + } + }, + "spec": { + "containers": [ + { + "envFrom": [ + { + "configMapRef": { + "name": "scoreboard-web-config" + } + } + ], + "image": "localhost/fc-scoreboard-web:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "initialDelaySeconds": 30, + "periodSeconds": 30, + "successThreshold": 1, + "tcpSocket": { + "port": 8080 + }, + "timeoutSeconds": 5 + }, + "name": "scoreboard-web", + "ports": [ + { + "containerPort": 8080, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 6, + "initialDelaySeconds": 10, + "periodSeconds": 10, + "successThreshold": 1, + "tcpSocket": { + "port": 8080 + }, + "timeoutSeconds": 5 + }, + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "initContainers": [ + { + "command": [ + "/bin/sh", + "-c", + "chown -R 1654:1654 /data && chmod -R u+rwX,g+rwX /data" + ], + "image": "localhost/fc-scoreboard-web:gx10-v1", + "imagePullPolicy": "Never", + "name": "scoreboard-data-permissions", + "resources": {}, + "securityContext": { + "runAsGroup": 0, + "runAsUser": 0 + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + } + ] + } + ], + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": { + "fsGroup": 1654, + "fsGroupChangePolicy": "OnRootMismatch" + }, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "scoreboard-web-data" + } + } + ] + } + } + } +} diff --git a/apps-gx10/fc-scoreboard/ingressroute-scoreboard-web.json b/apps-gx10/fc-scoreboard/ingressroute-scoreboard-web.json new file mode 100644 index 0000000..d5fdc94 --- /dev/null +++ b/apps-gx10/fc-scoreboard/ingressroute-scoreboard-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "scoreboard-web", + "namespace": "fc-scoreboard" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`scoreboard.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "scoreboard-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "scoreboard-web-tls" + } + } +} diff --git a/apps-gx10/fc-scoreboard/service-scoreboard-web.json b/apps-gx10/fc-scoreboard/service-scoreboard-web.json new file mode 100644 index 0000000..35ec4bb --- /dev/null +++ b/apps-gx10/fc-scoreboard/service-scoreboard-web.json @@ -0,0 +1,28 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app.kubernetes.io/name": "scoreboard-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "scoreboard-web", + "namespace": "fc-scoreboard" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 8080 + } + ], + "selector": { + "app.kubernetes.io/name": "scoreboard-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-segmentdisplay/configmap-segmentdisplay-web-config.json b/apps-gx10/fc-segmentdisplay/configmap-segmentdisplay-web-config.json new file mode 100644 index 0000000..6a3ccdf --- /dev/null +++ b/apps-gx10/fc-segmentdisplay/configmap-segmentdisplay-web-config.json @@ -0,0 +1,19 @@ +{ + "apiVersion": "v1", + "data": { + "ASPNETCORE_ENVIRONMENT": "Production", + "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true", + "ASPNETCORE_URLS": "http://+:8080", + "FlowerCore__Database__ConnectionStrings__Sqlite": "Data Source=/data/segmentdisplay.db", + "FlowerCore__Database__Provider": "Sqlite", + "OTEL_EXPORTER_OTLP_ENDPOINT": "http://otel-collector.monitoring.svc.cluster.local:4317", + "OTEL_EXPORTER_OTLP_PROTOCOL": "grpc", + "OTEL_SERVICE_NAME": "FlowerCore.SegmentDisplay", + "Security__AllowedOrigins__0": "https://segmentdisplay.iamworkin.lan" + }, + "kind": "ConfigMap", + "metadata": { + "name": "segmentdisplay-web-config", + "namespace": "fc-segmentdisplay" + } +} diff --git a/apps-gx10/fc-segmentdisplay/deployment-segmentdisplay-web.json b/apps-gx10/fc-segmentdisplay/deployment-segmentdisplay-web.json new file mode 100644 index 0000000..3c91745 --- /dev/null +++ b/apps-gx10/fc-segmentdisplay/deployment-segmentdisplay-web.json @@ -0,0 +1,113 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/name": "segmentdisplay-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "segmentdisplay-web", + "namespace": "fc-segmentdisplay" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "segmentdisplay-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "prometheus.io/path": "/metrics/prometheus", + "prometheus.io/port": "8080", + "prometheus.io/scrape": "true" + }, + "labels": { + "app.kubernetes.io/name": "segmentdisplay-web", + "app.kubernetes.io/part-of": "flowercore" + } + }, + "spec": { + "containers": [ + { + "envFrom": [ + { + "configMapRef": { + "name": "segmentdisplay-web-config" + } + }, + { + "secretRef": { + "name": "segmentdisplay-web-secrets", + "optional": true + } + } + ], + "image": "localhost/fc-segmentdisplay-web:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 30, + "periodSeconds": 30, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "name": "segmentdisplay-web", + "ports": [ + { + "containerPort": 8080, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 6, + "httpGet": { + "path": "/health", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 10, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "segmentdisplay-web-data" + } + } + ] + } + } + } +} diff --git a/apps-gx10/fc-segmentdisplay/ingressroute-segmentdisplay-web.json b/apps-gx10/fc-segmentdisplay/ingressroute-segmentdisplay-web.json new file mode 100644 index 0000000..36f0474 --- /dev/null +++ b/apps-gx10/fc-segmentdisplay/ingressroute-segmentdisplay-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "segmentdisplay-web", + "namespace": "fc-segmentdisplay" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`segmentdisplay.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "segmentdisplay-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "segmentdisplay-web-tls" + } + } +} diff --git a/apps-gx10/fc-segmentdisplay/service-segmentdisplay-web.json b/apps-gx10/fc-segmentdisplay/service-segmentdisplay-web.json new file mode 100644 index 0000000..91a2430 --- /dev/null +++ b/apps-gx10/fc-segmentdisplay/service-segmentdisplay-web.json @@ -0,0 +1,28 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app.kubernetes.io/name": "segmentdisplay-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "segmentdisplay-web", + "namespace": "fc-segmentdisplay" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 8080 + } + ], + "selector": { + "app.kubernetes.io/name": "segmentdisplay-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-signage/deployment-signage-replay-web.json b/apps-gx10/fc-signage/deployment-signage-replay-web.json new file mode 100644 index 0000000..044b2f4 --- /dev/null +++ b/apps-gx10/fc-signage/deployment-signage-replay-web.json @@ -0,0 +1,151 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "signage-replay-web" + }, + "name": "signage-replay-web", + "namespace": "fc-signage" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "signage-replay-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "kubectl.kubernetes.io/restartedAt": "2026-05-04T13:50:05-05:00" + }, + "labels": { + "app": "signage-replay-web" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "ASPNETCORE_URLS", + "value": "http://+:5280" + }, + { + "name": "ASPNETCORE_ENVIRONMENT", + "value": "Production" + }, + { + "name": "ReplayFederation__Signage__Enabled", + "value": "true" + }, + { + "name": "ReplayFederation__Signage__BaseUrl", + "value": "http://signage-web.fc-signage.svc.cluster.local.:5190" + }, + { + "name": "ReplayFederation__Dms__Enabled", + "value": "true" + }, + { + "name": "ReplayFederation__Dms__BaseUrl", + "value": "http://dms-web.fc-dms.svc.cluster.local.:8081" + } + ], + "image": "localhost/fc-signage-replay-web:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 5280, + "scheme": "HTTP" + }, + "initialDelaySeconds": 20, + "periodSeconds": 20, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "name": "signage-replay-web", + "ports": [ + { + "containerPort": 5280, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 5280, + "scheme": "HTTP" + }, + "initialDelaySeconds": 10, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "500m", + "memory": "256Mi" + }, + "requests": { + "cpu": "100m", + "memory": "128Mi" + } + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/tmp", + "name": "tmp" + }, + { + "mountPath": "/home/app/logs", + "name": "logs" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": { + "fsGroup": 1654, + "runAsGroup": 1654, + "runAsNonRoot": true, + "runAsUser": 1654 + }, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "emptyDir": {}, + "name": "tmp" + }, + { + "emptyDir": {}, + "name": "logs" + } + ] + } + } + } +} diff --git a/apps-gx10/fc-signage/deployment-signage-web.json b/apps-gx10/fc-signage/deployment-signage-web.json new file mode 100644 index 0000000..45249ae --- /dev/null +++ b/apps-gx10/fc-signage/deployment-signage-web.json @@ -0,0 +1,230 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "signage-web" + }, + "name": "signage-web", + "namespace": "fc-signage" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "signage-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "kubectl.kubernetes.io/restartedAt": "2026-05-04T13:50:05-05:00" + }, + "labels": { + "app": "signage-web" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "ASPNETCORE_URLS", + "value": "http://+:5190" + }, + { + "name": "ASPNETCORE_ENVIRONMENT", + "value": "Production" + }, + { + "name": "TrafficSignal__RelayBridge__Enabled", + "value": "true" + }, + { + "name": "TrafficSignal__RelayBridge__BaseUrl", + "value": "http://pirelay.iamworkin.lan:5100" + }, + { + "name": "DatabaseProvider", + "value": "Sqlite" + }, + { + "name": "ConnectionStrings__DefaultConnection", + "value": "Data Source=/data/signage.db" + }, + { + "name": "Serilog__MinimumLevel__Default", + "value": "Information" + }, + { + "name": "Serilog__WriteTo__0__Name", + "value": "Console" + }, + { + "name": "Kestrel__Endpoints__Http__Url", + "value": "http://+:5190" + }, + { + "name": "Kestrel__Endpoints__Grpc__Url", + "value": "http://+:5191" + }, + { + "name": "FlowerCore__DefaultTenantId", + "value": "default" + }, + { + "name": "FlowerCore__Signage__Announcements__AudibleEnabled", + "value": "true" + }, + { + "name": "FlowerCore__Signage__Announcements__DefaultVoiceName", + "value": "en_US-amy-low" + }, + { + "name": "FlowerCore__Signage__Announcements__Piper__Host", + "value": "10.0.57.17" + }, + { + "name": "FlowerCore__Signage__Announcements__Piper__Port", + "value": "10400" + }, + { + "name": "FlowerCore__Signage__Announcements__Piper__TimeoutSeconds", + "value": "120" + } + ], + "image": "localhost/fc-signage-web:v20260616-tt2-gx10-6a4486e", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 5190, + "scheme": "HTTP" + }, + "initialDelaySeconds": 30, + "periodSeconds": 30, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "name": "signage-web", + "ports": [ + { + "containerPort": 5190, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 5190, + "scheme": "HTTP" + }, + "initialDelaySeconds": 15, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "500m", + "memory": "512Mi" + }, + "requests": { + "cpu": "10m", + "memory": "256Mi" + } + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true + }, + "startupProbe": { + "failureThreshold": 30, + "periodSeconds": 5, + "successThreshold": 1, + "tcpSocket": { + "port": 5190 + }, + "timeoutSeconds": 1 + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + }, + { + "mountPath": "/app/data", + "name": "data" + }, + { + "mountPath": "/app/Cache", + "name": "data" + }, + { + "mountPath": "/app/storage", + "name": "data" + }, + { + "mountPath": "/app/wwwroot/uploads", + "name": "data" + }, + { + "mountPath": "/tmp", + "name": "tmp" + }, + { + "mountPath": "/app/logs", + "name": "logs" + }, + { + "mountPath": "/app/wwwroot/announcement-audio", + "name": "data" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": { + "fsGroup": 1654, + "runAsGroup": 1654, + "runAsNonRoot": true, + "runAsUser": 1654 + }, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "signage-data" + } + }, + { + "emptyDir": {}, + "name": "tmp" + }, + { + "emptyDir": {}, + "name": "logs" + } + ] + } + } + } +} diff --git a/apps-gx10/fc-signage/ingressroute-signage-replay-web.json b/apps-gx10/fc-signage/ingressroute-signage-replay-web.json new file mode 100644 index 0000000..fb839a0 --- /dev/null +++ b/apps-gx10/fc-signage/ingressroute-signage-replay-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "signage-replay-web", + "namespace": "fc-signage" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`replay.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "signage-replay-web", + "port": 5280 + } + ] + } + ], + "tls": { + "secretName": "signage-replay-web-tls" + } + } +} diff --git a/apps-gx10/fc-signage/ingressroute-signage-web.json b/apps-gx10/fc-signage/ingressroute-signage-web.json new file mode 100644 index 0000000..c449d65 --- /dev/null +++ b/apps-gx10/fc-signage/ingressroute-signage-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "signage-web", + "namespace": "fc-signage" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`signage.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "signage-web", + "port": 5190 + } + ] + } + ], + "tls": { + "secretName": "signage-web-tls" + } + } +} diff --git a/apps-gx10/fc-signage/service-signage-replay-web.json b/apps-gx10/fc-signage/service-signage-replay-web.json new file mode 100644 index 0000000..9739f45 --- /dev/null +++ b/apps-gx10/fc-signage/service-signage-replay-web.json @@ -0,0 +1,24 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "name": "signage-replay-web", + "namespace": "fc-signage" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 5280, + "protocol": "TCP", + "targetPort": 5280 + } + ], + "selector": { + "app": "signage-replay-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-signage/service-signage-web.json b/apps-gx10/fc-signage/service-signage-web.json new file mode 100644 index 0000000..b0975b9 --- /dev/null +++ b/apps-gx10/fc-signage/service-signage-web.json @@ -0,0 +1,24 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "name": "signage-web", + "namespace": "fc-signage" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 5190, + "protocol": "TCP", + "targetPort": 5190 + } + ], + "selector": { + "app": "signage-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-signalcontrol/deployment-signalcontrol-web.json b/apps-gx10/fc-signalcontrol/deployment-signalcontrol-web.json new file mode 100644 index 0000000..ef8ff93 --- /dev/null +++ b/apps-gx10/fc-signalcontrol/deployment-signalcontrol-web.json @@ -0,0 +1,133 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/name": "signalcontrol-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "signalcontrol-web", + "namespace": "fc-signalcontrol" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "signalcontrol-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "kubectl.kubernetes.io/restartedAt": "2026-04-22T23:55:51-05:00" + }, + "labels": { + "app.kubernetes.io/name": "signalcontrol-web", + "app.kubernetes.io/part-of": "flowercore" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "ASPNETCORE_ENVIRONMENT", + "value": "Production" + }, + { + "name": "ASPNETCORE_URLS", + "value": "http://+:5000" + }, + { + "name": "ConnectionStrings__Default", + "value": "Data Source=/data/signalcontrol.db" + }, + { + "name": "Logging__LogLevel__Default", + "value": "Information" + }, + { + "name": "Auth__ApiKey", + "valueFrom": { + "secretKeyRef": { + "key": "Auth__ApiKey", + "name": "signalcontrol-auth" + } + } + } + ], + "image": "localhost/fc-signalcontrol-web:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "initialDelaySeconds": 30, + "periodSeconds": 30, + "successThreshold": 1, + "tcpSocket": { + "port": "http" + }, + "timeoutSeconds": 5 + }, + "name": "signalcontrol-web", + "ports": [ + { + "containerPort": 5000, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 6, + "initialDelaySeconds": 10, + "periodSeconds": 10, + "successThreshold": 1, + "tcpSocket": { + "port": "http" + }, + "timeoutSeconds": 5 + }, + "resources": { + "limits": { + "cpu": "500m", + "memory": "512Mi" + }, + "requests": { + "cpu": "100m", + "memory": "128Mi" + } + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": { + "fsGroup": 4200, + "fsGroupChangePolicy": "OnRootMismatch" + }, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "signalcontrol-data" + } + } + ] + } + } + } +} diff --git a/apps-gx10/fc-signalcontrol/ingressroute-signalcontrol-web.json b/apps-gx10/fc-signalcontrol/ingressroute-signalcontrol-web.json new file mode 100644 index 0000000..6bf726d --- /dev/null +++ b/apps-gx10/fc-signalcontrol/ingressroute-signalcontrol-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "signalcontrol-web", + "namespace": "fc-signalcontrol" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`signalcontrol.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "signalcontrol-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "signalcontrol-web-tls" + } + } +} diff --git a/apps-gx10/fc-signalcontrol/service-signalcontrol-web.json b/apps-gx10/fc-signalcontrol/service-signalcontrol-web.json new file mode 100644 index 0000000..7777078 --- /dev/null +++ b/apps-gx10/fc-signalcontrol/service-signalcontrol-web.json @@ -0,0 +1,28 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app.kubernetes.io/name": "signalcontrol-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "signalcontrol-web", + "namespace": "fc-signalcontrol" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": "http" + } + ], + "selector": { + "app.kubernetes.io/name": "signalcontrol-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-system/configmap-fc-landing-html.json b/apps-gx10/fc-system/configmap-fc-landing-html.json new file mode 100644 index 0000000..fbaacc5 --- /dev/null +++ b/apps-gx10/fc-system/configmap-fc-landing-html.json @@ -0,0 +1,11 @@ +{ + "apiVersion": "v1", + "data": { + "index.html": "\n\n\n \n \n FlowerCore\n \n\n\n
\n
🌻
\n

FlowerCore

\n

Blue Jay Lab

\n

\n Multi-tenant service management platform built on .NET 10,\n Kubernetes, and GitOps. Digital signage, telephony IVR,\n MySQL/PHP hosting, and infrastructure automation.\n

\n
\n
\n \n

Source

\n

Gitea repositories

\n
\n \n

Mail

\n

Webmail access

\n
\n \n

Chat

\n

Matrix messaging

\n
\n \n

GitHub

\n

Open source

\n
\n
\n
\n
\n
17
\n
Services
\n
\n
\n
13
\n
VLANs
\n
\n
\n
12k+
\n
Tests
\n
\n
\n

\n FlowerCore · Bare-metal RKE2 · ArgoCD managed\n · Contact\n

\n\n\n" + }, + "kind": "ConfigMap", + "metadata": { + "name": "fc-landing-html", + "namespace": "fc-system" + } +} diff --git a/apps-gx10/fc-system/configmap-fc-landing-nginx-conf.json b/apps-gx10/fc-system/configmap-fc-landing-nginx-conf.json new file mode 100644 index 0000000..29c1f2d --- /dev/null +++ b/apps-gx10/fc-system/configmap-fc-landing-nginx-conf.json @@ -0,0 +1,11 @@ +{ + "apiVersion": "v1", + "data": { + "default.conf": "server {\n listen 80;\n server_name _;\n root /usr/share/nginx/html;\n index index.html;\n\n location / {\n try_files $uri $uri/ =404;\n }\n\n location /healthz {\n access_log off;\n return 200 \"ok\";\n add_header Content-Type text/plain;\n }\n}\n" + }, + "kind": "ConfigMap", + "metadata": { + "name": "fc-landing-nginx-conf", + "namespace": "fc-system" + } +} diff --git a/apps-gx10/fc-system/configmap-kiosk-web-config.json b/apps-gx10/fc-system/configmap-kiosk-web-config.json new file mode 100644 index 0000000..52e2963 --- /dev/null +++ b/apps-gx10/fc-system/configmap-kiosk-web-config.json @@ -0,0 +1,11 @@ +{ + "apiVersion": "v1", + "data": { + "appsettings.Production.json": "{\n \"FlowerCore\": {\n \"Database\": {\n \"Provider\": \"Sqlite\",\n \"ConnectionStrings\": {\n \"Sqlite\": \"Data Source=/app/data/kiosk.db\"\n }\n },\n \"Kiosk\": {\n \"Profiles\": {\n \"Backend\": \"K8s\",\n \"LonghornRoot\": \"/var/lib/flowercore/kiosk/profiles/data\"\n }\n },\n \"PrintWeb\": {\n \"Url\": \"http://10.0.57.16:5200\"\n }\n },\n \"Serilog\": {\n \"MinimumLevel\": {\n \"Default\": \"Information\",\n \"Override\": {\n \"Microsoft\": \"Warning\",\n \"Microsoft.EntityFrameworkCore\": \"Warning\"\n }\n },\n \"WriteTo\": [\n {\n \"Name\": \"Console\",\n \"Args\": {\n \"formatter\": \"Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact\"\n }\n }\n ],\n \"Enrich\": [\n \"FromLogContext\",\n \"WithProperty\"\n ],\n \"Properties\": {\n \"Service\": \"Kiosk.Web\",\n \"Environment\": \"Production\"\n }\n },\n \"LibraryWeb\": {\n \"Url\": \"http://library.iamworkin.lan:5100\"\n },\n \"Security\": {\n \"Mode\": \"apikey\",\n \"ApiKeys\": [],\n \"AdminApiKeys\": [],\n \"AgentApiKeys\": [],\n \"ExemptPaths\": [ \"/health\", \"/metrics\", \"/_blazor\", \"/_framework\", \"/css\", \"/hubs\" ]\n },\n \"Logging\": {\n \"LogLevel\": {\n \"Default\": \"Information\",\n \"Microsoft\": \"Warning\"\n }\n },\n \"AllowedHosts\": \"*\"\n}\n" + }, + "kind": "ConfigMap", + "metadata": { + "name": "kiosk-web-config", + "namespace": "fc-system" + } +} diff --git a/apps-gx10/fc-system/deployment-fc-landing.json b/apps-gx10/fc-system/deployment-fc-landing.json new file mode 100644 index 0000000..5cbcd29 --- /dev/null +++ b/apps-gx10/fc-system/deployment-fc-landing.json @@ -0,0 +1,119 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "fc-landing" + }, + "name": "fc-landing", + "namespace": "fc-system" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "fc-landing" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%" + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "labels": { + "app": "fc-landing" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:alpine", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 80, + "scheme": "HTTP" + }, + "initialDelaySeconds": 5, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 80, + "scheme": "HTTP" + }, + "initialDelaySeconds": 3, + "periodSeconds": 5, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "50m", + "memory": "64Mi" + }, + "requests": { + "cpu": "5m", + "memory": "16Mi" + } + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/etc/nginx/conf.d/default.conf", + "name": "nginx-conf", + "subPath": "default.conf" + }, + { + "mountPath": "/usr/share/nginx/html", + "name": "html" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "configMap": { + "defaultMode": 420, + "name": "fc-landing-nginx-conf" + }, + "name": "nginx-conf" + }, + { + "configMap": { + "defaultMode": 420, + "name": "fc-landing-html" + }, + "name": "html" + } + ] + } + } + } +} diff --git a/apps-gx10/fc-system/deployment-kiosk-web.json b/apps-gx10/fc-system/deployment-kiosk-web.json new file mode 100644 index 0000000..2b23268 --- /dev/null +++ b/apps-gx10/fc-system/deployment-kiosk-web.json @@ -0,0 +1,275 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "kiosk-web", + "app.kubernetes.io/component": "web", + "app.kubernetes.io/instance": "kiosk-web", + "app.kubernetes.io/managed-by": "flowercore-kiosk", + "app.kubernetes.io/name": "kiosk-web", + "component": "web", + "flowercore.io/created-by": "kiosk-fleshing-out-phase-2", + "flowercore.io/tenant-id": "default", + "project": "flowercore-kiosk" + }, + "name": "kiosk-web", + "namespace": "fc-system" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "kiosk-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "kubectl.kubernetes.io/restartedAt": "2026-05-06T21:21:19-05:00" + }, + "labels": { + "app": "kiosk-web", + "app.kubernetes.io/component": "web", + "app.kubernetes.io/instance": "kiosk-web", + "app.kubernetes.io/managed-by": "flowercore-kiosk", + "app.kubernetes.io/name": "kiosk-web", + "component": "web", + "flowercore.io/created-by": "kiosk-fleshing-out-phase-2", + "flowercore.io/tenant-id": "default", + "project": "flowercore-kiosk" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "ASPNETCORE_URLS", + "value": "http://+:8080" + }, + { + "name": "ASPNETCORE_ENVIRONMENT", + "value": "Production" + }, + { + "name": "Security__ApiKeys__0", + "valueFrom": { + "secretKeyRef": { + "key": "BrowserBypassApiKey", + "name": "kiosk-web-api-keys" + } + } + }, + { + "name": "Security__AdminApiKeys__0", + "valueFrom": { + "secretKeyRef": { + "key": "AdminApiKey", + "name": "kiosk-web-api-keys" + } + } + }, + { + "name": "Security__AgentApiKeys__0", + "valueFrom": { + "secretKeyRef": { + "key": "AgentApiKey", + "name": "kiosk-web-api-keys" + } + } + }, + { + "name": "FlowerCore__Kiosk__Profiles__Backend", + "value": "K8s" + }, + { + "name": "FlowerCore__Kiosk__Profiles__LonghornRoot", + "value": "/var/lib/flowercore/kiosk/profiles/data" + }, + { + "name": "FlowerCore__PrintWeb__Url", + "value": "http://10.0.57.16:5200" + }, + { + "name": "FlowerCore__PrintWeb__ApiKey", + "valueFrom": { + "secretKeyRef": { + "key": "PrintWebApiKey", + "name": "kiosk-web-api-keys" + } + } + } + ], + "image": "localhost/fc-kiosk-web:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 6, + "httpGet": { + "path": "/health", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 120, + "periodSeconds": 20, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "name": "kiosk-web", + "ports": [ + { + "containerPort": 8080, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 45, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "resources": { + "limits": { + "cpu": "1", + "memory": "512Mi" + }, + "requests": { + "cpu": "250m", + "memory": "256Mi" + } + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/app/data", + "name": "data" + }, + { + "mountPath": "/tmp", + "name": "tmp" + }, + { + "mountPath": "/app/logs", + "name": "logs" + }, + { + "mountPath": "/var/lib/flowercore/kiosk/profiles", + "name": "user-profiles" + }, + { + "mountPath": "/app/appsettings.Production.json", + "name": "appsettings-production", + "readOnly": true, + "subPath": "appsettings.Production.json" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "initContainers": [ + { + "command": [ + "sh", + "-c", + "mkdir -p /profiles/data && chown -R 1654:1654 /profiles/data && chmod -R u+rwX,g+rwX /profiles/data" + ], + "image": "localhost/fc-kiosk-web:gx10-v1", + "imagePullPolicy": "Never", + "name": "fix-profile-perms", + "resources": {}, + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "add": [ + "CHOWN", + "FOWNER" + ], + "drop": [ + "ALL" + ] + }, + "runAsGroup": 0, + "runAsNonRoot": false, + "runAsUser": 0 + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/profiles", + "name": "user-profiles" + } + ] + } + ], + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": { + "fsGroup": 1654, + "fsGroupChangePolicy": "OnRootMismatch", + "runAsGroup": 1654, + "runAsNonRoot": true, + "runAsUser": 1654 + }, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "kiosk-web-data" + } + }, + { + "emptyDir": {}, + "name": "tmp" + }, + { + "emptyDir": {}, + "name": "logs" + }, + { + "name": "user-profiles", + "persistentVolumeClaim": { + "claimName": "kiosk-user-profiles" + } + }, + { + "configMap": { + "defaultMode": 420, + "items": [ + { + "key": "appsettings.Production.json", + "path": "appsettings.Production.json" + } + ], + "name": "kiosk-web-config" + }, + "name": "appsettings-production" + } + ] + } + } + } +} diff --git a/apps-gx10/fc-system/deployment-mysql-operator.json b/apps-gx10/fc-system/deployment-mysql-operator.json new file mode 100644 index 0000000..a1be2c9 --- /dev/null +++ b/apps-gx10/fc-system/deployment-mysql-operator.json @@ -0,0 +1,117 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/component": "operator", + "app.kubernetes.io/instance": "mysql-operator", + "app.kubernetes.io/managed-by": "flowercore", + "app.kubernetes.io/name": "mysql-operator", + "app.kubernetes.io/part-of": "flowercore-mysql" + }, + "name": "mysql-operator", + "namespace": "fc-system" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app.kubernetes.io/instance": "mysql-operator", + "app.kubernetes.io/name": "mysql-operator" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%" + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "annotations": { + "kubectl.kubernetes.io/restartedAt": "2026-04-17T09:34:39-05:00" + }, + "labels": { + "app.kubernetes.io/component": "operator", + "app.kubernetes.io/instance": "mysql-operator", + "app.kubernetes.io/managed-by": "flowercore", + "app.kubernetes.io/name": "mysql-operator", + "app.kubernetes.io/part-of": "flowercore-mysql" + } + }, + "spec": { + "automountServiceAccountToken": true, + "containers": [ + { + "env": [ + { + "name": "ASPNETCORE_ENVIRONMENT", + "value": "Production" + }, + { + "name": "ASPNETCORE_URLS", + "value": "http://+:8080" + } + ], + "image": "localhost/fc-mysql-operator:gx10-v1", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 15, + "periodSeconds": 20, + "successThreshold": 1, + "timeoutSeconds": 3 + }, + "name": "mysql-operator", + "ports": [ + { + "containerPort": 8080, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 5, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 3 + }, + "resources": { + "limits": { + "cpu": "500m", + "memory": "512Mi" + }, + "requests": { + "cpu": "250m", + "memory": "256Mi" + } + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "mysql-operator", + "serviceAccountName": "mysql-operator", + "terminationGracePeriodSeconds": 30 + } + } + } +} diff --git a/apps-gx10/fc-system/deployment-php-operator.json b/apps-gx10/fc-system/deployment-php-operator.json new file mode 100644 index 0000000..39e375c --- /dev/null +++ b/apps-gx10/fc-system/deployment-php-operator.json @@ -0,0 +1,134 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/component": "operator", + "app.kubernetes.io/instance": "php-operator", + "app.kubernetes.io/managed-by": "flowercore", + "app.kubernetes.io/name": "php-operator", + "app.kubernetes.io/part-of": "flowercore-php" + }, + "name": "php-operator", + "namespace": "fc-system" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app.kubernetes.io/instance": "php-operator", + "app.kubernetes.io/name": "php-operator", + "app.kubernetes.io/part-of": "flowercore-php" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%" + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "annotations": { + "kubectl.kubernetes.io/restartedAt": "2026-04-17T10:09:10-05:00" + }, + "labels": { + "app.kubernetes.io/component": "operator", + "app.kubernetes.io/instance": "php-operator", + "app.kubernetes.io/managed-by": "flowercore", + "app.kubernetes.io/name": "php-operator", + "app.kubernetes.io/part-of": "flowercore-php" + } + }, + "spec": { + "automountServiceAccountToken": true, + "containers": [ + { + "env": [ + { + "name": "ASPNETCORE_ENVIRONMENT", + "value": "Production" + }, + { + "name": "ASPNETCORE_URLS", + "value": "http://+:8080" + }, + { + "name": "MySqlManager__BaseUrl", + "value": "https://mysql.iamworkin.lan/" + }, + { + "name": "MySqlManager__BypassTls", + "value": "true" + }, + { + "name": "PhpManager__BaseUrl", + "value": "https://php.iamworkin.lan/" + }, + { + "name": "PhpManager__BypassTls", + "value": "true" + } + ], + "image": "localhost/fc-php-operator:gx10-v1", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 15, + "periodSeconds": 20, + "successThreshold": 1, + "timeoutSeconds": 3 + }, + "name": "php-operator", + "ports": [ + { + "containerPort": 8080, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 5, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 3 + }, + "resources": { + "limits": { + "cpu": "500m", + "memory": "512Mi" + }, + "requests": { + "cpu": "250m", + "memory": "256Mi" + } + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "php-operator", + "serviceAccountName": "php-operator", + "terminationGracePeriodSeconds": 30 + } + } + } +} diff --git a/apps-gx10/fc-system/ingressroute-fc-landing-public.json b/apps-gx10/fc-system/ingressroute-fc-landing-public.json new file mode 100644 index 0000000..4a9e1b3 --- /dev/null +++ b/apps-gx10/fc-system/ingressroute-fc-landing-public.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "fc-landing-public", + "namespace": "fc-system" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`flowercore.io`) || Host(`www.flowercore.io`)", + "priority": 100, + "services": [ + { + "name": "fc-landing", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "cf-origin-flowercore-io" + } + } +} diff --git a/apps-gx10/fc-system/ingressroute-kiosk-web.json b/apps-gx10/fc-system/ingressroute-kiosk-web.json new file mode 100644 index 0000000..f45a10f --- /dev/null +++ b/apps-gx10/fc-system/ingressroute-kiosk-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "kiosk-web", + "namespace": "fc-system" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`kiosk.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "kiosk-web", + "port": 8080 + } + ] + } + ], + "tls": { + "secretName": "kiosk-web-tls" + } + } +} diff --git a/apps-gx10/fc-system/service-fc-landing.json b/apps-gx10/fc-system/service-fc-landing.json new file mode 100644 index 0000000..b80e2b8 --- /dev/null +++ b/apps-gx10/fc-system/service-fc-landing.json @@ -0,0 +1,27 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app": "fc-landing" + }, + "name": "fc-landing", + "namespace": "fc-system" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 80 + } + ], + "selector": { + "app": "fc-landing" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-system/service-kiosk-web.json b/apps-gx10/fc-system/service-kiosk-web.json new file mode 100644 index 0000000..d520cc0 --- /dev/null +++ b/apps-gx10/fc-system/service-kiosk-web.json @@ -0,0 +1,34 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app": "kiosk-web", + "app.kubernetes.io/component": "web", + "app.kubernetes.io/instance": "kiosk-web", + "app.kubernetes.io/managed-by": "flowercore-kiosk", + "app.kubernetes.io/name": "kiosk-web", + "flowercore.io/created-by": "kiosk-fleshing-out-phase-2", + "flowercore.io/tenant-id": "default", + "project": "flowercore-kiosk" + }, + "name": "kiosk-web", + "namespace": "fc-system" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 8080, + "protocol": "TCP", + "targetPort": 8080 + } + ], + "selector": { + "app": "kiosk-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-system/serviceaccount-mysql-operator.json b/apps-gx10/fc-system/serviceaccount-mysql-operator.json new file mode 100644 index 0000000..f1a578c --- /dev/null +++ b/apps-gx10/fc-system/serviceaccount-mysql-operator.json @@ -0,0 +1,15 @@ +{ + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": { + "labels": { + "app.kubernetes.io/component": "operator", + "app.kubernetes.io/instance": "mysql-operator", + "app.kubernetes.io/managed-by": "flowercore", + "app.kubernetes.io/name": "mysql-operator", + "app.kubernetes.io/part-of": "flowercore-mysql" + }, + "name": "mysql-operator", + "namespace": "fc-system" + } +} diff --git a/apps-gx10/fc-system/serviceaccount-php-operator.json b/apps-gx10/fc-system/serviceaccount-php-operator.json new file mode 100644 index 0000000..88dd85f --- /dev/null +++ b/apps-gx10/fc-system/serviceaccount-php-operator.json @@ -0,0 +1,15 @@ +{ + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": { + "labels": { + "app.kubernetes.io/component": "operator", + "app.kubernetes.io/instance": "php-operator", + "app.kubernetes.io/managed-by": "flowercore", + "app.kubernetes.io/name": "php-operator", + "app.kubernetes.io/part-of": "flowercore-php" + }, + "name": "php-operator", + "namespace": "fc-system" + } +} diff --git a/apps-gx10/fc-tenant-andrew/configmap-andrew-web-html.json b/apps-gx10/fc-tenant-andrew/configmap-andrew-web-html.json new file mode 100644 index 0000000..25ef24e --- /dev/null +++ b/apps-gx10/fc-tenant-andrew/configmap-andrew-web-html.json @@ -0,0 +1,11 @@ +{ + "apiVersion": "v1", + "data": { + "index.html": "\n\n\n \n \n Blue Jay \u2014 bluejay.dev\n \n\n\n
\n
\n
Andrew's Space
\n
🐦
\n

Blue Jay

\n

bluejay.dev

\n
\n \n

Coming Soon

\n
\n
\n

\n Powered by FlowerCore\n

\n
\n\n\n" + }, + "kind": "ConfigMap", + "metadata": { + "name": "andrew-web-html", + "namespace": "fc-tenant-andrew" + } +} diff --git a/apps-gx10/fc-tenant-andrew/configmap-andrew-web-nginx-conf.json b/apps-gx10/fc-tenant-andrew/configmap-andrew-web-nginx-conf.json new file mode 100644 index 0000000..00efbe7 --- /dev/null +++ b/apps-gx10/fc-tenant-andrew/configmap-andrew-web-nginx-conf.json @@ -0,0 +1,11 @@ +{ + "apiVersion": "v1", + "data": { + "default.conf": "server {\n listen 80;\n server_name _;\n root /usr/share/nginx/html;\n index index.html;\n location / { try_files $uri $uri/ =404; }\n location /healthz { access_log off; return 200 \"ok\"; add_header Content-Type text/plain; }\n}\n" + }, + "kind": "ConfigMap", + "metadata": { + "name": "andrew-web-nginx-conf", + "namespace": "fc-tenant-andrew" + } +} diff --git a/apps-gx10/fc-tenant-andrew/deployment-andrew-web.json b/apps-gx10/fc-tenant-andrew/deployment-andrew-web.json new file mode 100644 index 0000000..e506f36 --- /dev/null +++ b/apps-gx10/fc-tenant-andrew/deployment-andrew-web.json @@ -0,0 +1,119 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "andrew-web" + }, + "name": "andrew-web", + "namespace": "fc-tenant-andrew" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "andrew-web" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%" + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "labels": { + "app": "andrew-web" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:alpine", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 80, + "scheme": "HTTP" + }, + "initialDelaySeconds": 5, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 80, + "scheme": "HTTP" + }, + "initialDelaySeconds": 3, + "periodSeconds": 5, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "50m", + "memory": "64Mi" + }, + "requests": { + "cpu": "10m", + "memory": "32Mi" + } + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/etc/nginx/conf.d/default.conf", + "name": "nginx-conf", + "subPath": "default.conf" + }, + { + "mountPath": "/usr/share/nginx/html", + "name": "html" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "configMap": { + "defaultMode": 420, + "name": "andrew-web-nginx-conf" + }, + "name": "nginx-conf" + }, + { + "configMap": { + "defaultMode": 420, + "name": "andrew-web-html" + }, + "name": "html" + } + ] + } + } + } +} diff --git a/apps-gx10/fc-tenant-andrew/ingressroute-andrew-web.json b/apps-gx10/fc-tenant-andrew/ingressroute-andrew-web.json new file mode 100644 index 0000000..bb58190 --- /dev/null +++ b/apps-gx10/fc-tenant-andrew/ingressroute-andrew-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "andrew-web", + "namespace": "fc-tenant-andrew" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`bluejay.dev`) || Host(`www.bluejay.dev`)", + "priority": 100, + "services": [ + { + "name": "andrew-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "cf-origin-bluejay-dev" + } + } +} diff --git a/apps-gx10/fc-tenant-andrew/service-andrew-web.json b/apps-gx10/fc-tenant-andrew/service-andrew-web.json new file mode 100644 index 0000000..6655e7e --- /dev/null +++ b/apps-gx10/fc-tenant-andrew/service-andrew-web.json @@ -0,0 +1,24 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "name": "andrew-web", + "namespace": "fc-tenant-andrew" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 80 + } + ], + "selector": { + "app": "andrew-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-tenant-dustin/configmap-dustin-web-html.json b/apps-gx10/fc-tenant-dustin/configmap-dustin-web-html.json new file mode 100644 index 0000000..a23b2b6 --- /dev/null +++ b/apps-gx10/fc-tenant-dustin/configmap-dustin-web-html.json @@ -0,0 +1,11 @@ +{ + "apiVersion": "v1", + "data": { + "index.html": "\n\n\n \n \n timeforta.co — Coming Soon\n \n\n\n
\n
🌮
\n

timeforta.co

\n
Dustin
\n
\n

It's always time for tacos.

\n
\n \n Under Construction\n
\n
\n \n\n\n" + }, + "kind": "ConfigMap", + "metadata": { + "name": "dustin-web-html", + "namespace": "fc-tenant-dustin" + } +} diff --git a/apps-gx10/fc-tenant-dustin/configmap-dustin-web-nginx-conf.json b/apps-gx10/fc-tenant-dustin/configmap-dustin-web-nginx-conf.json new file mode 100644 index 0000000..d215f96 --- /dev/null +++ b/apps-gx10/fc-tenant-dustin/configmap-dustin-web-nginx-conf.json @@ -0,0 +1,11 @@ +{ + "apiVersion": "v1", + "data": { + "default.conf": "server {\n listen 80;\n server_name _;\n root /usr/share/nginx/html;\n index index.html;\n location / { try_files $uri $uri/ =404; }\n location /healthz { access_log off; return 200 \"ok\"; add_header Content-Type text/plain; }\n}\n" + }, + "kind": "ConfigMap", + "metadata": { + "name": "dustin-web-nginx-conf", + "namespace": "fc-tenant-dustin" + } +} diff --git a/apps-gx10/fc-tenant-dustin/deployment-dustin-web.json b/apps-gx10/fc-tenant-dustin/deployment-dustin-web.json new file mode 100644 index 0000000..5aa721e --- /dev/null +++ b/apps-gx10/fc-tenant-dustin/deployment-dustin-web.json @@ -0,0 +1,119 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "dustin-web" + }, + "name": "dustin-web", + "namespace": "fc-tenant-dustin" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "dustin-web" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%" + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "labels": { + "app": "dustin-web" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:alpine", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 80, + "scheme": "HTTP" + }, + "initialDelaySeconds": 5, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 80, + "scheme": "HTTP" + }, + "initialDelaySeconds": 3, + "periodSeconds": 5, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "50m", + "memory": "64Mi" + }, + "requests": { + "cpu": "10m", + "memory": "32Mi" + } + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/etc/nginx/conf.d/default.conf", + "name": "nginx-conf", + "subPath": "default.conf" + }, + { + "mountPath": "/usr/share/nginx/html", + "name": "html" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "configMap": { + "defaultMode": 420, + "name": "dustin-web-nginx-conf" + }, + "name": "nginx-conf" + }, + { + "configMap": { + "defaultMode": 420, + "name": "dustin-web-html" + }, + "name": "html" + } + ] + } + } + } +} diff --git a/apps-gx10/fc-tenant-dustin/ingressroute-dustin-web.json b/apps-gx10/fc-tenant-dustin/ingressroute-dustin-web.json new file mode 100644 index 0000000..fdf6e19 --- /dev/null +++ b/apps-gx10/fc-tenant-dustin/ingressroute-dustin-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "dustin-web", + "namespace": "fc-tenant-dustin" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`timeforta.co`) || Host(`www.timeforta.co`)", + "priority": 100, + "services": [ + { + "name": "dustin-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "cf-origin-timeforta-co" + } + } +} diff --git a/apps-gx10/fc-tenant-dustin/service-dustin-web.json b/apps-gx10/fc-tenant-dustin/service-dustin-web.json new file mode 100644 index 0000000..7f4801c --- /dev/null +++ b/apps-gx10/fc-tenant-dustin/service-dustin-web.json @@ -0,0 +1,24 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "name": "dustin-web", + "namespace": "fc-tenant-dustin" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 80 + } + ], + "selector": { + "app": "dustin-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-tenant-erik/configmap-erik-web-html.json b/apps-gx10/fc-tenant-erik/configmap-erik-web-html.json new file mode 100644 index 0000000..eb9ba63 --- /dev/null +++ b/apps-gx10/fc-tenant-erik/configmap-erik-web-html.json @@ -0,0 +1,11 @@ +{ + "apiVersion": "v1", + "data": { + "index.html": "\n\n\n \n \n Erckak \u2014 erckak.dev\n \n\n\n
\n
\n
Erik's Space
\n
🚀
\n

Erckak

\n

erckak.dev

\n
\n \n

Coming Soon

\n
\n
\n

\n Powered by FlowerCore\n

\n
\n\n\n" + }, + "kind": "ConfigMap", + "metadata": { + "name": "erik-web-html", + "namespace": "fc-tenant-erik" + } +} diff --git a/apps-gx10/fc-tenant-erik/configmap-erik-web-nginx-conf.json b/apps-gx10/fc-tenant-erik/configmap-erik-web-nginx-conf.json new file mode 100644 index 0000000..dfcd8cd --- /dev/null +++ b/apps-gx10/fc-tenant-erik/configmap-erik-web-nginx-conf.json @@ -0,0 +1,11 @@ +{ + "apiVersion": "v1", + "data": { + "default.conf": "server {\n listen 80;\n server_name _;\n root /usr/share/nginx/html;\n index index.html;\n location / { try_files $uri $uri/ =404; }\n location /healthz { access_log off; return 200 \"ok\"; add_header Content-Type text/plain; }\n}\n" + }, + "kind": "ConfigMap", + "metadata": { + "name": "erik-web-nginx-conf", + "namespace": "fc-tenant-erik" + } +} diff --git a/apps-gx10/fc-tenant-erik/deployment-erik-web.json b/apps-gx10/fc-tenant-erik/deployment-erik-web.json new file mode 100644 index 0000000..9a80156 --- /dev/null +++ b/apps-gx10/fc-tenant-erik/deployment-erik-web.json @@ -0,0 +1,119 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "erik-web" + }, + "name": "erik-web", + "namespace": "fc-tenant-erik" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "erik-web" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%" + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "labels": { + "app": "erik-web" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:alpine", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 80, + "scheme": "HTTP" + }, + "initialDelaySeconds": 5, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 80, + "scheme": "HTTP" + }, + "initialDelaySeconds": 3, + "periodSeconds": 5, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "50m", + "memory": "64Mi" + }, + "requests": { + "cpu": "10m", + "memory": "32Mi" + } + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/etc/nginx/conf.d/default.conf", + "name": "nginx-conf", + "subPath": "default.conf" + }, + { + "mountPath": "/usr/share/nginx/html", + "name": "html" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "configMap": { + "defaultMode": 420, + "name": "erik-web-nginx-conf" + }, + "name": "nginx-conf" + }, + { + "configMap": { + "defaultMode": 420, + "name": "erik-web-html" + }, + "name": "html" + } + ] + } + } + } +} diff --git a/apps-gx10/fc-tenant-erik/ingressroute-erik-web.json b/apps-gx10/fc-tenant-erik/ingressroute-erik-web.json new file mode 100644 index 0000000..c735bfb --- /dev/null +++ b/apps-gx10/fc-tenant-erik/ingressroute-erik-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "erik-web", + "namespace": "fc-tenant-erik" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`erckak.dev`) || Host(`www.erckak.dev`)", + "priority": 100, + "services": [ + { + "name": "erik-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "cf-origin-erckak-dev" + } + } +} diff --git a/apps-gx10/fc-tenant-erik/service-erik-web.json b/apps-gx10/fc-tenant-erik/service-erik-web.json new file mode 100644 index 0000000..348d32e --- /dev/null +++ b/apps-gx10/fc-tenant-erik/service-erik-web.json @@ -0,0 +1,24 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "name": "erik-web", + "namespace": "fc-tenant-erik" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 80 + } + ], + "selector": { + "app": "erik-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-tenant-fit/configmap-fit-web-html.json b/apps-gx10/fc-tenant-fit/configmap-fit-web-html.json new file mode 100644 index 0000000..354accb --- /dev/null +++ b/apps-gx10/fc-tenant-fit/configmap-fit-web-html.json @@ -0,0 +1,11 @@ +{ + "apiVersion": "v1", + "data": { + "index.html": "\n\n\n \n \n Flower Insider \u2014 flowerinsider.xyz\n \n\n\n
\n
\n
Flower Insider Team
\n
🌸
\n

Flower Insider

\n

flowerinsider.xyz

\n
\n \n

Coming Soon

\n
\n
\n

\n Powered by FlowerCore\n

\n
\n\n\n" + }, + "kind": "ConfigMap", + "metadata": { + "name": "fit-web-html", + "namespace": "fc-tenant-fit" + } +} diff --git a/apps-gx10/fc-tenant-fit/configmap-fit-web-nginx-conf.json b/apps-gx10/fc-tenant-fit/configmap-fit-web-nginx-conf.json new file mode 100644 index 0000000..5925412 --- /dev/null +++ b/apps-gx10/fc-tenant-fit/configmap-fit-web-nginx-conf.json @@ -0,0 +1,11 @@ +{ + "apiVersion": "v1", + "data": { + "default.conf": "server {\n listen 80;\n server_name _;\n root /usr/share/nginx/html;\n index index.html;\n location / { try_files $uri $uri/ =404; }\n location /healthz { access_log off; return 200 \"ok\"; add_header Content-Type text/plain; }\n}\n" + }, + "kind": "ConfigMap", + "metadata": { + "name": "fit-web-nginx-conf", + "namespace": "fc-tenant-fit" + } +} diff --git a/apps-gx10/fc-tenant-fit/deployment-fit-web.json b/apps-gx10/fc-tenant-fit/deployment-fit-web.json new file mode 100644 index 0000000..1966731 --- /dev/null +++ b/apps-gx10/fc-tenant-fit/deployment-fit-web.json @@ -0,0 +1,119 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "fit-web" + }, + "name": "fit-web", + "namespace": "fc-tenant-fit" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "fit-web" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%" + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "labels": { + "app": "fit-web" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:alpine", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 80, + "scheme": "HTTP" + }, + "initialDelaySeconds": 5, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 80, + "scheme": "HTTP" + }, + "initialDelaySeconds": 3, + "periodSeconds": 5, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "50m", + "memory": "64Mi" + }, + "requests": { + "cpu": "10m", + "memory": "32Mi" + } + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/etc/nginx/conf.d/default.conf", + "name": "nginx-conf", + "subPath": "default.conf" + }, + { + "mountPath": "/usr/share/nginx/html", + "name": "html" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "configMap": { + "defaultMode": 420, + "name": "fit-web-nginx-conf" + }, + "name": "nginx-conf" + }, + { + "configMap": { + "defaultMode": 420, + "name": "fit-web-html" + }, + "name": "html" + } + ] + } + } + } +} diff --git a/apps-gx10/fc-tenant-fit/ingressroute-fit-web.json b/apps-gx10/fc-tenant-fit/ingressroute-fit-web.json new file mode 100644 index 0000000..be61ad8 --- /dev/null +++ b/apps-gx10/fc-tenant-fit/ingressroute-fit-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "fit-web", + "namespace": "fc-tenant-fit" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`flowerinsider.xyz`) || Host(`www.flowerinsider.xyz`)", + "priority": 100, + "services": [ + { + "name": "fit-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "cf-origin-flowerinsider-xyz" + } + } +} diff --git a/apps-gx10/fc-tenant-fit/service-fit-web.json b/apps-gx10/fc-tenant-fit/service-fit-web.json new file mode 100644 index 0000000..6ad3229 --- /dev/null +++ b/apps-gx10/fc-tenant-fit/service-fit-web.json @@ -0,0 +1,24 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "name": "fit-web", + "namespace": "fc-tenant-fit" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 80 + } + ], + "selector": { + "app": "fit-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-tenant-matt/configmap-matt-web-html.json b/apps-gx10/fc-tenant-matt/configmap-matt-web-html.json new file mode 100644 index 0000000..09a0de0 --- /dev/null +++ b/apps-gx10/fc-tenant-matt/configmap-matt-web-html.json @@ -0,0 +1,11 @@ +{ + "apiVersion": "v1", + "data": { + "index.html": "\n\n\n \n \n matt.flowercore.io — Coming Soon\n \n\n\n
\n
🔥
\n

matt.flowercore.io

\n
Matt
\n
\n

Building something extraordinary.

\n
\n \n Under Construction\n
\n
\n \n\n\n" + }, + "kind": "ConfigMap", + "metadata": { + "name": "matt-web-html", + "namespace": "fc-tenant-matt" + } +} diff --git a/apps-gx10/fc-tenant-matt/configmap-matt-web-nginx-conf.json b/apps-gx10/fc-tenant-matt/configmap-matt-web-nginx-conf.json new file mode 100644 index 0000000..195c3ab --- /dev/null +++ b/apps-gx10/fc-tenant-matt/configmap-matt-web-nginx-conf.json @@ -0,0 +1,11 @@ +{ + "apiVersion": "v1", + "data": { + "default.conf": "server {\n listen 80;\n server_name _;\n root /usr/share/nginx/html;\n index index.html;\n location / { try_files $uri $uri/ =404; }\n location /healthz { access_log off; return 200 \"ok\"; add_header Content-Type text/plain; }\n}\n" + }, + "kind": "ConfigMap", + "metadata": { + "name": "matt-web-nginx-conf", + "namespace": "fc-tenant-matt" + } +} diff --git a/apps-gx10/fc-tenant-matt/deployment-matt-web.json b/apps-gx10/fc-tenant-matt/deployment-matt-web.json new file mode 100644 index 0000000..b5b8fe7 --- /dev/null +++ b/apps-gx10/fc-tenant-matt/deployment-matt-web.json @@ -0,0 +1,119 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "matt-web" + }, + "name": "matt-web", + "namespace": "fc-tenant-matt" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "matt-web" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%" + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "labels": { + "app": "matt-web" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:alpine", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 80, + "scheme": "HTTP" + }, + "initialDelaySeconds": 5, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 80, + "scheme": "HTTP" + }, + "initialDelaySeconds": 3, + "periodSeconds": 5, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "50m", + "memory": "64Mi" + }, + "requests": { + "cpu": "10m", + "memory": "32Mi" + } + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/etc/nginx/conf.d/default.conf", + "name": "nginx-conf", + "subPath": "default.conf" + }, + { + "mountPath": "/usr/share/nginx/html", + "name": "html" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "configMap": { + "defaultMode": 420, + "name": "matt-web-nginx-conf" + }, + "name": "nginx-conf" + }, + { + "configMap": { + "defaultMode": 420, + "name": "matt-web-html" + }, + "name": "html" + } + ] + } + } + } +} diff --git a/apps-gx10/fc-tenant-matt/ingressroute-matt-web.json b/apps-gx10/fc-tenant-matt/ingressroute-matt-web.json new file mode 100644 index 0000000..b72cbb0 --- /dev/null +++ b/apps-gx10/fc-tenant-matt/ingressroute-matt-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "matt-web", + "namespace": "fc-tenant-matt" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`matt.flowercore.io`)", + "priority": 100, + "services": [ + { + "name": "matt-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "cf-origin-flowercore-io" + } + } +} diff --git a/apps-gx10/fc-tenant-matt/service-matt-web.json b/apps-gx10/fc-tenant-matt/service-matt-web.json new file mode 100644 index 0000000..72026c0 --- /dev/null +++ b/apps-gx10/fc-tenant-matt/service-matt-web.json @@ -0,0 +1,24 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "name": "matt-web", + "namespace": "fc-tenant-matt" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 80 + } + ], + "selector": { + "app": "matt-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-ttsreader/deployment-ttsreader-web.json b/apps-gx10/fc-ttsreader/deployment-ttsreader-web.json new file mode 100644 index 0000000..4bd7831 --- /dev/null +++ b/apps-gx10/fc-ttsreader/deployment-ttsreader-web.json @@ -0,0 +1,293 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/name": "ttsreader-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "ttsreader-web", + "namespace": "fc-ttsreader" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "ttsreader-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "fc.flowercore.io/healthz-anon": "true", + "fc.flowercore.io/probe-path": "/health", + "kubectl.kubernetes.io/restartedAt": "2026-06-14T00:57:20-05:00", + "prometheus.io/path": "/metrics", + "prometheus.io/port": "5217", + "prometheus.io/scrape": "true" + }, + "labels": { + "app.kubernetes.io/name": "ttsreader-web", + "app.kubernetes.io/part-of": "flowercore" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "ASPNETCORE_URLS", + "value": "http://+:5217" + }, + { + "name": "ASPNETCORE_ENVIRONMENT", + "value": "Production" + }, + { + "name": "FlowerCore__Database__ConnectionStrings__Sqlite", + "value": "Data Source=/data/ttsreader.db" + }, + { + "name": "TtsReader__Audio__OutputRoot", + "value": "/data/audio" + }, + { + "name": "TtsReader__Audio__FfmpegPath", + "value": "/usr/bin/ffmpeg" + }, + { + "name": "TtsReader__Bible__CorpusRoot", + "value": "/data/corpus-cache/world-english-bible/eng/usx" + }, + { + "name": "TtsReader__ChapterContext__DatabasePath", + "value": "/data/chapter-context.db" + }, + { + "name": "TtsReader__Jobs__Root", + "value": "/data/jobs" + }, + { + "name": "TtsReader__Export__LocalCasRoot", + "value": "/data/bundles/cas" + }, + { + "name": "TtsReader__Piper__Host", + "value": "10.0.57.17" + }, + { + "name": "TtsReader__Piper__Port", + "value": "8500" + }, + { + "name": "TtsReader__Piper__Transport", + "value": "http" + }, + { + "name": "TtsReader__Piper__HttpPath", + "value": "/tts" + }, + { + "name": "TtsReader__Kokoro__Enabled", + "value": "true" + }, + { + "name": "TtsReader__Kokoro__BaseUrl", + "value": "http://ttsreader-kokoro.fc-ttsreader.svc.cluster.local.:8880" + }, + { + "name": "TtsReader__Kokoro__TimeoutSeconds", + "value": "120" + }, + { + "name": "FlowerCore__Tts__BiblicalTts__Enabled", + "value": "true" + }, + { + "name": "FlowerCore__Tts__BiblicalTts__BaseUrl", + "value": "http://ttsreader-biblical.fc-ttsreader.svc.cluster.local.:10402" + }, + { + "name": "FlowerCore__Tts__BiblicalTts__TimeoutSeconds", + "value": "60" + }, + { + "name": "FlowerCore__Tts__BiblicalTts__DefaultLanguage", + "value": "grc" + }, + { + "name": "Speech__Alignment__Enabled", + "value": "true" + }, + { + "name": "Speech__Alignment__BaseUrl", + "value": "http://ttsreader-align.fc-ttsreader.svc.cluster.local.:9200" + }, + { + "name": "Speech__Alignment__TimeoutSeconds", + "value": "120" + }, + { + "name": "TtsReader__Transcription__Enabled", + "value": "true" + }, + { + "name": "TtsReader__Transcription__BaseUrl", + "value": "http://ttsreader-align.fc-ttsreader.svc.cluster.local.:9200" + }, + { + "name": "TtsReader__Transcription__TimeoutSeconds", + "value": "300" + }, + { + "name": "TtsReader__Ollama__BaseUrl", + "value": "http://10.0.57.201:11434" + }, + { + "name": "TtsReader__Ollama__DefaultModel", + "value": "gemma3:4b" + }, + { + "name": "TtsReader__Ollama__TimeoutSeconds", + "value": "45" + }, + { + "name": "TtsReader__Runtime__LogsRoot", + "value": "/data/logs" + }, + { + "name": "TtsReader__Runtime__SmokeStatePath", + "value": "/data/ops/smoke-status.json" + }, + { + "name": "TtsReader__Preview__CacheDirectory", + "value": "/data/voice-previews" + }, + { + "name": "TtsReader__VoiceLibrary__ReferenceClip__Directory", + "value": "/data/voice-reference-clips" + }, + { + "name": "TtsReader__Render__CdnDirectory", + "value": "/data/cdn" + }, + { + "name": "Auth__ApiKey", + "valueFrom": { + "secretKeyRef": { + "key": "Auth__ApiKey", + "name": "ttsreader-secrets", + "optional": true + } + } + }, + { + "name": "Auth__AdminApiKey", + "valueFrom": { + "secretKeyRef": { + "key": "Auth__AdminApiKey", + "name": "ttsreader-secrets", + "optional": true + } + } + } + ], + "image": "localhost/fc-ttsreader-web:v20260616-quicknav-b8c6174", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 5217, + "scheme": "HTTP" + }, + "initialDelaySeconds": 15, + "periodSeconds": 30, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "name": "web", + "ports": [ + { + "containerPort": 5217, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 5217, + "scheme": "HTTP" + }, + "initialDelaySeconds": 5, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "500m", + "memory": "512Mi" + }, + "requests": { + "cpu": "10m", + "memory": "256Mi" + } + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true, + "runAsGroup": 1654, + "runAsNonRoot": true, + "runAsUser": 1654 + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + }, + { + "mountPath": "/tmp", + "name": "tmp" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": { + "fsGroup": 1654, + "fsGroupChangePolicy": "OnRootMismatch" + }, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "ttsreader-data" + } + }, + { + "emptyDir": {}, + "name": "tmp" + } + ] + } + } + } +} diff --git a/apps-gx10/fc-ttsreader/ingressroute-ttsreader-web.json b/apps-gx10/fc-ttsreader/ingressroute-ttsreader-web.json new file mode 100644 index 0000000..25a9d5f --- /dev/null +++ b/apps-gx10/fc-ttsreader/ingressroute-ttsreader-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "ttsreader-web", + "namespace": "fc-ttsreader" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`ttsreader.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "ttsreader-web", + "port": 5217 + } + ] + } + ], + "tls": { + "secretName": "ttsreader-tls" + } + } +} diff --git a/apps-gx10/fc-ttsreader/service-ttsreader-web.json b/apps-gx10/fc-ttsreader/service-ttsreader-web.json new file mode 100644 index 0000000..807c64c --- /dev/null +++ b/apps-gx10/fc-ttsreader/service-ttsreader-web.json @@ -0,0 +1,25 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": {}, + "name": "ttsreader-web", + "namespace": "fc-ttsreader" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 5217, + "protocol": "TCP", + "targetPort": 5217 + } + ], + "selector": { + "app.kubernetes.io/name": "ttsreader-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-updater/deployment-updatecenter-web.json b/apps-gx10/fc-updater/deployment-updatecenter-web.json new file mode 100644 index 0000000..e4c3524 --- /dev/null +++ b/apps-gx10/fc-updater/deployment-updatecenter-web.json @@ -0,0 +1,273 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "updatecenter-web", + "app.kubernetes.io/name": "updatecenter-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "updatecenter-web", + "namespace": "fc-updater" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 3, + "selector": { + "matchLabels": { + "app": "updatecenter-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "fc.flowercore.io/healthz-anon": "true", + "fc.flowercore.io/probe-path": "/", + "kubectl.kubernetes.io/restartedAt": "2026-05-04T23:35:59-05:00" + }, + "labels": { + "app": "updatecenter-web" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "ASPNETCORE_URLS", + "value": "http://+:8080" + }, + { + "name": "FlowerCore__Updater__Database__Provider", + "value": "sqlite" + }, + { + "name": "FlowerCore__Updater__Database__ConnectionString", + "value": "Data Source=/data/updatecenter.db" + }, + { + "name": "FlowerCore__Updater__BundleStorage__LocalFs__RootDirectory", + "value": "/data/bundles" + }, + { + "name": "FlowerCore__Updater__PublicShares__RequirePublicVisibilityOnPublicHosts", + "value": "true" + }, + { + "name": "FlowerCore__Updater__PublicShares__Links__0__Code", + "value": "8f3c2a9e7d41" + }, + { + "name": "FlowerCore__Updater__PublicShares__Links__0__AppId", + "value": "flowercore.faith-ai-mike" + }, + { + "name": "FlowerCore__Updater__PublicShares__Links__0__Channel", + "value": "stable" + }, + { + "name": "FlowerCore__Updater__PublicShares__Links__0__RuntimeId", + "value": "win-x64" + }, + { + "name": "FlowerCore__Updater__PublicShares__Links__0__DisplayName", + "value": "Faith AI Mike Edition" + }, + { + "name": "FlowerCore__Updater__PublicShares__Links__0__Headline", + "value": "Faith AI Mike Edition" + }, + { + "name": "FlowerCore__Updater__PublicShares__Links__0__Description", + "value": "Private release link for Mike's Faith AI bundle." + }, + { + "name": "FlowerCore__Audit__Sinks__Loki__Enabled", + "value": "false" + }, + { + "name": "FlowerCore__Updater__Auth__Bootstrap__Enabled", + "value": "true" + }, + { + "name": "FlowerCore__Updater__Auth__Bootstrap__Username", + "valueFrom": { + "secretKeyRef": { + "key": "username", + "name": "updater-bootstrap-auth" + } + } + }, + { + "name": "FlowerCore__Updater__Auth__Bootstrap__Password", + "valueFrom": { + "secretKeyRef": { + "key": "password", + "name": "updater-bootstrap-auth" + } + } + }, + { + "name": "FlowerCore__Updater__Auth__Bootstrap__SigningKey", + "valueFrom": { + "secretKeyRef": { + "key": "signing-key", + "name": "updater-bootstrap-auth" + } + } + }, + { + "name": "FlowerCore__Updater__Signing__AutoSignOnPublish", + "value": "true" + }, + { + "name": "FlowerCore__Updater__Signing__RequireSignatureOnPublish", + "value": "true" + }, + { + "name": "FlowerCore__Updater__Signing__PfxBase64", + "valueFrom": { + "secretKeyRef": { + "key": "pfx-base64", + "name": "updater-signing" + } + } + }, + { + "name": "FlowerCore__Updater__Signing__PfxPassword", + "valueFrom": { + "secretKeyRef": { + "key": "pfx-password", + "name": "updater-signing" + } + } + }, + { + "name": "FlowerCore__Updater__Signing__OpItemReference", + "value": "op://FlowerCore/step-ca-codesign" + }, + { + "name": "FlowerCore__Updater__Signing__TrustAnchorPath", + "value": "/etc/flowercore-updater/signing/root-ca.pem" + }, + { + "name": "FlowerCore__Updater__GitHub__Token", + "valueFrom": { + "secretKeyRef": { + "key": "github-token", + "name": "updater-webhooks" + } + } + }, + { + "name": "FlowerCore__Updater__GitHub__WebhookSecret", + "valueFrom": { + "secretKeyRef": { + "key": "github-webhook-secret", + "name": "updater-webhooks" + } + } + }, + { + "name": "FlowerCore__Updater__Gitea__Token", + "valueFrom": { + "secretKeyRef": { + "key": "gitea-token", + "name": "updater-webhooks" + } + } + }, + { + "name": "FlowerCore__Updater__Gitea__WebhookSecret", + "valueFrom": { + "secretKeyRef": { + "key": "gitea-webhook-secret", + "name": "updater-webhooks" + } + } + }, + { + "name": "FlowerCore__Updater__BundleStorage__LocalFs__MaxTotalBytes", + "value": "26843545600" + } + ], + "image": "localhost/fc-updater-web:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "initialDelaySeconds": 30, + "periodSeconds": 30, + "successThreshold": 1, + "tcpSocket": { + "port": "http" + }, + "timeoutSeconds": 1 + }, + "name": "web", + "ports": [ + { + "containerPort": 8080, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "initialDelaySeconds": 10, + "periodSeconds": 15, + "successThreshold": 1, + "tcpSocket": { + "port": "http" + }, + "timeoutSeconds": 1 + }, + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + }, + { + "mountPath": "/etc/flowercore-updater/signing", + "name": "signing", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "updatecenter-data" + } + }, + { + "name": "signing", + "secret": { + "defaultMode": 420, + "items": [ + { + "key": "root-ca.pem", + "path": "root-ca.pem" + } + ], + "secretName": "updater-signing" + } + } + ] + } + } + } +} diff --git a/apps-gx10/fc-updater/ingressroute-updatecenter-web-gx10.json b/apps-gx10/fc-updater/ingressroute-updatecenter-web-gx10.json new file mode 100644 index 0000000..246c68d --- /dev/null +++ b/apps-gx10/fc-updater/ingressroute-updatecenter-web-gx10.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "updatecenter-web-gx10", + "namespace": "fc-updater" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "(Host(`updatecenter.iamworkin.lan`) || Host(`updates.iamworkin.lan`)) && (Method(`GET`) || Method(`HEAD`) || Method(`POST`) || Method(`OPTIONS`))", + "priority": 100, + "services": [ + { + "name": "updatecenter-web", + "port": 8080 + } + ] + } + ], + "tls": { + "secretName": "updatecenter-web-tls" + } + } +} diff --git a/apps-gx10/fc-updater/ingressroute-updatecenter-web-internal-gx10.json b/apps-gx10/fc-updater/ingressroute-updatecenter-web-internal-gx10.json new file mode 100644 index 0000000..4f2157b --- /dev/null +++ b/apps-gx10/fc-updater/ingressroute-updatecenter-web-internal-gx10.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "updatecenter-web-internal-gx10", + "namespace": "fc-updater" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`updatecenter-internal.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "updatecenter-web", + "port": 8080 + } + ] + } + ], + "tls": { + "secretName": "updatecenter-web-internal-tls" + } + } +} diff --git a/apps-gx10/fc-updater/ingressroute-updatecenter-web-public-gx10.json b/apps-gx10/fc-updater/ingressroute-updatecenter-web-public-gx10.json new file mode 100644 index 0000000..941d258 --- /dev/null +++ b/apps-gx10/fc-updater/ingressroute-updatecenter-web-public-gx10.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "updatecenter-web-public-gx10", + "namespace": "fc-updater" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "(Host(`update.flowercore.io`) || Host(`updates.flowercore.io`)) && (Method(`GET`) || Method(`HEAD`) || Method(`POST`) || Method(`OPTIONS`))", + "priority": 100, + "services": [ + { + "name": "updatecenter-web", + "port": 8080 + } + ] + } + ], + "tls": { + "secretName": "cf-origin-flowercore-io" + } + } +} diff --git a/apps-gx10/fc-updater/service-updatecenter-web.json b/apps-gx10/fc-updater/service-updatecenter-web.json new file mode 100644 index 0000000..39e12c0 --- /dev/null +++ b/apps-gx10/fc-updater/service-updatecenter-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app": "updatecenter-web", + "app.kubernetes.io/name": "updatecenter-web", + "app.kubernetes.io/part-of": "flowercore" + }, + "name": "updatecenter-web", + "namespace": "fc-updater" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 8080, + "protocol": "TCP", + "targetPort": "http" + } + ], + "selector": { + "app": "updatecenter-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/fc-worldbuilder/deployment-worldbuilder-web.json b/apps-gx10/fc-worldbuilder/deployment-worldbuilder-web.json new file mode 100644 index 0000000..c51a95a --- /dev/null +++ b/apps-gx10/fc-worldbuilder/deployment-worldbuilder-web.json @@ -0,0 +1,214 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/component": "web", + "app.kubernetes.io/managed-by": "argocd", + "app.kubernetes.io/name": "worldbuilder-web", + "app.kubernetes.io/part-of": "flowercore", + "flowercore.io/created-by": "bluejay-infra", + "flowercore.io/tenant-id": "system" + }, + "name": "worldbuilder-web", + "namespace": "fc-worldbuilder" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 3, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "worldbuilder-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "fc.flowercore.io/healthz-anon": "true", + "fc.flowercore.io/probe-path": "/healthz", + "flowercore.io/audit-trace-id": "worldbuilder-runtime-demo", + "prometheus.io/path": "/metrics/prometheus", + "prometheus.io/port": "8080", + "prometheus.io/scrape": "true" + }, + "labels": { + "app.kubernetes.io/component": "web", + "app.kubernetes.io/managed-by": "argocd", + "app.kubernetes.io/name": "worldbuilder-web", + "app.kubernetes.io/part-of": "flowercore", + "flowercore.io/created-by": "bluejay-infra", + "flowercore.io/tenant-id": "system" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "ASPNETCORE_URLS", + "value": "http://+:8080" + }, + { + "name": "ASPNETCORE_ENVIRONMENT", + "value": "Production" + }, + { + "name": "DOTNET_RUNNING_IN_CONTAINER", + "value": "true" + }, + { + "name": "DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", + "value": "false" + }, + { + "name": "ConnectionStrings__DefaultConnection", + "value": "Data Source=/data/worldbuilder.db" + }, + { + "name": "FlowerCore__Database__Provider", + "value": "Sqlite" + }, + { + "name": "FlowerCore__Database__ConnectionStrings__Sqlite", + "value": "Data Source=/data/worldbuilder.db" + }, + { + "name": "FlowerCore__WorldBuilder__ImageStore__RootPath", + "value": "/data/gallery" + }, + { + "name": "FlowerCore__WorldBuilder__Export__RootPath", + "value": "/data/exports" + }, + { + "name": "FlowerCore__WorldBuilder__ImageGeneration__BaseUrl", + "value": "http://10.0.56.20:8188" + }, + { + "name": "FlowerCore__WorldBuilder__ImageGeneration__ClientMode", + "value": "comfyui" + }, + { + "name": "FlowerCore__WorldBuilder__ImageGeneration__BackendId", + "value": "comfyui" + }, + { + "name": "FlowerCore__WorldBuilder__ImageGeneration__VisitorSafe", + "value": "false" + } + ], + "image": "localhost/fc-worldbuilder:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "initialDelaySeconds": 30, + "periodSeconds": 30, + "successThreshold": 1, + "tcpSocket": { + "port": 8080 + }, + "timeoutSeconds": 1 + }, + "name": "web", + "ports": [ + { + "containerPort": 8080, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/healthz", + "port": 8080, + "scheme": "HTTP" + }, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "1", + "memory": "768Mi" + }, + "requests": { + "cpu": "25m", + "memory": "256Mi" + } + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true, + "runAsGroup": 1654, + "runAsNonRoot": true, + "runAsUser": 1654 + }, + "startupProbe": { + "failureThreshold": 30, + "httpGet": { + "path": "/healthz", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 5, + "periodSeconds": 5, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "data" + }, + { + "mountPath": "/tmp", + "name": "tmp" + }, + { + "mountPath": "/app/logs", + "name": "logs" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": { + "fsGroup": 1654, + "fsGroupChangePolicy": "OnRootMismatch" + }, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "data", + "persistentVolumeClaim": { + "claimName": "worldbuilder-data" + } + }, + { + "emptyDir": {}, + "name": "tmp" + }, + { + "emptyDir": {}, + "name": "logs" + } + ] + } + } + } +} diff --git a/apps-gx10/fc-worldbuilder/ingressroute-worldbuilder-web.json b/apps-gx10/fc-worldbuilder/ingressroute-worldbuilder-web.json new file mode 100644 index 0000000..c49fa46 --- /dev/null +++ b/apps-gx10/fc-worldbuilder/ingressroute-worldbuilder-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "worldbuilder-web", + "namespace": "fc-worldbuilder" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`worldbuilder.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "worldbuilder-web", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "worldbuilder-web-tls" + } + } +} diff --git a/apps-gx10/fc-worldbuilder/service-worldbuilder-web.json b/apps-gx10/fc-worldbuilder/service-worldbuilder-web.json new file mode 100644 index 0000000..6bd3c3e --- /dev/null +++ b/apps-gx10/fc-worldbuilder/service-worldbuilder-web.json @@ -0,0 +1,32 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app.kubernetes.io/component": "web", + "app.kubernetes.io/managed-by": "argocd", + "app.kubernetes.io/name": "worldbuilder-web", + "app.kubernetes.io/part-of": "flowercore", + "flowercore.io/created-by": "bluejay-infra", + "flowercore.io/tenant-id": "system" + }, + "name": "worldbuilder-web", + "namespace": "fc-worldbuilder" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 8080 + } + ], + "selector": { + "app.kubernetes.io/name": "worldbuilder-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/intranet/configmap-intranet-config.json b/apps-gx10/intranet/configmap-intranet-config.json new file mode 100644 index 0000000..462eeb9 --- /dev/null +++ b/apps-gx10/intranet/configmap-intranet-config.json @@ -0,0 +1,12 @@ +{ + "apiVersion": "v1", + "data": { + "KnowledgeApiKey": "", + "TrustedHeaderSharedSecret": "" + }, + "kind": "ConfigMap", + "metadata": { + "name": "intranet-config", + "namespace": "intranet" + } +} diff --git a/apps-gx10/intranet/deployment-intranet-web.json b/apps-gx10/intranet/deployment-intranet-web.json new file mode 100644 index 0000000..11cd0f9 --- /dev/null +++ b/apps-gx10/intranet/deployment-intranet-web.json @@ -0,0 +1,160 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "intranet-web" + }, + "name": "intranet-web", + "namespace": "intranet" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "intranet-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "kubectl.kubernetes.io/restartedAt": "2026-06-14T00:57:21-05:00" + }, + "labels": { + "app": "intranet-web" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "ASPNETCORE_ENVIRONMENT", + "value": "Production" + }, + { + "name": "ASPNETCORE_URLS", + "value": "http://+:5300" + }, + { + "name": "IntranetSearch__OllamaBaseUrl", + "value": "http://10.0.57.201:11434" + }, + { + "name": "IntranetSearch__Enabled", + "value": "true" + }, + { + "name": "PageReadingOverrides__DatabasePath", + "value": "/data/page-reading-overrides.db" + }, + { + "name": "KnowledgeFleetSearch__BaseUrl", + "value": "https://knowledge.iamworkin.lan" + }, + { + "name": "KnowledgeFleetSearch__ApiKey", + "valueFrom": { + "configMapKeyRef": { + "key": "KnowledgeApiKey", + "name": "intranet-config", + "optional": true + } + } + }, + { + "name": "TrustedHeaderAuthentication__SharedSecret", + "valueFrom": { + "configMapKeyRef": { + "key": "TrustedHeaderSharedSecret", + "name": "intranet-config", + "optional": true + } + } + } + ], + "image": "localhost/fc-intranet-web:gx10-v1", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 5300, + "scheme": "HTTP" + }, + "initialDelaySeconds": 30, + "periodSeconds": 30, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "name": "intranet-web", + "ports": [ + { + "containerPort": 5300, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 5300, + "scheme": "HTTP" + }, + "initialDelaySeconds": 10, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "1", + "memory": "1Gi" + }, + "requests": { + "cpu": "100m", + "memory": "256Mi" + } + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/data", + "name": "vector-store" + }, + { + "mountPath": "/srv/flowercore-notes", + "name": "notes-corpus", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "vector-store", + "persistentVolumeClaim": { + "claimName": "intranet-vector-store" + } + }, + { + "emptyDir": {}, + "name": "notes-corpus" + } + ] + } + } + } +} diff --git a/apps-gx10/intranet/ingressroute-intranet-web.json b/apps-gx10/intranet/ingressroute-intranet-web.json new file mode 100644 index 0000000..749f4c2 --- /dev/null +++ b/apps-gx10/intranet/ingressroute-intranet-web.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "intranet-web", + "namespace": "intranet" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`intranet.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "intranet-web", + "port": 5300 + } + ] + } + ], + "tls": { + "secretName": "intranet-tls" + } + } +} diff --git a/apps-gx10/intranet/service-intranet-web.json b/apps-gx10/intranet/service-intranet-web.json new file mode 100644 index 0000000..84cb944 --- /dev/null +++ b/apps-gx10/intranet/service-intranet-web.json @@ -0,0 +1,25 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": {}, + "name": "intranet-web", + "namespace": "intranet" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 5300, + "protocol": "TCP", + "targetPort": 5300 + } + ], + "selector": { + "app": "intranet-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/telephony/certificate-yealink-provision-tls.json b/apps-gx10/telephony/certificate-yealink-provision-tls.json new file mode 100644 index 0000000..191e7b6 --- /dev/null +++ b/apps-gx10/telephony/certificate-yealink-provision-tls.json @@ -0,0 +1,18 @@ +{ + "apiVersion": "cert-manager.io/v1", + "kind": "Certificate", + "metadata": { + "name": "yealink-provision-tls", + "namespace": "telephony" + }, + "spec": { + "dnsNames": [ + "prov.telephony.iamworkin.lan" + ], + "issuerRef": { + "kind": "ClusterIssuer", + "name": "step-ca-acme" + }, + "secretName": "yealink-provision-tls" + } +} diff --git a/apps-gx10/telephony/configmap-asterisk-config.json b/apps-gx10/telephony/configmap-asterisk-config.json new file mode 100644 index 0000000..390363c --- /dev/null +++ b/apps-gx10/telephony/configmap-asterisk-config.json @@ -0,0 +1,17 @@ +{ + "apiVersion": "v1", + "data": { + "ari.conf": "[general]\nenabled=yes\npretty=yes\nallowed_origins=*\n\n[flowercore]\ntype=user\nread_only=no\npassword=bluejay-asterisk-ari\npassword_format=plain\n", + "extensions.conf": "[general]\nstatic=yes\nwriteprotect=no\n\n[from-twilio]\n; Inbound calls from Twilio SIP trunk -> FlowerCore IVR workflow\nexten => _+X.,1,Answer()\n same => n,Wait(1)\n same => n,Stasis(flowercore-pbx,inbound-pstn,${EXTEN})\n same => n,Hangup()\n\nexten => _X.,1,Answer()\n same => n,Wait(1)\n same => n,Stasis(flowercore-pbx,inbound-pstn,${EXTEN})\n same => n,Hangup()\n\n[from-internal]\n; Internal extension-to-extension dialing\nexten => _1XX,1,Dial(PJSIP/${EXTEN},30)\n same => n,Hangup()\n\n; Softphone proof endpoints and utility extensions\nexten => _9XX,1,NoOp(Proof call to ${EXTEN})\n same => n,Dial(PJSIP/${EXTEN},30)\n same => n,Hangup()\n\nexten => 999,1,Answer()\n same => n,Playback(demo-echotest)\n same => n,Echo()\n same => n,Hangup()\n\nexten => 998,1,Answer()\n same => n,Milliwatt()\n same => n,Hangup()\n\nexten => 997,1,Answer()\n same => n,Wait(0.5)\n same => n,Playback(hello-world)\n same => n,Wait(1)\n same => n,Hangup()\n\nexten => 996,1,Answer()\n same => n,Wait(0.5)\n same => n,Read(DIGITS,,4,,,5)\n same => n,SayDigits(${DIGITS})\n same => n,Hangup()\n\n; Outbound via Twilio SIP trunk (11-digit US)\nexten => _1NXXNXXXXXX,1,Set(CALLERID(num)=+13202332529)\n same => n,Dial(PJSIP/+${EXTEN}@twilio-trunk,60)\n same => n,Hangup()\n\n; Outbound via Twilio SIP trunk (+1 format)\nexten => _+1NXXNXXXXXX,1,Set(CALLERID(num)=+13202332529)\n same => n,Dial(PJSIP/${EXTEN}@twilio-trunk,60)\n same => n,Hangup()\n\n; IVR access from internal phones (when ARI is connected)\nexten => *100,1,Stasis(flowercore-pbx,internal,ivr)\n same => n,Hangup()\n\n; Test-only entry into the Victory Day workflow (DID +15074618329).\n; Used by live SIP AATs to exercise the VDAY Fun Menu + AsteriskGameHandler\n; path without dialing in over Twilio. Mnemonic: *832 = \"V-D-A\" (8-3-2).\nexten => *832,1,NoOp(Test entry: Victory Day workflow via AAT)\n same => n,Stasis(flowercore-pbx,inbound-pstn,+15074618329)\n same => n,Hangup()\n\n; Star codes routed to FlowerCore Stasis app for handling\nexten => *0,1,Stasis(flowercore-pbx,starcode,*0)\n same => n,Hangup()\nexten => *30,1,Stasis(flowercore-pbx,starcode,*30)\n same => n,Hangup()\nexten => *69,1,Stasis(flowercore-pbx,starcode,*69)\n same => n,Hangup()\nexten => *70,1,Stasis(flowercore-pbx,starcode,*70)\n same => n,Hangup()\nexten => _*70X.,1,Stasis(flowercore-pbx,starcode,${EXTEN})\n same => n,Hangup()\nexten => *71,1,Stasis(flowercore-pbx,starcode,*71)\n same => n,Hangup()\nexten => _*71X.,1,Stasis(flowercore-pbx,starcode,${EXTEN})\n same => n,Hangup()\nexten => *72,1,Stasis(flowercore-pbx,starcode,*72)\n same => n,Hangup()\nexten => *73,1,Stasis(flowercore-pbx,starcode,*73)\n same => n,Hangup()\nexten => *75,1,Stasis(flowercore-pbx,starcode,*75)\n same => n,Hangup()\nexten => *77,1,Stasis(flowercore-pbx,starcode,*77)\n same => n,Hangup()\nexten => *78,1,Stasis(flowercore-pbx,starcode,*78)\n same => n,Hangup()\nexten => *79,1,Stasis(flowercore-pbx,starcode,*79)\n same => n,Hangup()\nexten => *86,1,Stasis(flowercore-pbx,starcode,*86)\n same => n,Hangup()\nexten => *87,1,Stasis(flowercore-pbx,starcode,*87)\n same => n,Hangup()\nexten => *97,1,Stasis(flowercore-pbx,starcode,*97)\n same => n,Hangup()\nexten => *43,1,Stasis(flowercore-pbx,starcode,*43)\n same => n,Hangup()\nexten => *80,1,Stasis(flowercore-pbx,starcode,*80)\n same => n,Hangup()\nexten => *88,1,Stasis(flowercore-pbx,starcode,*88)\n same => n,Hangup()\nexten => *41,1,Stasis(flowercore-pbx,starcode,*41)\n same => n,Hangup()\nexten => *411,1,Stasis(flowercore-pbx,starcode,*411)\n same => n,Hangup()\n\n; Catch-all for any other star codes\nexten => _*X.,1,Stasis(flowercore-pbx,starcode,${EXTEN})\n same => n,Hangup()\n\n[default]\nexten => _X.,1,NoOp(Unhandled call to ${EXTEN})\n same => n,Hangup()\n", + "http.conf": "[general]\nenabled=yes\nbindaddr=0.0.0.0\nbindport=8088\n", + "manager.conf": "[general]\nenabled=no\n", + "modules.conf": "[modules]\nautoload=yes\nnoload=chan_sip.so\nnoload=res_hep.so\nnoload=res_hep_pjsip.so\nnoload=res_hep_rtcp.so\n", + "pjsip.conf": "; ===== Transports =====\n[transport-udp]\ntype=transport\nprotocol=udp\nbind=0.0.0.0:5060\n; NAT: internal phones see node IP, Twilio sees public IP\nlocal_net=10.0.0.0/8\nlocal_net=172.16.0.0/12\nlocal_net=192.168.0.0/16\nexternal_media_address=74.40.140.28\nexternal_signaling_address=74.40.140.28\n\n; ===== Global endpoint identification / anti-scanner hardening =====\n; Reimagined 2026-06-15 (Blue Jay SIP). Identify Twilio by source IP first,\n; then userpass for phones, then anonymous LAST. There is NO [anonymous]\n; endpoint, so any REGISTER/INVITE matching neither an identify block nor a\n; named endpoint+auth is REJECTED (kills the brute-force REGISTER flood).\n[global]\ntype=global\nendpoint_identifier_order=ip,username,anonymous\n\n; ===== Inbound ACL (defense in depth) =====\n; Single global ACL evaluated by res_pjsip_acl for ALL inbound SIP.\n; Permit LAN + Andrew VPN + Twilio NA signaling blocks; deny everything else.\n; (Twilio inbound arrives post-pfSense-NAT as 10.0.56.14 -> covered by 10.0.0.0/8,\n; but the Twilio blocks are listed explicitly for clarity / future direct peering.)\n[lan-vpn-only]\ntype=acl\ndeny=0.0.0.0/0.0.0.0\npermit=10.0.0.0/255.0.0.0\npermit=10.0.68.0/255.255.255.224\npermit=54.172.60.0/255.255.255.252\npermit=54.172.60.4/255.255.255.252\npermit=54.244.51.0/255.255.255.252\npermit=54.244.51.4/255.255.255.252\npermit=34.203.250.0/255.255.254.0\npermit=54.171.127.192/255.255.255.192\npermit=35.156.191.128/255.255.255.128\npermit=54.65.63.192/255.255.255.192\npermit=54.169.127.128/255.255.255.192\npermit=54.252.254.64/255.255.255.192\npermit=177.71.206.192/255.255.255.192\n\n; ===== Twilio SIP Trunk =====\n[twilio-trunk]\ntype=endpoint\ncontext=from-twilio\ntransport=transport-udp\ndisallow=all\nallow=ulaw\nallow=alaw\nallow=g722\naors=twilio-trunk\nfrom_domain=sip.twilio.com\ndirect_media=no\nice_support=no\nrtp_symmetric=yes\nforce_rport=yes\nrewrite_contact=yes\ntrust_id_inbound=yes\n\n[twilio-trunk]\ntype=aor\ncontact=sip:bluejay.pstn.twilio.com\n\n[twilio-trunk]\ntype=identify\nendpoint=twilio-trunk\n; Twilio North America signaling IPs\nmatch=54.172.60.0/30\nmatch=54.172.60.4/30\nmatch=54.244.51.0/30\nmatch=54.244.51.4/30\nmatch=34.203.250.0/23\nmatch=54.171.127.192/26\nmatch=35.156.191.128/25\nmatch=54.65.63.192/26\nmatch=54.169.127.128/26\nmatch=54.252.254.64/26\nmatch=177.71.206.192/26\n\n; ===== Phone Template (Yealink desk + softphones) =====\n; opus first for the mobile softphones (Family iPhone / Blue Jay Android),\n; ulaw/alaw guarantee interop; g722 wideband for the desk phone.\n; dtmf_mode=rfc4733 is LOAD-BEARING: in-call star codes (*0 etc.) reach the\n; ARI flowercore-pbx app only if DTMF arrives as RFC4733 events. Do NOT change.\n[phone-template](!)\ntype=endpoint\ncontext=from-internal\ntransport=transport-udp\ndisallow=all\nallow=opus\nallow=g722\nallow=ulaw\nallow=alaw\ndirect_media=no\ndtmf_mode=rfc4733\nrtp_symmetric=yes\nforce_rport=yes\nrewrite_contact=yes\n; Advertise the MetalLB VIP (reachable from the phone) for media, so the phone's\n; upstream RTP \u2014 which carries rfc4733 DTMF \u2014 actually reaches Asterisk. The RTP\n; range is exposed on the asterisk-sip LoadBalancer (externalTrafficPolicy=Local).\nmedia_address=10.0.57.203\n\n; Extension 100 - Blue Jay's Nest\n[100](phone-template)\nauth=auth100\naors=100\ncallerid=\"Blue Jay's Nest\" <100>\n\n[auth100]\ntype=auth\nauth_type=userpass\nusername=100\npassword=kvNiD1gCeX5DCfTYrapGQxpu2wU7\n\n[100]\ntype=aor\nmax_contacts=1\nremove_existing=yes\nqualify_frequency=60\n\n; Extension 110 - Family iPhone\n[110](phone-template)\nauth=auth110\naors=110\ncallerid=\"Family iPhone\" <110>\n\n[auth110]\ntype=auth\nauth_type=userpass\nusername=110\npassword=wanVn0oqExl8wUfFJ3hx6BGAcvNF\n\n[110]\ntype=aor\nmax_contacts=1\nremove_existing=yes\nqualify_frequency=60\n\n; Extension 111 - Blue Jay Android\n[111](phone-template)\nauth=auth111\naors=111\ncallerid=\"Blue Jay Android\" <111>\n\n[auth111]\ntype=auth\nauth_type=userpass\nusername=111\npassword=C14qNz2rDRRgyAsUjrZGAMilLMcO\n\n[111]\ntype=aor\nmax_contacts=1\nremove_existing=yes\nqualify_frequency=60\n\n; Extension 101 - Office 1\n[101](phone-template)\nauth=auth101\naors=101\ncallerid=\"Office 1\" <101>\n\n[auth101]\ntype=auth\nauth_type=userpass\nusername=101\npassword=knYPbhnWQtfbWJr9hOPUql6InJns\n\n[101]\ntype=aor\nmax_contacts=1\nremove_existing=yes\nqualify_frequency=60\n\n; Extension 102 - Office 2\n[102](phone-template)\nauth=auth102\naors=102\ncallerid=\"Office 2\" <102>\n\n[auth102]\ntype=auth\nauth_type=userpass\nusername=102\npassword=D0aJY4LFKievwcRszq3TkbkhG1F7\n\n[102]\ntype=aor\nmax_contacts=1\nremove_existing=yes\nqualify_frequency=60\n\n; Extension 103 - Office 3\n[103](phone-template)\nauth=auth103\naors=103\ncallerid=\"Office 3\" <103>\n\n[auth103]\ntype=auth\nauth_type=userpass\nusername=103\npassword=56I8Q3oNOrd1nQMzWjeqizX0G4UI\n\n[103]\ntype=aor\nmax_contacts=1\nremove_existing=yes\nqualify_frequency=60\n\n; ===== Test endpoints 901-904 (softphone proof harness) =====\n[test-endpoint](!)\ntype=endpoint\ncontext=from-internal\ntransport=transport-udp\ndisallow=all\nallow=ulaw\nallow=alaw\ndirect_media=no\nrtp_symmetric=yes\nforce_rport=yes\nrewrite_contact=yes\nmedia_address=10.0.57.203\n\n[901](test-endpoint)\nauth=auth901\naors=901\ncallerid=\"Proof Caller\" <901>\n\n[auth901]\ntype=auth\nauth_type=userpass\nusername=901\npassword=Q0ti3c03K7xuKgMY6svBo9WGx0Rx\n\n[901]\ntype=aor\nmax_contacts=1\nremove_existing=yes\n\n[902](test-endpoint)\nauth=auth902\naors=902\ncallerid=\"Proof Callee\" <902>\n\n[auth902]\ntype=auth\nauth_type=userpass\nusername=902\npassword=uzcOVNn283sMtBtUT15ARY1I4J1K\n\n[902]\ntype=aor\nmax_contacts=1\nremove_existing=yes\n\n[903](test-endpoint)\nauth=auth903\naors=903\ncallerid=\"Proof Endpoint 3\" <903>\n\n[auth903]\ntype=auth\nauth_type=userpass\nusername=903\npassword=oD73km75xk3GzDMXUU8HNo4lIIOx\n\n[903]\ntype=aor\nmax_contacts=1\nremove_existing=yes\n\n[904](test-endpoint)\nauth=auth904\naors=904\ncallerid=\"Proof Endpoint 4\" <904>\n\n[auth904]\ntype=auth\nauth_type=userpass\nusername=904\npassword=EvljdvMTZ7SXkBPRUTWAcSge27Bk\n\n[904]\ntype=aor\nmax_contacts=1\nremove_existing=yes\n", + "rtp.conf": "[general]\nrtpstart=10000\nrtpend=10030\nstrictrtp=yes\nicesupport=no\n" + }, + "kind": "ConfigMap", + "metadata": { + "name": "asterisk-config", + "namespace": "telephony" + } +} diff --git a/apps-gx10/telephony/configmap-telephony-config.json b/apps-gx10/telephony/configmap-telephony-config.json new file mode 100644 index 0000000..eb3c352 --- /dev/null +++ b/apps-gx10/telephony/configmap-telephony-config.json @@ -0,0 +1,11 @@ +{ + "apiVersion": "v1", + "data": { + "appsettings.Production.json": "{\n \"Telephony\": {\n \"Provider\": \"asterisk\",\n \"Twilio\": {\n \"VoiceUrl\": \"https://telephony.flowercore.io/api/twilio/webhooks/voice/incoming\",\n \"StatusCallbackUrl\": \"https://telephony.flowercore.io/api/twilio/webhooks/voice/status\"\n },\n \"Asterisk\": {\n \"BaseUrl\": \"http://asterisk-ari.telephony.svc.cluster.local:8088\",\n \"Username\": \"flowercore\",\n \"Password\": \"bluejay-asterisk-ari\",\n \"Application\": \"flowercore-pbx\",\n \"ReconnectDelaySeconds\": 5,\n \"MaxReconnectDelaySeconds\": 60\n }\n },\n \"Ari\": {\n \"BaseUrl\": \"http://asterisk-ari.telephony.svc.cluster.local:8088\",\n \"Username\": \"flowercore\",\n \"Password\": \"bluejay-asterisk-ari\",\n \"Application\": \"flowercore-pbx\",\n \"ReconnectDelaySeconds\": 5,\n \"MaxReconnectDelaySeconds\": 60,\n \"WebSocketKeepAliveIntervalSeconds\": 30\n },\n \"Sip\": {\n \"Domain\": \"10.0.57.203\",\n \"Port\": 5060,\n \"Transport\": \"udp\"\n },\n \"Tts\": {\n \"PiperUrl\": \"http://10.0.56.14:30850\",\n \"DefaultEngine\": \"piper\",\n \"SampleRate\": 8000\n },\n \"DatabaseProvider\": \"Sqlite\",\n \"ConnectionStrings\": {\n \"DefaultConnection\": \"Data Source=/data/telephony.db\"\n },\n \"Kestrel\": {\n \"Endpoints\": {\n \"Http\": {\n \"Url\": \"http://0.0.0.0:5100\"\n }\n }\n }\n}" + }, + "kind": "ConfigMap", + "metadata": { + "name": "telephony-config", + "namespace": "telephony" + } +} diff --git a/apps-gx10/telephony/configmap-yealink-provisioning.json b/apps-gx10/telephony/configmap-yealink-provisioning.json new file mode 100644 index 0000000..4321784 --- /dev/null +++ b/apps-gx10/telephony/configmap-yealink-provisioning.json @@ -0,0 +1,18 @@ +{ + "apiVersion": "v1", + "data": { + "ext100.cfg": "#!version:1.0.0.1\naccount.1.enable = 1\naccount.1.label = Blue Jay's Nest\naccount.1.display_name = Blue Jay's Nest\naccount.1.auth_name = 100\naccount.1.user_name = 100\naccount.1.password = kvNiD1gCeX5DCfTYrapGQxpu2wU7\naccount.1.sip_server.1.address = 10.0.57.203\naccount.1.sip_server.1.port = 5060\naccount.1.sip_server.1.transport_type = 0\n", + "ext101.cfg": "#!version:1.0.0.1\naccount.1.enable = 1\naccount.1.label = Office 1\naccount.1.display_name = Office 1\naccount.1.auth_name = 101\naccount.1.user_name = 101\naccount.1.password = knYPbhnWQtfbWJr9hOPUql6InJns\naccount.1.sip_server.1.address = 10.0.57.203\naccount.1.sip_server.1.port = 5060\naccount.1.sip_server.1.transport_type = 0\n", + "ext102.cfg": "#!version:1.0.0.1\naccount.1.enable = 1\naccount.1.label = Office 2\naccount.1.display_name = Office 2\naccount.1.auth_name = 102\naccount.1.user_name = 102\naccount.1.password = D0aJY4LFKievwcRszq3TkbkhG1F7\naccount.1.sip_server.1.address = 10.0.57.203\naccount.1.sip_server.1.port = 5060\naccount.1.sip_server.1.transport_type = 0\n", + "ext103.cfg": "#!version:1.0.0.1\naccount.1.enable = 1\naccount.1.label = Office 3\naccount.1.display_name = Office 3\naccount.1.auth_name = 103\naccount.1.user_name = 103\naccount.1.password = 56I8Q3oNOrd1nQMzWjeqizX0G4UI\naccount.1.sip_server.1.address = 10.0.57.203\naccount.1.sip_server.1.port = 5060\naccount.1.sip_server.1.transport_type = 0\n", + "ext110.cfg": "#!version:1.0.0.1\naccount.1.enable = 1\naccount.1.label = Family iPhone\naccount.1.display_name = Family iPhone\naccount.1.auth_name = 110\naccount.1.user_name = 110\naccount.1.password = wanVn0oqExl8wUfFJ3hx6BGAcvNF\naccount.1.sip_server.1.address = 10.0.57.203\naccount.1.sip_server.1.port = 5060\naccount.1.sip_server.1.transport_type = 0\n", + "ext111.cfg": "#!version:1.0.0.1\naccount.1.enable = 1\naccount.1.label = Blue Jay Android\naccount.1.display_name = Blue Jay Android\naccount.1.auth_name = 111\naccount.1.user_name = 111\naccount.1.password = C14qNz2rDRRgyAsUjrZGAMilLMcO\naccount.1.sip_server.1.address = 10.0.57.203\naccount.1.sip_server.1.port = 5060\naccount.1.sip_server.1.transport_type = 0\n", + "nginx.conf": "server {\n listen 80;\n root /usr/share/nginx/html/provision;\n autoindex off;\n\n location /provision/ {\n alias /usr/share/nginx/html/provision/;\n default_type application/octet-stream;\n }\n}\n", + "y000000000000.cfg": "#!version:1.0.0.1\n## Yealink Global Auto-Provisioning Config\n## Applied to all Yealink phones that contact this server\n\n## SIP Account 1\naccount.1.enable = 1\naccount.1.label = BlueJay\naccount.1.display_name = $MAC\naccount.1.sip_server.1.address = 10.0.57.203\naccount.1.sip_server.1.port = 5060\naccount.1.sip_server.1.transport_type = 0\naccount.1.sip_server.1.expires = 3600\naccount.1.codec.1.enable = 1\naccount.1.codec.1.payload_type = g722\naccount.1.codec.1.priority = 0\naccount.1.codec.2.enable = 1\naccount.1.codec.2.payload_type = PCMU\naccount.1.codec.2.priority = 1\naccount.1.codec.3.enable = 1\naccount.1.codec.3.payload_type = PCMA\naccount.1.codec.3.priority = 2\naccount.1.codec.4.enable = 1\naccount.1.codec.4.payload_type = opus\naccount.1.codec.4.priority = 3\n\n## Network\nnetwork.dhcp_host_name =\nnetwork.vlan.internet_port_enable = 0\n\n## Time\nlocal_time.time_zone = -6\nlocal_time.time_zone_name = United States-Central Time\nlocal_time.ntp_server1 = 10.0.56.1\nlocal_time.date_format = 1\nlocal_time.time_format = 1\nlocal_time.manual_ntp_srv_prior = 1\n\n## Phone Settings\nphone_setting.ring_type = Ring1.wav\nfeatures.power_saving.enable = 0\n\n## DTMF \u2014 use RFC2833 (RFC4733) for Asterisk ARI compatibility\naccount.1.dtmf.type = 1\naccount.1.dtmf.dtmf_payload = 101\n\n## Dial Plan \u2014 send ALL * codes to the SIP server (do NOT handle locally)\n## Without this, *0 etc. get intercepted by the phone firmware\ndialplan.digitmap = { *x+ | *xx | *xxx | *xxxx | [1-9]xx | +x+ | 1xxxxxxxxxx | x+ }\ndialplan.digitmap.apply_to = 0\n\n## Disable local feature code handling \u2014 let the server handle everything\nfeatures.pickup.direct_pickup_enable = 0\nfeatures.pickup.direct_pickup_code =\nfeatures.pickup.group_pickup_enable = 0\nfeatures.pickup.group_pickup_code =\nfeatures.key_as_send = 1\n\n## Disable local voicemail \u2014 server handles voicemail via star codes\nvoice_mail.number.1 =\naccount.1.voice_mail.number =\n\n## Provisioning\nauto_provision.server.url = https://prov.telephony.iamworkin.lan/provision\nauto_provision.repeat.enable = 1\nauto_provision.repeat.minutes = 1440\n" + }, + "kind": "ConfigMap", + "metadata": { + "name": "yealink-provisioning", + "namespace": "telephony" + } +} diff --git a/apps-gx10/telephony/deployment-asterisk.json b/apps-gx10/telephony/deployment-asterisk.json new file mode 100644 index 0000000..edb6923 --- /dev/null +++ b/apps-gx10/telephony/deployment-asterisk.json @@ -0,0 +1,326 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "asterisk" + }, + "name": "asterisk", + "namespace": "telephony" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "asterisk" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "kubectl.kubernetes.io/restartedAt": "2026-06-16T13:09:51-05:00" + }, + "labels": { + "app": "asterisk" + } + }, + "spec": { + "containers": [ + { + "image": "localhost/andrius/asterisk:latest", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "initialDelaySeconds": 15, + "periodSeconds": 10, + "successThreshold": 1, + "tcpSocket": { + "port": 8088 + }, + "timeoutSeconds": 1 + }, + "name": "asterisk", + "ports": [ + { + "containerPort": 5060, + "name": "sip-udp", + "protocol": "UDP" + }, + { + "containerPort": 5060, + "name": "sip-tcp", + "protocol": "TCP" + }, + { + "containerPort": 8088, + "name": "ari", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "httpHeaders": [ + { + "name": "Authorization", + "value": "Basic Zmxvd2VyY29yZTpibHVlamF5LWFzdGVyaXNrLWFyaQ==" + } + ], + "path": "/ari/asterisk/info", + "port": 8088, + "scheme": "HTTP" + }, + "initialDelaySeconds": 10, + "periodSeconds": 5, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "1", + "memory": "512Mi" + }, + "requests": { + "cpu": "100m", + "memory": "128Mi" + } + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/etc/asterisk/modules.conf", + "name": "config-modules", + "subPath": "modules.conf" + }, + { + "mountPath": "/etc/asterisk/http.conf", + "name": "config-http", + "subPath": "http.conf" + }, + { + "mountPath": "/etc/asterisk/ari.conf", + "name": "config-ari", + "subPath": "ari.conf" + }, + { + "mountPath": "/etc/asterisk/manager.conf", + "name": "config-manager", + "subPath": "manager.conf" + }, + { + "mountPath": "/etc/asterisk/pjsip.conf", + "name": "config-pjsip", + "subPath": "pjsip.conf" + }, + { + "mountPath": "/etc/asterisk/extensions.conf", + "name": "config-extensions", + "subPath": "extensions.conf" + }, + { + "mountPath": "/etc/asterisk/rtp.conf", + "name": "config-rtp", + "subPath": "rtp.conf" + }, + { + "mountPath": "/var/spool/asterisk", + "name": "asterisk-data" + }, + { + "mountPath": "/var/log/asterisk", + "name": "asterisk-logs" + }, + { + "mountPath": "/var/lib/asterisk/sounds/en", + "name": "sounds" + }, + { + "mountPath": "/var/lib/asterisk/sounds/tts", + "name": "shared-tts" + } + ] + } + ], + "dnsConfig": { + "nameservers": [ + "10.43.0.10" + ], + "options": [ + { + "name": "ndots", + "value": "2" + } + ], + "searches": [ + "telephony.svc.cluster.local", + "svc.cluster.local", + "cluster.local" + ] + }, + "dnsPolicy": "None", + "hostAliases": [ + { + "hostnames": [ + "downloads.asterisk.org" + ], + "ip": "165.22.184.19" + } + ], + "initContainers": [ + { + "command": [ + "sh", + "-c", + "set -eu\nif [ -f /sounds/en/vm-goodbye.ulaw ] || [ -f /sounds/en/vm-goodbye.gsm ]; then\n echo \"Sounds already present \u00e2\u20ac\u201d skipping download.\"\n exit 0\nfi\necho \"Installing curl + tar...\"\napk add --no-cache curl tar gzip >/dev/null\ncd /tmp\necho \"Downloading Asterisk core sounds (en, ulaw) 1.6.1...\"\n# -k: cluster egress goes through a step-ca MITM for outbound TLS\n# that this pod does not trust. The tarball is a public artifact \u00e2\u20ac\u201d\n# integrity is checked downstream by Asterisk at playback time.\ncurl -fksSLO https://downloads.asterisk.org/pub/telephony/sounds/releases/asterisk-core-sounds-en-ulaw-1.6.1.tar.gz\necho \"Extracting to /sounds/en ...\"\nmkdir -p /sounds/en\ntar -xzf asterisk-core-sounds-en-ulaw-1.6.1.tar.gz -C /sounds/en\necho \"Done \u00e2\u20ac\u201d $(ls /sounds/en | wc -l) files installed.\"\n" + ], + "image": "alpine:3.20", + "imagePullPolicy": "IfNotPresent", + "name": "install-sounds", + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/sounds/en", + "name": "sounds" + } + ] + } + ], + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": { + "fsGroup": 0 + }, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "configMap": { + "defaultMode": 420, + "items": [ + { + "key": "modules.conf", + "path": "modules.conf" + } + ], + "name": "asterisk-config" + }, + "name": "config-modules" + }, + { + "configMap": { + "defaultMode": 420, + "items": [ + { + "key": "http.conf", + "path": "http.conf" + } + ], + "name": "asterisk-config" + }, + "name": "config-http" + }, + { + "configMap": { + "defaultMode": 420, + "items": [ + { + "key": "ari.conf", + "path": "ari.conf" + } + ], + "name": "asterisk-config" + }, + "name": "config-ari" + }, + { + "configMap": { + "defaultMode": 420, + "items": [ + { + "key": "manager.conf", + "path": "manager.conf" + } + ], + "name": "asterisk-config" + }, + "name": "config-manager" + }, + { + "configMap": { + "defaultMode": 420, + "items": [ + { + "key": "pjsip.conf", + "path": "pjsip.conf" + } + ], + "name": "asterisk-config" + }, + "name": "config-pjsip" + }, + { + "configMap": { + "defaultMode": 420, + "items": [ + { + "key": "extensions.conf", + "path": "extensions.conf" + } + ], + "name": "asterisk-config" + }, + "name": "config-extensions" + }, + { + "configMap": { + "defaultMode": 420, + "items": [ + { + "key": "rtp.conf", + "path": "rtp.conf" + } + ], + "name": "asterisk-config" + }, + "name": "config-rtp" + }, + { + "name": "asterisk-data", + "persistentVolumeClaim": { + "claimName": "asterisk-data" + } + }, + { + "emptyDir": {}, + "name": "asterisk-logs" + }, + { + "emptyDir": {}, + "name": "sounds" + }, + { + "hostPath": { + "path": "/tmp/tts-audio", + "type": "DirectoryOrCreate" + }, + "name": "shared-tts" + }, + { + "hostPath": { + "path": "/tmp/tts-audio", + "type": "DirectoryOrCreate" + }, + "name": "tts-shared" + } + ] + } + } + } +} diff --git a/apps-gx10/telephony/deployment-telephony-web.json b/apps-gx10/telephony/deployment-telephony-web.json new file mode 100644 index 0000000..c6ce6fc --- /dev/null +++ b/apps-gx10/telephony/deployment-telephony-web.json @@ -0,0 +1,259 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "telephony-web" + }, + "name": "telephony-web", + "namespace": "telephony" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "telephony-web" + } + }, + "strategy": { + "type": "Recreate" + }, + "template": { + "metadata": { + "annotations": { + "fc.flowercore.io/healthz-anon": "true", + "fc.flowercore.io/probe-path": "/health", + "kubectl.kubernetes.io/restartedAt": "2026-06-15T18:24:58-05:00", + "operator.1password.io/last-restarted": "2026-03-10T17:28:16Z" + }, + "labels": { + "app": "telephony-web" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "Telephony__Twilio__AccountSid", + "valueFrom": { + "secretKeyRef": { + "key": "AccountSid", + "name": "twilio-credentials", + "optional": true + } + } + }, + { + "name": "Telephony__Twilio__AuthToken", + "valueFrom": { + "secretKeyRef": { + "key": "AuthToken", + "name": "twilio-credentials", + "optional": true + } + } + }, + { + "name": "Telephony__Twilio__DefaultFromNumber", + "valueFrom": { + "secretKeyRef": { + "key": "DefaultFromNumber", + "name": "twilio-credentials", + "optional": true + } + } + }, + { + "name": "Tts__PiperUrl", + "value": "http://10.0.56.14:30850" + }, + { + "name": "Ari__Username", + "value": "flowercore" + }, + { + "name": "Ari__Password", + "value": "bluejay-asterisk-ari" + }, + { + "name": "Logging__LogLevel__FlowerCore.Telephony.Web.Services.DtmfCollector", + "value": "Debug" + }, + { + "name": "Logging__LogLevel__FlowerCore.Telephony.Web.Daemons.AriEventHandlerRegistration", + "value": "Debug" + }, + { + "name": "Logging__LogLevel__FlowerCore.Telephony.Web.Providers.Asterisk.AsteriskProvider", + "value": "Debug" + }, + { + "name": "Logging__LogLevel__FlowerCore.Telephony.Web.Handlers.StarCodeHandler", + "value": "Debug" + }, + { + "name": "Telephony__Tts__DefaultEngine", + "value": "piper" + } + ], + "image": "localhost/fc-telephony-web:gx10-v2", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 5100, + "scheme": "HTTP" + }, + "initialDelaySeconds": 30, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "name": "telephony-web", + "ports": [ + { + "containerPort": 5100, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 5100, + "scheme": "HTTP" + }, + "initialDelaySeconds": 10, + "periodSeconds": 5, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "cpu": "1", + "memory": "1Gi" + }, + "requests": { + "cpu": "100m", + "memory": "256Mi" + } + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/app/appsettings.Production.json", + "name": "telephony-config", + "readOnly": true, + "subPath": "appsettings.Production.json" + }, + { + "mountPath": "/data", + "name": "telephony-data" + }, + { + "mountPath": "/tmp", + "name": "tmp" + }, + { + "mountPath": "/app/logs", + "name": "logs" + }, + { + "mountPath": "/shared-tts", + "name": "shared-tts" + } + ] + } + ], + "dnsPolicy": "ClusterFirstWithHostNet", + "hostNetwork": true, + "initContainers": [ + { + "command": [ + "sh", + "-c", + "chmod 0777 /shared-tts && echo tts-perms-fixed" + ], + "image": "localhost/fc-telephony-web:gx10-v1", + "imagePullPolicy": "IfNotPresent", + "name": "fix-tts-perms", + "resources": {}, + "securityContext": { + "runAsNonRoot": false, + "runAsUser": 0 + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/shared-tts", + "name": "shared-tts" + } + ] + } + ], + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": { + "fsGroup": 1654, + "runAsGroup": 1654, + "runAsNonRoot": true, + "runAsUser": 1654 + }, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "configMap": { + "defaultMode": 420, + "name": "telephony-config" + }, + "name": "telephony-config" + }, + { + "name": "telephony-data", + "persistentVolumeClaim": { + "claimName": "telephony-data" + } + }, + { + "emptyDir": {}, + "name": "tmp" + }, + { + "emptyDir": {}, + "name": "logs" + }, + { + "hostPath": { + "path": "/tmp/tts-audio", + "type": "DirectoryOrCreate" + }, + "name": "shared-tts" + }, + { + "hostPath": { + "path": "/tmp/tts-audio", + "type": "DirectoryOrCreate" + }, + "name": "tts-shared" + } + ] + } + } + } +} diff --git a/apps-gx10/telephony/deployment-yealink-provision.json b/apps-gx10/telephony/deployment-yealink-provision.json new file mode 100644 index 0000000..f796a4c --- /dev/null +++ b/apps-gx10/telephony/deployment-yealink-provision.json @@ -0,0 +1,100 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "yealink-provision" + }, + "name": "yealink-provision", + "namespace": "telephony" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "yealink-provision" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%" + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "labels": { + "app": "yealink-provision" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:alpine", + "imagePullPolicy": "IfNotPresent", + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "protocol": "TCP" + } + ], + "resources": { + "limits": { + "cpu": "200m", + "memory": "64Mi" + }, + "requests": { + "cpu": "10m", + "memory": "16Mi" + } + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/usr/share/nginx/html/provision", + "name": "configs" + }, + { + "mountPath": "/etc/nginx/conf.d/default.conf", + "name": "nginx-conf", + "subPath": "nginx.conf" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "configMap": { + "defaultMode": 420, + "name": "yealink-provisioning" + }, + "name": "configs" + }, + { + "configMap": { + "defaultMode": 420, + "items": [ + { + "key": "nginx.conf", + "path": "nginx.conf" + } + ], + "name": "yealink-provisioning" + }, + "name": "nginx-conf" + } + ] + } + } + } +} diff --git a/apps-gx10/telephony/ingressroute-telephony-web-gx10.json b/apps-gx10/telephony/ingressroute-telephony-web-gx10.json new file mode 100644 index 0000000..c02e055 --- /dev/null +++ b/apps-gx10/telephony/ingressroute-telephony-web-gx10.json @@ -0,0 +1,40 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "telephony-web-gx10", + "namespace": "telephony" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`telephony.flowercore.io`)", + "priority": 100, + "services": [ + { + "name": "telephony-web", + "port": 5100 + } + ] + }, + { + "kind": "Rule", + "match": "Host(`telephony.iamwork.in`)", + "priority": 100, + "services": [ + { + "name": "telephony-web", + "port": 5100 + } + ] + } + ], + "tls": { + "secretName": "cf-origin-flowercore-io" + } + } +} diff --git a/apps-gx10/telephony/ingressroute-telephony-web-internal-gx10.json b/apps-gx10/telephony/ingressroute-telephony-web-internal-gx10.json new file mode 100644 index 0000000..6979404 --- /dev/null +++ b/apps-gx10/telephony/ingressroute-telephony-web-internal-gx10.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "telephony-web-internal-gx10", + "namespace": "telephony" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`telephony.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "telephony-web", + "port": 5100 + } + ] + } + ], + "tls": { + "secretName": "telephony-internal-tls" + } + } +} diff --git a/apps-gx10/telephony/ingressroute-yealink-provision.json b/apps-gx10/telephony/ingressroute-yealink-provision.json new file mode 100644 index 0000000..fb63679 --- /dev/null +++ b/apps-gx10/telephony/ingressroute-yealink-provision.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "traefik.io/v1alpha1", + "kind": "IngressRoute", + "metadata": { + "name": "yealink-provision", + "namespace": "telephony" + }, + "spec": { + "entryPoints": [ + "websecure" + ], + "routes": [ + { + "kind": "Rule", + "match": "Host(`prov.telephony.iamworkin.lan`)", + "priority": 100, + "services": [ + { + "name": "yealink-provision", + "port": 80 + } + ] + } + ], + "tls": { + "secretName": "yealink-provision-tls" + } + } +} diff --git a/apps-gx10/telephony/service-asterisk-ari.json b/apps-gx10/telephony/service-asterisk-ari.json new file mode 100644 index 0000000..43755d6 --- /dev/null +++ b/apps-gx10/telephony/service-asterisk-ari.json @@ -0,0 +1,24 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "name": "asterisk-ari", + "namespace": "telephony" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "ari", + "port": 8088, + "protocol": "TCP", + "targetPort": 8088 + } + ], + "selector": { + "app": "asterisk" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/telephony/service-asterisk-sip.json b/apps-gx10/telephony/service-asterisk-sip.json new file mode 100644 index 0000000..a6500cf --- /dev/null +++ b/apps-gx10/telephony/service-asterisk-sip.json @@ -0,0 +1,259 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "annotations": { + "metallb.io/ip-allocated-from-pool": "prod-pool", + "metallb.universe.tf/loadBalancerIPs": "10.0.57.203" + }, + "labels": { + "app": "asterisk" + }, + "name": "asterisk-sip", + "namespace": "telephony" + }, + "spec": { + "allocateLoadBalancerNodePorts": true, + "externalTrafficPolicy": "Local", + "healthCheckNodePort": 32642, + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "sip-udp", + "nodePort": 30143, + "port": 5060, + "protocol": "UDP", + "targetPort": 5060 + }, + { + "name": "sip-tcp", + "nodePort": 30143, + "port": 5060, + "protocol": "TCP", + "targetPort": 5060 + }, + { + "name": "rtp-10000", + "nodePort": 31818, + "port": 10000, + "protocol": "UDP", + "targetPort": 10000 + }, + { + "name": "rtp-10001", + "nodePort": 30670, + "port": 10001, + "protocol": "UDP", + "targetPort": 10001 + }, + { + "name": "rtp-10002", + "nodePort": 30807, + "port": 10002, + "protocol": "UDP", + "targetPort": 10002 + }, + { + "name": "rtp-10003", + "nodePort": 32369, + "port": 10003, + "protocol": "UDP", + "targetPort": 10003 + }, + { + "name": "rtp-10004", + "nodePort": 30585, + "port": 10004, + "protocol": "UDP", + "targetPort": 10004 + }, + { + "name": "rtp-10005", + "nodePort": 31732, + "port": 10005, + "protocol": "UDP", + "targetPort": 10005 + }, + { + "name": "rtp-10006", + "nodePort": 31964, + "port": 10006, + "protocol": "UDP", + "targetPort": 10006 + }, + { + "name": "rtp-10007", + "nodePort": 30590, + "port": 10007, + "protocol": "UDP", + "targetPort": 10007 + }, + { + "name": "rtp-10008", + "nodePort": 32576, + "port": 10008, + "protocol": "UDP", + "targetPort": 10008 + }, + { + "name": "rtp-10009", + "nodePort": 30609, + "port": 10009, + "protocol": "UDP", + "targetPort": 10009 + }, + { + "name": "rtp-10010", + "nodePort": 31719, + "port": 10010, + "protocol": "UDP", + "targetPort": 10010 + }, + { + "name": "rtp-10011", + "nodePort": 31134, + "port": 10011, + "protocol": "UDP", + "targetPort": 10011 + }, + { + "name": "rtp-10012", + "nodePort": 32402, + "port": 10012, + "protocol": "UDP", + "targetPort": 10012 + }, + { + "name": "rtp-10013", + "nodePort": 32366, + "port": 10013, + "protocol": "UDP", + "targetPort": 10013 + }, + { + "name": "rtp-10014", + "nodePort": 32726, + "port": 10014, + "protocol": "UDP", + "targetPort": 10014 + }, + { + "name": "rtp-10015", + "nodePort": 30626, + "port": 10015, + "protocol": "UDP", + "targetPort": 10015 + }, + { + "name": "rtp-10016", + "nodePort": 32040, + "port": 10016, + "protocol": "UDP", + "targetPort": 10016 + }, + { + "name": "rtp-10017", + "nodePort": 32389, + "port": 10017, + "protocol": "UDP", + "targetPort": 10017 + }, + { + "name": "rtp-10018", + "nodePort": 30345, + "port": 10018, + "protocol": "UDP", + "targetPort": 10018 + }, + { + "name": "rtp-10019", + "nodePort": 32459, + "port": 10019, + "protocol": "UDP", + "targetPort": 10019 + }, + { + "name": "rtp-10020", + "nodePort": 31689, + "port": 10020, + "protocol": "UDP", + "targetPort": 10020 + }, + { + "name": "rtp-10021", + "nodePort": 31020, + "port": 10021, + "protocol": "UDP", + "targetPort": 10021 + }, + { + "name": "rtp-10022", + "nodePort": 30901, + "port": 10022, + "protocol": "UDP", + "targetPort": 10022 + }, + { + "name": "rtp-10023", + "nodePort": 31490, + "port": 10023, + "protocol": "UDP", + "targetPort": 10023 + }, + { + "name": "rtp-10024", + "nodePort": 31629, + "port": 10024, + "protocol": "UDP", + "targetPort": 10024 + }, + { + "name": "rtp-10025", + "nodePort": 32374, + "port": 10025, + "protocol": "UDP", + "targetPort": 10025 + }, + { + "name": "rtp-10026", + "nodePort": 31209, + "port": 10026, + "protocol": "UDP", + "targetPort": 10026 + }, + { + "name": "rtp-10027", + "nodePort": 32521, + "port": 10027, + "protocol": "UDP", + "targetPort": 10027 + }, + { + "name": "rtp-10028", + "nodePort": 32265, + "port": 10028, + "protocol": "UDP", + "targetPort": 10028 + }, + { + "name": "rtp-10029", + "nodePort": 30871, + "port": 10029, + "protocol": "UDP", + "targetPort": 10029 + }, + { + "name": "rtp-10030", + "nodePort": 31116, + "port": 10030, + "protocol": "UDP", + "targetPort": 10030 + } + ], + "selector": { + "app": "asterisk" + }, + "sessionAffinity": "None", + "type": "LoadBalancer" + } +} diff --git a/apps-gx10/telephony/service-telephony-web.json b/apps-gx10/telephony/service-telephony-web.json new file mode 100644 index 0000000..c8466ef --- /dev/null +++ b/apps-gx10/telephony/service-telephony-web.json @@ -0,0 +1,25 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": {}, + "name": "telephony-web", + "namespace": "telephony" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 5100, + "protocol": "TCP", + "targetPort": 5100 + } + ], + "selector": { + "app": "telephony-web" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/telephony/service-yealink-provision.json b/apps-gx10/telephony/service-yealink-provision.json new file mode 100644 index 0000000..a76b480 --- /dev/null +++ b/apps-gx10/telephony/service-yealink-provision.json @@ -0,0 +1,27 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app": "yealink-provision" + }, + "name": "yealink-provision", + "namespace": "telephony" + }, + "spec": { + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 80 + } + ], + "selector": { + "app": "yealink-provision" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } +} diff --git a/apps-gx10/tts/deployment-gx10-tts.json b/apps-gx10/tts/deployment-gx10-tts.json new file mode 100644 index 0000000..cb80798 --- /dev/null +++ b/apps-gx10/tts/deployment-gx10-tts.json @@ -0,0 +1,106 @@ +{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "gx10-tts" + }, + "name": "gx10-tts", + "namespace": "tts" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "gx10-tts" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": "25%" + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "labels": { + "app": "gx10-tts" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "TTS_PORT", + "value": "8500" + }, + { + "name": "PIPER_VOICE", + "value": "en_US-amy-medium" + }, + { + "name": "TARGET_RATE", + "value": "16000" + } + ], + "image": "localhost/fc-gx10-tts:v20260614", + "imagePullPolicy": "Never", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 8500, + "scheme": "HTTP" + }, + "initialDelaySeconds": 10, + "periodSeconds": 20, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "name": "tts", + "ports": [ + { + "containerPort": 8500, + "name": "http", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 8500, + "scheme": "HTTP" + }, + "initialDelaySeconds": 3, + "periodSeconds": 5, + "successThreshold": 1, + "timeoutSeconds": 3 + }, + "resources": { + "limits": { + "cpu": "4", + "memory": "2Gi" + }, + "requests": { + "cpu": "500m", + "memory": "512Mi" + } + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + } + } + } +} diff --git a/apps-gx10/tts/service-gx10-tts.json b/apps-gx10/tts/service-gx10-tts.json new file mode 100644 index 0000000..099bc93 --- /dev/null +++ b/apps-gx10/tts/service-gx10-tts.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app": "gx10-tts" + }, + "name": "gx10-tts", + "namespace": "tts" + }, + "spec": { + "externalTrafficPolicy": "Cluster", + "internalTrafficPolicy": "Cluster", + "ports": [ + { + "name": "http", + "nodePort": 30850, + "port": 8500, + "protocol": "TCP", + "targetPort": 8500 + } + ], + "selector": { + "app": "gx10-tts" + }, + "sessionAffinity": "None", + "type": "NodePort" + } +}