# rdev-api - Go REST API for controlling claudebox pods # v0.5 - API Server with Authentication apiVersion: apps/v1 kind: Deployment metadata: name: rdev-api namespace: rdev labels: app.kubernetes.io/name: rdev-api app.kubernetes.io/part-of: rdev spec: replicas: 1 selector: matchLabels: app: rdev-api template: metadata: labels: app: rdev-api app.kubernetes.io/name: rdev-api app.kubernetes.io/part-of: rdev spec: serviceAccountName: rdev-api containers: - name: rdev-api image: ghcr.io/orchard9/rdev-api:v0.10.45 imagePullPolicy: Always ports: - containerPort: 8080 name: http resources: requests: cpu: "100m" memory: "128Mi" limits: cpu: "500m" memory: "512Mi" securityContext: runAsNonRoot: true runAsUser: 1000 readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: ["ALL"] livenessProbe: httpGet: path: /health port: http initialDelaySeconds: 10 periodSeconds: 30 readinessProbe: httpGet: path: /ready port: http initialDelaySeconds: 5 periodSeconds: 10 env: - name: NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: PORT value: "8080" - name: DB_HOST value: "postgres.databases.svc.cluster.local" - name: DB_PORT value: "5432" - name: DB_USER value: "rdev" - name: DB_NAME value: "rdev" - name: DB_SSL_MODE value: "disable" - name: DB_PASSWORD valueFrom: secretKeyRef: name: rdev-credentials key: DB_PASSWORD - name: RDEV_ADMIN_KEY valueFrom: secretKeyRef: name: rdev-credentials key: RDEV_ADMIN_KEY - name: CREDENTIAL_ENCRYPTION_KEY valueFrom: secretKeyRef: name: rdev-credentials key: CREDENTIAL_ENCRYPTION_KEY # Infrastructure adapters for threesix.ai (fallback if not in DB) # Note: Using internal service hostnames to avoid hairpin NAT issues - name: GITEA_URL value: "http://gitea.threesix.svc.cluster.local" - name: GITEA_TOKEN valueFrom: secretKeyRef: name: rdev-credentials key: GITEA_TOKEN - name: CLOUDFLARE_API_TOKEN valueFrom: secretKeyRef: name: rdev-credentials key: CLOUDFLARE_API_TOKEN - name: CLOUDFLARE_ZONE_ID valueFrom: secretKeyRef: name: rdev-credentials key: CLOUDFLARE_ZONE_ID - name: WOODPECKER_WEBHOOK_SECRET valueFrom: secretKeyRef: name: rdev-credentials key: WOODPECKER_WEBHOOK_SECRET - name: WOODPECKER_URL value: "http://woodpecker-server.threesix.svc.cluster.local:8000" - name: WOODPECKER_API_TOKEN valueFrom: secretKeyRef: name: rdev-credentials key: WOODPECKER_API_TOKEN # CockroachDB for project database provisioning - name: CRDB_HOST value: "cockroachdb-public.databases.svc.cluster.local" - name: CRDB_PORT value: "26257" - name: CRDB_USER value: "root" - name: CRDB_SSL_MODE value: "disable" # Redis for project cache provisioning - name: REDIS_HOST value: "redis.databases.svc.cluster.local" - name: REDIS_PORT value: "6379" - name: REDIS_PASSWORD valueFrom: secretKeyRef: name: redis-credentials key: REDIS_PASSWORD # OpenTelemetry - name: OTEL_EXPORTER_OTLP_ENDPOINT value: "otel-collector.observability.svc.cluster.local:4317" imagePullSecrets: - name: ghcr-secret --- # Service for rdev-api apiVersion: v1 kind: Service metadata: name: rdev-api namespace: rdev labels: app.kubernetes.io/name: rdev-api app.kubernetes.io/part-of: rdev spec: type: ClusterIP selector: app: rdev-api ports: - port: 8080 targetPort: http name: http --- # ServiceAccount for rdev-api apiVersion: v1 kind: ServiceAccount metadata: name: rdev-api namespace: rdev --- # Role for rdev-api to exec into claudebox pods and read configmaps apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: rdev-api namespace: rdev rules: # Pod access for discovery and status - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"] # Pod exec for command execution - apiGroups: [""] resources: ["pods/exec"] verbs: ["create"] # ConfigMap access for project configuration - apiGroups: [""] resources: ["configmaps"] verbs: ["get", "list", "watch"] --- # RoleBinding for rdev-api apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: rdev-api namespace: rdev subjects: - kind: ServiceAccount name: rdev-api namespace: rdev roleRef: kind: Role name: rdev-api apiGroup: rbac.authorization.k8s.io --- # ClusterRole for rdev-api to deploy projects across namespaces apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: rdev-api-deployer rules: # Deployment management - apiGroups: ["apps"] resources: ["deployments"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # Service management - apiGroups: [""] resources: ["services"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # Ingress management - apiGroups: ["networking.k8s.io"] resources: ["ingresses"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # Namespace verification (check exists before creating) - apiGroups: [""] resources: ["namespaces"] verbs: ["get", "create"] # Pod logs for deployment status - apiGroups: [""] resources: ["pods", "pods/log"] verbs: ["get", "list", "watch"] # Secrets for env vars and TLS certificates - apiGroups: [""] resources: ["secrets"] verbs: ["get", "list", "create", "update", "patch"] --- # ClusterRoleBinding for rdev-api deployer apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: rdev-api-deployer subjects: - kind: ServiceAccount name: rdev-api namespace: rdev roleRef: kind: ClusterRole name: rdev-api-deployer apiGroup: rbac.authorization.k8s.io --- # Ingress for rdev-api apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: rdev-api namespace: rdev annotations: cert-manager.io/cluster-issuer: letsencrypt-prod traefik.ingress.kubernetes.io/router.entrypoints: websecure traefik.ingress.kubernetes.io/router.tls: "true" spec: ingressClassName: traefik rules: - host: rdev.masq-ops.orchard9.ai http: paths: - backend: service: name: rdev-api port: number: 8080 path: / pathType: Prefix tls: - hosts: - rdev.masq-ops.orchard9.ai secretName: rdev-api-tls