Files
pikasTech-unidesk/src/components/microservices/k3sctl-adapter/k3s/code-queue.k8s.yaml
T

1232 lines
43 KiB
YAML

apiVersion: v1
kind: Namespace
metadata:
name: unidesk
labels:
app.kubernetes.io/part-of: unidesk
unidesk.ai/k3s-cluster: unidesk-k3s
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: code-queue-read
namespace: unidesk
labels:
app.kubernetes.io/name: code-queue
app.kubernetes.io/component: read
app.kubernetes.io/part-of: unidesk
unidesk.ai/deployment-mode: k3sctl-managed
unidesk.ai/instance-id: D601-read
spec:
replicas: 2
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app.kubernetes.io/name: code-queue
app.kubernetes.io/component: read
unidesk.ai/instance-id: D601-read
template:
metadata:
labels:
app.kubernetes.io/name: code-queue
app.kubernetes.io/component: read
app.kubernetes.io/part-of: unidesk
unidesk.ai/deployment-mode: k3sctl-managed
unidesk.ai/instance-id: D601-read
unidesk.ai/node-id: D601
spec:
nodeSelector:
unidesk.ai/node-id: D601
terminationGracePeriodSeconds: 30
containers:
- name: code-queue
image: unidesk-code-queue:d601
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 4222
envFrom:
- secretRef:
name: code-queue-env
optional: true
env:
- name: HOST
value: "0.0.0.0"
- name: PORT
value: "4222"
- name: DATABASE_URL
value: "postgres://unidesk:unidesk_dev_password@d601-tcp-egress-gateway.unidesk.svc.cluster.local:15432/unidesk"
- name: CODE_QUEUE_INSTANCE_ID
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: CODE_QUEUE_SERVICE_ROLE
value: "read"
- name: CODE_QUEUE_SCHEDULER_ENABLED
value: "false"
- name: CODE_QUEUE_STARTUP_OA_BACKFILL_ENABLED
value: "false"
- name: CODE_QUEUE_DATA_DIR
value: "/var/lib/unidesk/code-queue"
- name: CODE_QUEUE_WORKDIR
value: "/workspace"
- name: CODE_QUEUE_CODEX_HOME
value: "/var/lib/unidesk/code-queue/codex-home"
- name: CODE_QUEUE_OPENCODE_XDG_DIR
value: "/var/lib/unidesk/code-queue/opencode-xdg"
- name: CODE_QUEUE_SOURCE_CODEX_CONFIG
value: "/root/.codex/config.toml"
- name: UNIDESK_SKILLS_PATH
value: "/root/.agents/skills"
- name: CODE_QUEUE_RUNNER_SKILLS_SOURCE_PATH
value: "/home/ubuntu/.agents/skills"
- name: CODE_QUEUE_DEFAULT_MODEL
value: "gpt-5.5"
- name: CODE_QUEUE_MODELS
value: "gpt-5.5,gpt-5.4-mini,gpt-5.4,deepseek-chat,minimax-m2.7"
- name: CODE_QUEUE_MODEL_REASONING_EFFORTS
value: "gpt-5.5=xhigh"
- name: CODE_QUEUE_SANDBOX
value: "danger-full-access"
- name: CODE_QUEUE_APPROVAL_POLICY
value: "never"
- name: CODE_QUEUE_MAX_ACTIVE_QUEUES
value: "0"
- name: CODE_QUEUE_DATABASE_POOL_MAX
value: "2"
- name: NODE_OPTIONS
value: "--max-old-space-size=512"
- name: GIT_CONFIG_COUNT
value: "1"
- name: GIT_CONFIG_KEY_0
value: "safe.directory"
- name: GIT_CONFIG_VALUE_0
value: "*"
- name: CODE_QUEUE_IN_MEMORY_OUTPUT_RECORDS
value: "10"
- name: CODE_QUEUE_IN_MEMORY_EVENT_RECORDS
value: "10"
- name: CODE_QUEUE_MAIN_PROVIDER_ID
value: "D601"
- name: CODE_QUEUE_REMOTE_WORKDIR
value: "/home/ubuntu"
- name: CODE_QUEUE_EXECUTION_PROVIDER_IDS
value: "D601"
- name: CODE_QUEUE_DEV_CONTAINER_MASTER_HOST
value: "74.48.78.17"
- name: CODE_QUEUE_DEV_CONTAINER_DEFAULT_PROVIDER_ID
value: "D601"
- name: CODE_QUEUE_DEV_CONTAINER_WORKDIR
value: "/home/ubuntu"
- name: CODE_QUEUE_EGRESS_PROXY_ENABLED
value: "false"
- name: CODE_QUEUE_EGRESS_PROXY_URL
value: ""
- name: CODE_QUEUE_EGRESS_PROXY_NO_PROXY
value: "localhost,127.0.0.1,::1,host.docker.internal,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,backend-core,oa-event-flow,database"
- name: HTTP_PROXY
value: ""
- name: HTTPS_PROXY
value: ""
- name: ALL_PROXY
value: ""
- name: http_proxy
value: ""
- name: https_proxy
value: ""
- name: all_proxy
value: ""
- name: NO_PROXY
value: "localhost,127.0.0.1,::1,host.docker.internal,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,backend-core,oa-event-flow,database"
- name: no_proxy
value: "localhost,127.0.0.1,::1,host.docker.internal,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,backend-core,oa-event-flow,database"
- name: OA_EVENT_FLOW_BASE_URL
value: "http://d601-tcp-egress-gateway.unidesk.svc.cluster.local:4255"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED
value: "false"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL
value: ""
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE
value: "private"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_USER_ID
value: "645275593"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_MAX_RESPONSE_CHARS
value: "12000"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_TIMEOUT_MS
value: "15000"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_SEND_ATTEMPTS
value: "3"
- name: LOG_FILE
value: "/var/log/unidesk/code-queue-read.jsonl"
- name: UNIDESK_LOG_RETENTION_BYTES
value: "1GiB"
volumeMounts:
- name: docker-sock
mountPath: /var/run/docker.sock
- name: workspace
mountPath: /workspace
- name: workspace
mountPath: /home/ubuntu
- name: repo
mountPath: /root/unidesk
- name: repo
mountPath: /app
- name: codex-config
mountPath: /root/.codex/config.toml
readOnly: true
- name: codex-auth
mountPath: /root/.codex/auth.json
readOnly: true
- name: skills-dir
mountPath: /root/.agents/skills
readOnly: true
- name: ssh-dir
mountPath: /root/.ssh
readOnly: true
- name: logs
mountPath: /var/log/unidesk
- name: state
mountPath: /var/lib/unidesk/code-queue
readinessProbe:
httpGet:
path: /live
port: http
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 20
livenessProbe:
httpGet:
path: /live
port: http
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 6
startupProbe:
httpGet:
path: /live
port: http
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 60
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 1Gi
volumes:
- name: docker-sock
hostPath:
path: /var/run/docker.sock
type: Socket
- name: workspace
hostPath:
path: /home/ubuntu
type: Directory
- name: repo
hostPath:
path: /home/ubuntu/cq-deploy
type: Directory
- name: codex-config
hostPath:
path: /home/ubuntu/.codex/config.toml
type: File
- name: codex-auth
hostPath:
path: /home/ubuntu/.codex/auth.json
type: File
- name: skills-dir
hostPath:
path: /home/ubuntu/.agents/skills
type: Directory
- name: ssh-dir
hostPath:
path: /home/ubuntu/.ssh
type: Directory
- name: logs
hostPath:
path: /home/ubuntu/cq-deploy/.state/code-queue/logs
type: DirectoryOrCreate
- name: state
hostPath:
path: /home/ubuntu/cq-deploy/.state/code-queue
type: DirectoryOrCreate
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: code-queue-write
namespace: unidesk
labels:
app.kubernetes.io/name: code-queue
app.kubernetes.io/component: write
app.kubernetes.io/part-of: unidesk
unidesk.ai/deployment-mode: k3sctl-managed
unidesk.ai/instance-id: D601-write
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app.kubernetes.io/name: code-queue
app.kubernetes.io/component: write
unidesk.ai/instance-id: D601-write
template:
metadata:
labels:
app.kubernetes.io/name: code-queue
app.kubernetes.io/component: write
app.kubernetes.io/part-of: unidesk
unidesk.ai/deployment-mode: k3sctl-managed
unidesk.ai/instance-id: D601-write
unidesk.ai/node-id: D601
spec:
nodeSelector:
unidesk.ai/node-id: D601
terminationGracePeriodSeconds: 30
containers:
- name: code-queue
image: unidesk-code-queue:d601
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 4222
envFrom:
- secretRef:
name: code-queue-env
optional: true
env:
- name: HOST
value: "0.0.0.0"
- name: PORT
value: "4222"
- name: DATABASE_URL
value: "postgres://unidesk:unidesk_dev_password@d601-tcp-egress-gateway.unidesk.svc.cluster.local:15432/unidesk"
- name: CODE_QUEUE_INSTANCE_ID
value: "D601-write"
- name: CODE_QUEUE_SERVICE_ROLE
value: "write"
- name: CODE_QUEUE_SCHEDULER_ENABLED
value: "false"
- name: CODE_QUEUE_STARTUP_OA_BACKFILL_ENABLED
value: "false"
- name: CODE_QUEUE_DATA_DIR
value: "/var/lib/unidesk/code-queue"
- name: CODE_QUEUE_WORKDIR
value: "/workspace"
- name: CODE_QUEUE_CODEX_HOME
value: "/var/lib/unidesk/code-queue/codex-home"
- name: CODE_QUEUE_OPENCODE_XDG_DIR
value: "/var/lib/unidesk/code-queue/opencode-xdg"
- name: CODE_QUEUE_SOURCE_CODEX_CONFIG
value: "/root/.codex/config.toml"
- name: UNIDESK_SKILLS_PATH
value: "/root/.agents/skills"
- name: CODE_QUEUE_RUNNER_SKILLS_SOURCE_PATH
value: "/home/ubuntu/.agents/skills"
- name: CODE_QUEUE_DEFAULT_MODEL
value: "gpt-5.5"
- name: CODE_QUEUE_MODELS
value: "gpt-5.5,gpt-5.4-mini,gpt-5.4,deepseek-chat,minimax-m2.7"
- name: CODE_QUEUE_MODEL_REASONING_EFFORTS
value: "gpt-5.5=xhigh"
- name: CODE_QUEUE_SANDBOX
value: "danger-full-access"
- name: CODE_QUEUE_APPROVAL_POLICY
value: "never"
- name: CODE_QUEUE_MAX_ACTIVE_QUEUES
value: "0"
- name: CODE_QUEUE_DATABASE_POOL_MAX
value: "2"
- name: NODE_OPTIONS
value: "--max-old-space-size=768"
- name: GIT_CONFIG_COUNT
value: "1"
- name: GIT_CONFIG_KEY_0
value: "safe.directory"
- name: GIT_CONFIG_VALUE_0
value: "*"
- name: CODE_QUEUE_IN_MEMORY_OUTPUT_RECORDS
value: "10"
- name: CODE_QUEUE_IN_MEMORY_EVENT_RECORDS
value: "10"
- name: CODE_QUEUE_MAIN_PROVIDER_ID
value: "D601"
- name: CODE_QUEUE_REMOTE_WORKDIR
value: "/home/ubuntu"
- name: CODE_QUEUE_EXECUTION_PROVIDER_IDS
value: "D601"
- name: CODE_QUEUE_DEV_CONTAINER_MASTER_HOST
value: "74.48.78.17"
- name: CODE_QUEUE_DEV_CONTAINER_DEFAULT_PROVIDER_ID
value: "D601"
- name: CODE_QUEUE_DEV_CONTAINER_WORKDIR
value: "/home/ubuntu"
- name: CODE_QUEUE_EGRESS_PROXY_ENABLED
value: "false"
- name: CODE_QUEUE_EGRESS_PROXY_URL
value: ""
- name: CODE_QUEUE_EGRESS_PROXY_NO_PROXY
value: "localhost,127.0.0.1,::1,host.docker.internal,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,backend-core,oa-event-flow,database"
- name: HTTP_PROXY
value: ""
- name: HTTPS_PROXY
value: ""
- name: ALL_PROXY
value: ""
- name: http_proxy
value: ""
- name: https_proxy
value: ""
- name: all_proxy
value: ""
- name: NO_PROXY
value: "localhost,127.0.0.1,::1,host.docker.internal,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,backend-core,oa-event-flow,database"
- name: no_proxy
value: "localhost,127.0.0.1,::1,host.docker.internal,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,backend-core,oa-event-flow,database"
- name: OA_EVENT_FLOW_BASE_URL
value: "http://d601-tcp-egress-gateway.unidesk.svc.cluster.local:4255"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED
value: "false"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL
value: ""
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE
value: "private"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_USER_ID
value: "645275593"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_MAX_RESPONSE_CHARS
value: "12000"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_TIMEOUT_MS
value: "15000"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_SEND_ATTEMPTS
value: "3"
- name: LOG_FILE
value: "/var/log/unidesk/code-queue-write.jsonl"
- name: UNIDESK_LOG_RETENTION_BYTES
value: "1GiB"
volumeMounts:
- name: docker-sock
mountPath: /var/run/docker.sock
- name: workspace
mountPath: /workspace
- name: workspace
mountPath: /home/ubuntu
- name: repo
mountPath: /root/unidesk
- name: repo
mountPath: /app
- name: codex-config
mountPath: /root/.codex/config.toml
readOnly: true
- name: codex-auth
mountPath: /root/.codex/auth.json
readOnly: true
- name: skills-dir
mountPath: /root/.agents/skills
readOnly: true
- name: ssh-dir
mountPath: /root/.ssh
readOnly: true
- name: logs
mountPath: /var/log/unidesk
- name: state
mountPath: /var/lib/unidesk/code-queue
readinessProbe:
httpGet:
path: /live
port: http
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 20
livenessProbe:
httpGet:
path: /live
port: http
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 6
startupProbe:
httpGet:
path: /live
port: http
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 60
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 1Gi
volumes:
- name: docker-sock
hostPath:
path: /var/run/docker.sock
type: Socket
- name: workspace
hostPath:
path: /home/ubuntu
type: Directory
- name: repo
hostPath:
path: /home/ubuntu/cq-deploy
type: Directory
- name: codex-config
hostPath:
path: /home/ubuntu/.codex/config.toml
type: File
- name: codex-auth
hostPath:
path: /home/ubuntu/.codex/auth.json
type: File
- name: skills-dir
hostPath:
path: /home/ubuntu/.agents/skills
type: Directory
- name: ssh-dir
hostPath:
path: /home/ubuntu/.ssh
type: Directory
- name: logs
hostPath:
path: /home/ubuntu/cq-deploy/.state/code-queue/logs
type: DirectoryOrCreate
- name: state
hostPath:
path: /home/ubuntu/cq-deploy/.state/code-queue
type: DirectoryOrCreate
---
apiVersion: v1
kind: Service
metadata:
name: code-queue-scheduler
namespace: unidesk
labels:
app.kubernetes.io/name: code-queue
app.kubernetes.io/component: scheduler
app.kubernetes.io/part-of: unidesk
unidesk.ai/deployment-mode: k3sctl-managed
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: code-queue
unidesk.ai/instance-id: D601
ports:
- name: http
port: 4222
targetPort: http
---
apiVersion: v1
kind: Service
metadata:
name: code-queue-read
namespace: unidesk
labels:
app.kubernetes.io/name: code-queue
app.kubernetes.io/component: read
app.kubernetes.io/part-of: unidesk
unidesk.ai/deployment-mode: k3sctl-managed
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: code-queue
app.kubernetes.io/component: read
unidesk.ai/instance-id: D601-read
ports:
- name: http
port: 4222
targetPort: http
---
apiVersion: v1
kind: Service
metadata:
name: code-queue-write
namespace: unidesk
labels:
app.kubernetes.io/name: code-queue
app.kubernetes.io/component: write
app.kubernetes.io/part-of: unidesk
unidesk.ai/deployment-mode: k3sctl-managed
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: code-queue
app.kubernetes.io/component: write
unidesk.ai/instance-id: D601-write
ports:
- name: http
port: 4222
targetPort: http
---
apiVersion: v1
kind: Service
metadata:
name: d601-provider-egress-proxy
namespace: unidesk
labels:
app.kubernetes.io/name: provider-egress-proxy
app.kubernetes.io/part-of: unidesk
unidesk.ai/provider-id: D601
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: provider-egress-proxy
unidesk.ai/provider-id: D601
ports:
- name: http
port: 18789
targetPort: http
protocol: TCP
---
apiVersion: v1
kind: ConfigMap
metadata:
name: d601-provider-egress-proxy
namespace: unidesk
labels:
app.kubernetes.io/name: provider-egress-proxy
app.kubernetes.io/part-of: unidesk
unidesk.ai/provider-id: D601
data:
provider-egress-proxy.js: |
const net = require("node:net");
const listenPort = Number(process.env.PROVIDER_EGRESS_LISTEN_PORT || 18790);
const upstreamHost = process.env.PROVIDER_EGRESS_UPSTREAM_HOST || "127.0.0.1";
const upstreamPort = Number(process.env.PROVIDER_EGRESS_UPSTREAM_PORT || 18789);
function closeBoth(left, right) {
left.destroy();
right.destroy();
}
net.createServer((client) => {
const upstream = net.connect({ host: upstreamHost, port: upstreamPort });
client.pipe(upstream);
upstream.pipe(client);
client.on("error", () => closeBoth(client, upstream));
upstream.on("error", () => closeBoth(client, upstream));
}).listen(listenPort, "0.0.0.0", () => {
console.log(JSON.stringify({
ts: new Date().toISOString(),
service: "provider-egress-proxy",
level: "info",
message: "listening",
data: { listenPort, upstream: `${upstreamHost}:${upstreamPort}` },
}));
});
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: d601-provider-egress-proxy
namespace: unidesk
labels:
app.kubernetes.io/name: provider-egress-proxy
app.kubernetes.io/part-of: unidesk
unidesk.ai/provider-id: D601
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/name: provider-egress-proxy
unidesk.ai/provider-id: D601
template:
metadata:
labels:
app.kubernetes.io/name: provider-egress-proxy
app.kubernetes.io/part-of: unidesk
unidesk.ai/provider-id: D601
unidesk.ai/node-id: D601
spec:
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
nodeSelector:
unidesk.ai/node-id: D601
containers:
- name: provider-egress-proxy
image: unidesk-code-queue:d601
imagePullPolicy: IfNotPresent
command:
- bun
- /etc/unidesk-provider-egress/provider-egress-proxy.js
ports:
- name: http
containerPort: 18790
env:
- name: PROVIDER_EGRESS_LISTEN_PORT
value: "18790"
- name: PROVIDER_EGRESS_UPSTREAM_HOST
value: "127.0.0.1"
- name: PROVIDER_EGRESS_UPSTREAM_PORT
value: "18789"
volumeMounts:
- name: script
mountPath: /etc/unidesk-provider-egress
readOnly: true
readinessProbe:
tcpSocket:
port: http
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 12
livenessProbe:
tcpSocket:
port: http
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 6
volumes:
- name: script
configMap:
name: d601-provider-egress-proxy
---
apiVersion: v1
kind: ConfigMap
metadata:
name: d601-tcp-egress-gateway
namespace: unidesk
labels:
app.kubernetes.io/name: tcp-egress-gateway
app.kubernetes.io/part-of: unidesk
unidesk.ai/provider-id: D601
data:
tcp-egress-gateway.js: |
const net = require("node:net");
const proxyUrl = new URL(process.env.TCP_EGRESS_HTTP_PROXY || "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789");
const proxyHost = proxyUrl.hostname;
const proxyPort = Number(proxyUrl.port || 80);
const healthPort = Number(process.env.TCP_EGRESS_HEALTH_PORT || 18080);
const rawRoutes = process.env.TCP_EGRESS_ROUTES || "";
const startedAt = new Date().toISOString();
function positiveInt(value, fallback) {
const parsed = Number(value);
return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
}
const connectAttempts = positiveInt(process.env.TCP_EGRESS_CONNECT_ATTEMPTS, 8);
const connectRetryBackoffMs = positiveInt(process.env.TCP_EGRESS_CONNECT_RETRY_BACKOFF_MS, 250);
const maxEarlyClientBytes = positiveInt(process.env.TCP_EGRESS_MAX_EARLY_CLIENT_BYTES, 1024 * 1024);
function parseRoute(text) {
const parts = text.trim().split("=");
if (parts.length !== 3) throw new Error(`invalid route: ${text}`);
const [name, listenPortText, target] = parts;
const [targetHost, targetPortText] = target.split(":");
const listenPort = Number(listenPortText);
const targetPort = Number(targetPortText);
if (!name || !targetHost || !Number.isInteger(listenPort) || !Number.isInteger(targetPort)) throw new Error(`invalid route: ${text}`);
return { name, listenPort, targetHost, targetPort };
}
const routes = rawRoutes.split(",").map((item) => item.trim()).filter(Boolean).map(parseRoute);
if (routes.length === 0) throw new Error("TCP_EGRESS_ROUTES must define at least one route");
function findHeaderEnd(buffer) {
for (let index = 0; index <= buffer.length - 4; index += 1) {
if (buffer[index] === 13 && buffer[index + 1] === 10 && buffer[index + 2] === 13 && buffer[index + 3] === 10) return index + 4;
}
return -1;
}
function log(level, message, data = {}) {
console.log(JSON.stringify({ ts: new Date().toISOString(), service: "tcp-egress-gateway", level, message, data }));
}
function pipeViaHttpConnect(client, route) {
const earlyClientChunks = [];
let earlyClientBytes = 0;
let proxy = null;
let tunnelReady = false;
let closed = false;
let attempt = 0;
let retryTimer = null;
const cleanupProxy = () => {
if (proxy === null) return;
proxy.removeAllListeners();
proxy.destroy();
proxy = null;
};
const closeBoth = () => {
if (closed) return;
closed = true;
if (retryTimer !== null) clearTimeout(retryTimer);
client.destroy();
cleanupProxy();
};
const retryOrClose = (reason, data = {}) => {
cleanupProxy();
if (!closed && attempt < connectAttempts) {
const delayMs = Math.min(connectRetryBackoffMs * attempt, 3000);
log("warn", "connect_retry", { route: route.name, attempt, attempts: connectAttempts, delayMs, reason, ...data });
retryTimer = setTimeout(() => {
retryTimer = null;
startProxy();
}, delayMs);
retryTimer.unref?.();
return;
}
log("warn", "connect_rejected", { route: route.name, attempt, attempts: connectAttempts, reason, ...data });
closeBoth();
};
client.on("data", (chunk) => {
if (tunnelReady && proxy !== null) {
proxy.write(chunk);
return;
}
earlyClientBytes += chunk.length;
if (earlyClientBytes > maxEarlyClientBytes) {
log("warn", "early_client_buffer_limit_exceeded", { route: route.name, bytes: earlyClientBytes, limit: maxEarlyClientBytes });
closeBoth();
return;
}
earlyClientChunks.push(chunk);
});
client.on("error", closeBoth);
client.on("close", closeBoth);
const startProxy = () => {
if (closed) return;
attempt += 1;
tunnelReady = false;
const currentProxy = net.connect({ host: proxyHost, port: proxyPort });
const proxyHeaderChunks = [];
proxy = currentProxy;
currentProxy.on("connect", () => {
currentProxy.write(`CONNECT ${route.targetHost}:${route.targetPort} HTTP/1.1\r\nHost: ${route.targetHost}:${route.targetPort}\r\n\r\n`);
});
currentProxy.on("data", (chunk) => {
if (currentProxy !== proxy) return;
if (tunnelReady) {
client.write(chunk);
return;
}
proxyHeaderChunks.push(chunk);
const headerBuffer = Buffer.concat(proxyHeaderChunks);
const headerEnd = findHeaderEnd(headerBuffer);
if (headerEnd < 0) return;
const header = headerBuffer.subarray(0, headerEnd).toString("latin1");
if (!/^HTTP\/1\.[01] 200\b/u.test(header)) {
const body = headerBuffer.subarray(headerEnd).toString("utf8").slice(0, 300);
retryOrClose("non_200", { header: header.slice(0, 200), body: body.length > 0 ? body : null });
return;
}
tunnelReady = true;
const remaining = headerBuffer.subarray(headerEnd);
if (remaining.length > 0) client.write(remaining);
for (const early of earlyClientChunks) currentProxy.write(early);
earlyClientChunks.length = 0;
earlyClientBytes = 0;
});
currentProxy.on("error", (error) => {
if (currentProxy !== proxy) return;
retryOrClose("proxy_error", { error: String(error?.message || error) });
});
currentProxy.on("close", () => {
if (currentProxy !== proxy || closed) return;
if (!tunnelReady) {
retryOrClose("proxy_closed_before_tunnel");
return;
}
closeBoth();
});
};
startProxy();
}
for (const route of routes) {
net.createServer((client) => pipeViaHttpConnect(client, route)).listen(route.listenPort, "0.0.0.0", () => {
log("info", "route_listening", { route: route.name, listenPort: route.listenPort, target: `${route.targetHost}:${route.targetPort}`, proxy: `${proxyHost}:${proxyPort}` });
});
}
Bun.serve({
hostname: "0.0.0.0",
port: healthPort,
fetch() {
return Response.json({ ok: true, service: "tcp-egress-gateway", startedAt, proxy: `${proxyHost}:${proxyPort}`, routes, connectAttempts, connectRetryBackoffMs });
},
});
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: d601-tcp-egress-gateway
namespace: unidesk
labels:
app.kubernetes.io/name: tcp-egress-gateway
app.kubernetes.io/part-of: unidesk
unidesk.ai/provider-id: D601
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: tcp-egress-gateway
unidesk.ai/provider-id: D601
template:
metadata:
labels:
app.kubernetes.io/name: tcp-egress-gateway
app.kubernetes.io/part-of: unidesk
unidesk.ai/provider-id: D601
unidesk.ai/node-id: D601
spec:
nodeSelector:
unidesk.ai/node-id: D601
containers:
- name: tcp-egress-gateway
image: unidesk-code-queue:d601
imagePullPolicy: IfNotPresent
command:
- bun
- /etc/unidesk-tcp-egress/tcp-egress-gateway.js
ports:
- name: pg
containerPort: 15432
- name: oa
containerPort: 4255
- name: health
containerPort: 18080
env:
- name: TCP_EGRESS_HTTP_PROXY
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: TCP_EGRESS_ROUTES
value: "postgres=15432=74.48.78.17:15432,oa-event-flow=4255=74.48.78.17:4255"
- name: TCP_EGRESS_HEALTH_PORT
value: "18080"
- name: TCP_EGRESS_CONNECT_ATTEMPTS
value: "8"
- name: TCP_EGRESS_CONNECT_RETRY_BACKOFF_MS
value: "250"
volumeMounts:
- name: script
mountPath: /etc/unidesk-tcp-egress
readOnly: true
readinessProbe:
httpGet:
path: /health
port: health
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 12
livenessProbe:
httpGet:
path: /health
port: health
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 6
volumes:
- name: script
configMap:
name: d601-tcp-egress-gateway
---
apiVersion: v1
kind: Service
metadata:
name: d601-tcp-egress-gateway
namespace: unidesk
labels:
app.kubernetes.io/name: tcp-egress-gateway
app.kubernetes.io/part-of: unidesk
unidesk.ai/provider-id: D601
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: tcp-egress-gateway
unidesk.ai/provider-id: D601
ports:
- name: pg
port: 15432
targetPort: pg
- name: oa
port: 4255
targetPort: oa
- name: health
port: 18080
targetPort: health
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: code-queue
namespace: unidesk
labels:
app.kubernetes.io/name: code-queue
app.kubernetes.io/part-of: unidesk
unidesk.ai/deployment-mode: k3sctl-managed
unidesk.ai/instance-id: D601
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app.kubernetes.io/name: code-queue
unidesk.ai/instance-id: D601
template:
metadata:
labels:
app.kubernetes.io/name: code-queue
app.kubernetes.io/part-of: unidesk
unidesk.ai/deployment-mode: k3sctl-managed
unidesk.ai/instance-id: D601
unidesk.ai/node-id: D601
spec:
nodeSelector:
unidesk.ai/node-id: D601
terminationGracePeriodSeconds: 30
containers:
- name: code-queue
image: unidesk-code-queue:d601
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 4222
envFrom:
- secretRef:
name: code-queue-env
optional: true
env:
- name: HOST
value: "0.0.0.0"
- name: PORT
value: "4222"
- name: DATABASE_URL
value: "postgres://unidesk:unidesk_dev_password@d601-tcp-egress-gateway.unidesk.svc.cluster.local:15432/unidesk"
- name: CODE_QUEUE_INSTANCE_ID
value: "D601"
- name: CODE_QUEUE_SERVICE_ROLE
value: "scheduler"
- name: CODE_QUEUE_SCHEDULER_ENABLED
value: "true"
- name: CODE_QUEUE_SCHEDULER_POLL_INTERVAL_MS
value: "2000"
- name: CODE_QUEUE_STARTUP_OA_BACKFILL_ENABLED
value: "false"
- name: CODE_QUEUE_DATA_DIR
value: "/var/lib/unidesk/code-queue"
- name: CODE_QUEUE_WORKDIR
value: "/workspace"
- name: CODE_QUEUE_CODEX_HOME
value: "/var/lib/unidesk/code-queue/codex-home"
- name: CODE_QUEUE_OPENCODE_XDG_DIR
value: "/var/lib/unidesk/code-queue/opencode-xdg"
- name: CODE_QUEUE_SOURCE_CODEX_CONFIG
value: "/root/.codex/config.toml"
- name: UNIDESK_SKILLS_PATH
value: "/root/.agents/skills"
- name: CODE_QUEUE_RUNNER_SKILLS_SOURCE_PATH
value: "/home/ubuntu/.agents/skills"
- name: CODE_QUEUE_DEFAULT_MODEL
value: "gpt-5.5"
- name: CODE_QUEUE_MODELS
value: "gpt-5.5,gpt-5.4-mini,gpt-5.4,deepseek-chat,minimax-m2.7"
- name: CODE_QUEUE_MODEL_REASONING_EFFORTS
value: "gpt-5.5=xhigh"
- name: CODE_QUEUE_SANDBOX
value: "danger-full-access"
- name: CODE_QUEUE_APPROVAL_POLICY
value: "never"
- name: CODE_QUEUE_MAX_ACTIVE_QUEUES
value: "0"
- name: CODE_QUEUE_DATABASE_POOL_MAX
value: "2"
- name: NODE_OPTIONS
value: "--max-old-space-size=1024"
- name: GIT_CONFIG_COUNT
value: "1"
- name: GIT_CONFIG_KEY_0
value: "safe.directory"
- name: GIT_CONFIG_VALUE_0
value: "*"
- name: CODE_QUEUE_IN_MEMORY_OUTPUT_RECORDS
value: "10"
- name: CODE_QUEUE_IN_MEMORY_EVENT_RECORDS
value: "10"
- name: CODE_QUEUE_MAIN_PROVIDER_ID
value: "D601"
- name: CODE_QUEUE_REMOTE_WORKDIR
value: "/home/ubuntu"
- name: CODE_QUEUE_EXECUTION_PROVIDER_IDS
value: "D601"
- name: CODE_QUEUE_DEV_CONTAINER_MASTER_HOST
value: "74.48.78.17"
- name: CODE_QUEUE_DEV_CONTAINER_DEFAULT_PROVIDER_ID
value: "D601"
- name: CODE_QUEUE_DEV_CONTAINER_WORKDIR
value: "/home/ubuntu"
- name: CODE_QUEUE_EGRESS_PROXY_ENABLED
value: "true"
- name: CODE_QUEUE_EGRESS_PROXY_URL
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: CODE_QUEUE_EGRESS_PROXY_NO_PROXY
value: "localhost,127.0.0.1,::1,host.docker.internal,claudeqq,claudeqq.unidesk,claudeqq.unidesk.svc,claudeqq.unidesk.svc.cluster.local,d601-provider-egress-proxy,d601-provider-egress-proxy.unidesk,d601-provider-egress-proxy.unidesk.svc,d601-provider-egress-proxy.unidesk.svc.cluster.local,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,172.25.0.3,unidesk-provider-gateway-D601,backend-core,oa-event-flow,database,hyueapi.com,.hyueapi.com,api.minimaxi.com,.minimaxi.com"
- name: HTTP_PROXY
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: HTTPS_PROXY
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: ALL_PROXY
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: http_proxy
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: https_proxy
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: all_proxy
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: NO_PROXY
value: "localhost,127.0.0.1,::1,host.docker.internal,claudeqq,claudeqq.unidesk,claudeqq.unidesk.svc,claudeqq.unidesk.svc.cluster.local,d601-provider-egress-proxy,d601-provider-egress-proxy.unidesk,d601-provider-egress-proxy.unidesk.svc,d601-provider-egress-proxy.unidesk.svc.cluster.local,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,172.25.0.3,unidesk-provider-gateway-D601,backend-core,oa-event-flow,database,hyueapi.com,.hyueapi.com,api.minimaxi.com,.minimaxi.com"
- name: no_proxy
value: "localhost,127.0.0.1,::1,host.docker.internal,claudeqq,claudeqq.unidesk,claudeqq.unidesk.svc,claudeqq.unidesk.svc.cluster.local,d601-provider-egress-proxy,d601-provider-egress-proxy.unidesk,d601-provider-egress-proxy.unidesk.svc,d601-provider-egress-proxy.unidesk.svc.cluster.local,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,172.25.0.3,unidesk-provider-gateway-D601,backend-core,oa-event-flow,database,hyueapi.com,.hyueapi.com,api.minimaxi.com,.minimaxi.com"
- name: OA_EVENT_FLOW_BASE_URL
value: "http://d601-tcp-egress-gateway.unidesk.svc.cluster.local:4255"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED
value: "true"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL
value: "http://claudeqq.unidesk.svc.cluster.local:3290"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE
value: "private"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_USER_ID
value: "645275593"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_MAX_RESPONSE_CHARS
value: "12000"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_TIMEOUT_MS
value: "15000"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_SEND_ATTEMPTS
value: "3"
- name: LOG_FILE
value: "/var/log/unidesk/code-queue.jsonl"
- name: UNIDESK_LOG_RETENTION_BYTES
value: "1GiB"
volumeMounts:
- name: docker-sock
mountPath: /var/run/docker.sock
- name: workspace
mountPath: /workspace
- name: workspace
mountPath: /home/ubuntu
- name: repo
mountPath: /root/unidesk
- name: repo
mountPath: /app
- name: codex-config
mountPath: /root/.codex/config.toml
readOnly: true
- name: codex-auth
mountPath: /root/.codex/auth.json
readOnly: true
- name: skills-dir
mountPath: /root/.agents/skills
readOnly: true
- name: ssh-dir
mountPath: /root/.ssh
readOnly: true
- name: logs
mountPath: /var/log/unidesk
- name: state
mountPath: /var/lib/unidesk/code-queue
readinessProbe:
httpGet:
path: /health
port: http
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 20
livenessProbe:
httpGet:
path: /live
port: http
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 6
startupProbe:
httpGet:
path: /live
port: http
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 60
resources:
requests:
cpu: 250m
memory: 15Gi
limits:
memory: 15Gi
volumes:
- name: docker-sock
hostPath:
path: /var/run/docker.sock
type: Socket
- name: workspace
hostPath:
path: /home/ubuntu
type: Directory
- name: repo
hostPath:
path: /home/ubuntu/cq-deploy
type: Directory
- name: codex-config
hostPath:
path: /home/ubuntu/.codex/config.toml
type: File
- name: codex-auth
hostPath:
path: /home/ubuntu/.codex/auth.json
type: File
- name: skills-dir
hostPath:
path: /home/ubuntu/.agents/skills
type: Directory
- name: ssh-dir
hostPath:
path: /home/ubuntu/.ssh
type: Directory
- name: logs
hostPath:
path: /home/ubuntu/cq-deploy/.state/code-queue/logs
type: DirectoryOrCreate
- name: state
hostPath:
path: /home/ubuntu/cq-deploy/.state/code-queue
type: DirectoryOrCreate
---
apiVersion: v1
kind: Service
metadata:
name: code-queue
namespace: unidesk
labels:
app.kubernetes.io/name: code-queue
app.kubernetes.io/part-of: unidesk
unidesk.ai/deployment-mode: k3sctl-managed
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: code-queue
unidesk.ai/instance-id: D601
ports:
- name: http
port: 4222
targetPort: http