apiVersion: v1 kind: Namespace metadata: name: trading labels: name: trading environment: production --- apiVersion: v1 kind: Secret metadata: name: ib-credentials namespace: trading type: Opaque stringData: # Rotate your creds (you pasted them earlier). username: "saladin85" password: "3Lcd@05041985" trading-mode: "paper" --- apiVersion: apps/v1 kind: Deployment metadata: name: ib-gateway namespace: trading labels: app: ib-gateway component: trading-infrastructure spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app: ib-gateway template: metadata: labels: app: ib-gateway annotations: prometheus.io/scrape: "false" spec: nodeSelector: kubernetes.io/hostname: hetzner-2 # Keep your original security context securityContext: runAsNonRoot: false fsGroup: 1000 containers: - name: ib-gateway image: ghcr.io/gnzsnz/ib-gateway:stable imagePullPolicy: IfNotPresent # IMPORTANT: use env vars this image expects env: - name: TWS_USERID valueFrom: secretKeyRef: name: ib-credentials key: username - name: TWS_PASSWORD valueFrom: secretKeyRef: name: ib-credentials key: password - name: TRADING_MODE valueFrom: secretKeyRef: name: ib-credentials key: trading-mode - name: READ_ONLY_API value: "no" # These two match what your log shows the image uses - name: API_PORT value: "4002" - name: SOCAT_PORT value: "4004" # optional but nice - name: TIME_ZONE value: "Etc/UTC" - name: TWOFA_TIMEOUT_ACTION value: "exit" ports: # IB API ports (inside container / localhost use) - name: api-paper containerPort: 4002 protocol: TCP - name: api-live containerPort: 4001 protocol: TCP # socat relay port for non-localhost clients (what we expose via Service) - name: api-socat containerPort: 4004 protocol: TCP # optional UI/VNC - name: vnc containerPort: 5900 protocol: TCP resources: requests: memory: "1Gi" cpu: "500m" limits: memory: "2Gi" cpu: "1000m" # Probe the socat port (represents remote connectivity) startupProbe: tcpSocket: port: 4004 initialDelaySeconds: 60 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 18 readinessProbe: tcpSocket: port: 4004 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 2 livenessProbe: tcpSocket: port: 4004 periodSeconds: 60 timeoutSeconds: 5 failureThreshold: 3 restartPolicy: Always dnsPolicy: ClusterFirst --- apiVersion: v1 kind: Service metadata: name: ib-gateway namespace: trading labels: app: ib-gateway spec: type: ClusterIP selector: app: ib-gateway ports: # Clients connect to 4002, but we forward to SOCAT_PORT=4004 - name: paper-trading port: 4002 targetPort: 4004 protocol: TCP # If you truly need live, you should relay live via another socat port too. # For now keep it direct (or remove it entirely for safety). - name: live-trading port: 4001 targetPort: 4001 protocol: TCP sessionAffinity: ClientIP sessionAffinityConfig: clientIP: timeoutSeconds: 3600