typhon: register app and add v2-safe ble/control runtime toggles

This commit is contained in:
Brad Stein 2026-04-13 22:02:57 -03:00
parent 6815a67c1f
commit e5a824e4e1
10 changed files with 337 additions and 0 deletions

View File

@ -25,6 +25,7 @@ resources:
- mailu/kustomization.yaml
- jenkins/kustomization.yaml
- ai-llm/kustomization.yaml
- typhon/kustomization.yaml
- nextcloud/kustomization.yaml
- nextcloud-mail-sync/kustomization.yaml
- outline/kustomization.yaml

View File

@ -0,0 +1,29 @@
# clusters/atlas/flux-system/applications/typhon/kustomization.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: typhon
namespace: flux-system
spec:
interval: 10m
path: ./services/typhon
prune: true
sourceRef:
kind: GitRepository
name: flux-system
targetNamespace: climate
dependsOn:
- name: vault
- name: vault-csi
- name: monitoring
healthChecks:
- apiVersion: apps/v1
kind: Deployment
name: typhon
namespace: climate
- apiVersion: v1
kind: Service
name: typhon
namespace: climate
wait: false
timeout: 20m

View File

@ -0,0 +1,155 @@
# services/typhon/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: typhon
namespace: climate
labels:
app: typhon
spec:
replicas: 1
revisionHistoryLimit: 3
selector:
matchLabels:
app: typhon
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 0
maxUnavailable: 1
template:
metadata:
labels:
app: typhon
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9108"
prometheus.io/path: "/metrics"
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "typhon"
vault.hashicorp.com/agent-inject-secret-aci-env.sh: "kv/data/atlas/climate/typhon/ac-infinity"
vault.hashicorp.com/agent-inject-template-aci-env.sh: |
{{- with secret "kv/data/atlas/climate/typhon/ac-infinity" -}}
{{- if index .Data.data "ACI_EMAIL" }}
export ACI_EMAIL="{{ index .Data.data "ACI_EMAIL" }}"
{{- end }}
{{- if index .Data.data "ACI_PASSWORD" }}
export ACI_PASSWORD="{{ index .Data.data "ACI_PASSWORD" }}"
{{- end }}
{{- if index .Data.data "ACI_HOST" }}
export ACI_HOST="{{ index .Data.data "ACI_HOST" }}"
{{- end }}
{{- if index .Data.data "TYPHON_MODE" }}
export TYPHON_MODE="{{ index .Data.data "TYPHON_MODE" }}"
{{- end }}
{{- if index .Data.data "ENABLE_CONTROL_API" }}
export ENABLE_CONTROL_API="{{ index .Data.data "ENABLE_CONTROL_API" }}"
{{- end }}
{{- if index .Data.data "TY_BLE_DEFAULT_MAC" }}
export TY_BLE_DEFAULT_MAC="{{ index .Data.data "TY_BLE_DEFAULT_MAC" }}"
{{- end }}
{{- if index .Data.data "TY_BLE_ALLOWED_MACS" }}
export TY_BLE_ALLOWED_MACS="{{ index .Data.data "TY_BLE_ALLOWED_MACS" }}"
{{- end }}
{{- if index .Data.data "TY_BLE_DEVICE_TYPE" }}
export TY_BLE_DEVICE_TYPE="{{ index .Data.data "TY_BLE_DEVICE_TYPE" }}"
{{- end }}
{{- if index .Data.data "TY_BLE_SCAN_TIMEOUT_MS" }}
export TY_BLE_SCAN_TIMEOUT_MS="{{ index .Data.data "TY_BLE_SCAN_TIMEOUT_MS" }}"
{{- end }}
{{- if index .Data.data "TY_BLE_PORT_BASE" }}
export TY_BLE_PORT_BASE="{{ index .Data.data "TY_BLE_PORT_BASE" }}"
{{- end }}
{{- end -}}
typhon.bstein.dev/restart-rev: "2"
spec:
serviceAccountName: typhon
imagePullSecrets:
- name: harbor-regcred
nodeSelector:
kubernetes.io/arch: amd64
kubernetes.io/hostname: titan-22
containers:
- name: typhon
image: registry.bstein.dev/bstein/typhon:main
imagePullPolicy: Always
command: ["/bin/sh", "-c"]
args:
- |
set -eu
if [ -f /vault/secrets/aci-env.sh ]; then
. /vault/secrets/aci-env.sh
fi
: "${TYPHON_MODE:=cloud}"
: "${ENABLE_CONTROL_API:=false}"
exec node dist/index.js
env:
- name: TYPHON_MODE
value: "cloud"
- name: ENABLE_CONTROL_API
value: "false"
- name: POLL_INTERVAL_SECONDS
value: "30"
- name: REQUEST_TIMEOUT_MS
value: "10000"
- name: LISTEN_PORT
value: "9108"
- name: CONTROL_LISTEN_PORT
value: "9110"
- name: TY_BLE_DEVICE_TYPE
value: "11"
- name: TY_BLE_SCAN_TIMEOUT_MS
value: "20000"
- name: TY_BLE_PORT_BASE
value: "1"
- name: LOG_LEVEL
value: "info"
ports:
- name: metrics
containerPort: 9108
- name: control
containerPort: 9110
volumeMounts:
- name: tmp
mountPath: /tmp
- name: dbus-socket
mountPath: /run/dbus/system_bus_socket
readOnly: true
livenessProbe:
httpGet:
path: /healthz
port: metrics
initialDelaySeconds: 20
periodSeconds: 20
timeoutSeconds: 3
failureThreshold: 3
readinessProbe:
httpGet:
path: /healthz
port: metrics
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
securityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
volumes:
- name: tmp
emptyDir: {}
- name: dbus-socket
hostPath:
path: /run/dbus/system_bus_socket
type: Socket

View File

@ -0,0 +1,12 @@
# services/typhon/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: climate
resources:
- namespace.yaml
- serviceaccount.yaml
- secretproviderclass.yaml
- vault-sync-deployment.yaml
- deployment.yaml
- service.yaml
- networkpolicy.yaml

View File

@ -0,0 +1,5 @@
# services/typhon/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: climate

View File

@ -0,0 +1,53 @@
# services/typhon/networkpolicy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: typhon
namespace: climate
spec:
podSelector:
matchLabels:
app: typhon
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring
ports:
- protocol: TCP
port: 9108
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: climate
ports:
- protocol: TCP
port: 9110
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: vault
ports:
- protocol: TCP
port: 8200
- to:
- ipBlock:
cidr: 0.0.0.0/0
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443

View File

@ -0,0 +1,21 @@
# services/typhon/secretproviderclass.yaml
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: typhon-vault
namespace: climate
spec:
provider: vault
parameters:
vaultAddress: "http://vault.vault.svc.cluster.local:8200"
roleName: "typhon"
objects: |
- objectName: "harbor-pull__dockerconfigjson"
secretPath: "kv/data/atlas/shared/harbor-pull"
secretKey: "dockerconfigjson"
secretObjects:
- secretName: harbor-regcred
type: kubernetes.io/dockerconfigjson
data:
- objectName: harbor-pull__dockerconfigjson
key: .dockerconfigjson

View File

@ -0,0 +1,21 @@
# services/typhon/service.yaml
apiVersion: v1
kind: Service
metadata:
name: typhon
namespace: climate
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9108"
prometheus.io/path: "/metrics"
spec:
type: ClusterIP
selector:
app: typhon
ports:
- name: metrics
port: 9108
targetPort: metrics
- name: control
port: 9110
targetPort: control

View File

@ -0,0 +1,6 @@
# services/typhon/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: typhon
namespace: climate

View File

@ -0,0 +1,34 @@
# services/typhon/vault-sync-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: typhon-vault-sync
namespace: climate
spec:
replicas: 1
selector:
matchLabels:
app: typhon-vault-sync
template:
metadata:
labels:
app: typhon-vault-sync
spec:
serviceAccountName: typhon
containers:
- name: sync
image: alpine:3.20
command: ["/bin/sh", "-c"]
args:
- "sleep infinity"
volumeMounts:
- name: vault-secrets
mountPath: /vault/secrets
readOnly: true
volumes:
- name: vault-secrets
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: typhon-vault