OpenCode

🚀Installation

Install By

Preliminary

1. Kubernetes is installed; if not, check 🔗link


2. Helm is installed; if not, check 🔗link


3. ArgoCD is installed; if not, check 🔗link


1.prepare `opencode-configuration.yaml`

Details
kubectl get namespaces opencode > /dev/null 2>&1 || kubectl create namespace opencode

kubectl -n opencode create secret generic opencode-server-secret \
  --from-literal=OPENCODE_SERVER_PASSWORD=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 16)

1.1.choose different LLM configuration

kubectl -n opencode apply -f - <<'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
  name: opencode-config
data:
  opencode.json: |
    {
      "provider": {
        "openai": {
          "options": {
            "baseURL": "https://v2.qixuw.com/v1",
            "apiKey": "sk-ss"
          },
          "models": {
            "gpt-5.3-codex-spark": {
              "name": "GPT-5.3 Codex Spark",
              "limit": {
                "context": 128000,
                "output": 32000
              },
              "options": {
                "store": false
              },
              "variants": {
                "low": {},
                "medium": {},
                "high": {},
                "xhigh": {}
              }
            }
          }
        }
      },
      "agent": {
        "build": {
          "options": {
            "store": false
          }
        },
        "plan": {
          "options": {
            "store": false
          }
        }
      },
      "$schema": "https://opencode.ai/config.json"
    }
EOF
kubectl -n opencode apply -f - <<'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
  name: opencode-config
data:
  opencode.json: |
    {
      "provider": {
        "openai": {
          "options": {
            "baseURL": "https://v2.qixuw.com/v1",
            "apiKey": "sk-ss"
          },
          "models": {
            "gpt-5.3-codex-spark": {
              "name": "GPT-5.3 Codex Spark",
              "limit": {
                "context": 128000,
                "output": 32000
              },
              "options": {
                "store": false
              },
              "variants": {
                "low": {},
                "medium": {},
                "high": {},
                "xhigh": {}
              }
            }
          }
        }
      },
      "mcp": {
        "euclid-catalog": {
          "type": "remote",
          "url": "https://catalog.euclid.mcp.dev.72602.online:32443/sse",
          "enabled": true
        },
        "astro_k3s_mcp": {
          "type": "remote",
          "url": "http://eva24002-entrance.lab.zverse.space:30082/mcp",
          "enabled": true,
          "oauth": false,
          "timeout": 15000
        }
      },
      "agent": {
        "build": {
          "options": {
            "store": false
          }
        },
        "plan": {
          "options": {
            "store": false
          }
        }
      },
      "$schema": "https://opencode.ai/config.json"
    }
EOF
kubectl -n opencode apply -f - <<'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
  name: opencode-config
data:
  opencode.json: |
    {
      "$schema": "https://opencode.ai/config.json",
      "provider": {
        "minimax": {
          "npm": "@ai-sdk/openai-compatible",
          "name": "MiniMax M2.5",
          "options": {
            "baseURL": "http://10.200.92.41:31551/v1",
            "apiKey": "sk-sss"
          },
          "models": {
            "minimax-m2.5": {
              "name": "MiniMax M2.5",
              "id": "MiniMaxAI/MiniMax-M2.5",
              "limit": {
                "context": 196608,
                "output": 8192
              }
            }
          }
        }
      },
      "model": "minimax/minimax-m2.5"
    }
EOF
kubectl -n opencode apply -f - <<'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
  name: opencode-config
data:
  opencode.json: |
    {
      "$schema": "https://opencode.ai/config.json",
      "model": "opencode/minimax-m2.5-free",
      "small_model": "opencode/minimax-m2.5-free"
    }
EOF
kubectl -n opencode apply -f - <<'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
  name: opencode-config
data:
  opencode.json: |
    {
      "provider": {
        "qiniu": {
          "options": {
            "baseURL": "https://api.qnaigc.com/v1",
            "apiKey": "sk-sss"
          },
          "models": {
            "minimax-m2.5": {
              "name": "Minimax-M2.5",
              "limit": {
                "context": 128000,
                "output": 32000
              },
              "options": {
                "store": false
              },
              "variants": {
                "low": {},
                "medium": {},
                "high": {},
                "xhigh": {}
              }
            }
          }
        }
      },
      "agent": {
        "build": {
          "options": {
            "store": false
          }
        },
        "plan": {
          "options": {
            "store": false
          }
        }
      },
      "$schema": "https://opencode.ai/config.json"
    }
EOF

2.prepare `deploy-opencode.yaml`; change the default model when you apply a different ConfigMap

Details
kubectl -n argocd apply -f - <<'EOF'
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: opencode
  namespace: argocd
spec:
  project: default
  source:
    repoURL: oci://ghcr.io/aaronyang0628/opencode
    targetRevision: 0.20.0
    chart: opencode
    helm:
      values: |
        image:
          repository: ghcr.io/nimbleflux/opencode-docker
          tag: 1.2.26
          pullPolicy: Always
        replicaCount: 1
        command:
          - opencode
        args:
          - serve
          - --port
          - "4000"
          - --hostname
          - "0.0.0.0"
        service:
          type: ClusterIP
          port: 4000
        env:
          OPENCODE_PORT: "4000"
        extraVolumes:
          - name: opencode-config
            configMap:
              name: opencode-config
        extraVolumeMounts:
          - name: opencode-config
            mountPath: /home/opencode/.config/opencode/opencode.json
            subPath: opencode.json
            readOnly: true
        persistence:
          enabled: true
          storageClass: local-path
          config:
            enabled: false 
          data:
            enabled: true
            size: 1Gi
          workspace:
            enabled: true
            size: 5Gi
          playbook:
            enabled: true
            mountPath: /home/opencode/workspace/playbook
            example:
              enabled: true
        resources:
          requests:
            cpu: 500m
            memory: 1Gi
          limits:
            cpu: 2
            memory: 4Gi
        probes:
          liveness:
            tcpSocket:
              port: 4000
            initialDelaySeconds: 15
            periodSeconds: 30
          readiness:
            tcpSocket:
              port: 4000
            initialDelaySeconds: 10
            periodSeconds: 10
          startup:
            tcpSocket:
              port: 4000
            initialDelaySeconds: 5
            periodSeconds: 5
            failureThreshold: 30
        ingress:
          enabled: true
          className: nginx
          annotations:
            kubernetes.io/ingress.class: nginx
            cert-manager.io/cluster-issuer: self-signed-ca-issuer
            nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
            nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
            nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
            nginx.ingress.kubernetes.io/proxy-body-size: "50m"
            nginx.ingress.kubernetes.io/upstream-keepalive-connections: "50"
            nginx.ingress.kubernetes.io/upstream-keepalive-timeout: "60"
          hosts:
            - host: opencode.dev.72602.online
              paths:
                - path: /
                  pathType: Prefix
          tls:
          - hosts:
            - opencode.dev.72602.online
            secretName: opencode.dev.72602.online-tls
        globalLabels:
          app.kubernetes.io/part-of: opencode
          environment: production
        bridge:
          enabled: true
          image:
            repository: crpi-wixjy6gci86ms14e.cn-hongkong.personal.cr.aliyuncs.com/ay-dev/opencode-bridge
            tag: "v20260326r4"
          env:
            defaultModel: "opencode/minimax-m2.5-free"
            openaiStreamChunkSize: "4"
            openaiStreamChunkDelayMs: "10"
            enableLeadingEchoFilter: "false"
          resources:
            limits:
              cpu: 500m
              memory: 256Mi
            requests:
              cpu: 100m
              memory: 128Mi
          ingress:
            enabled: true
            annotations:
              kubernetes.io/ingress.class: nginx
              cert-manager.io/cluster-issuer: self-signed-ca-issuer
              nginx.ingress.kubernetes.io/proxy-buffering: "off"
              nginx.ingress.kubernetes.io/proxy-request-buffering: "off"
              nginx.ingress.kubernetes.io/proxy-connect-timeout: "300"
              nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
              nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
              nginx.ingress.kubernetes.io/proxy-body-size: "50m"
              nginx.ingress.kubernetes.io/upstream-keepalive-connections: "50"
              nginx.ingress.kubernetes.io/upstream-keepalive-timeout: "60"
            hosts:
              - host: opencode-bridge.dev.72602.online
                paths:
                  - path: /
                    pathType: Prefix
            tls:
              - secretName: opencode-bridge-tls
                hosts:
                  - opencode-bridge.dev.72602.online

  destination:
    server: https://kubernetes.default.svc
    namespace: opencode
  syncPolicy:
    syncOptions:
      - CreateNamespace=true
      - ServerSideApply=true
EOF

3.sync by argocd

Details
argocd app sync argocd/opencode

4.then you can talk with LLM with rest api

Details
curl -k -X POST https://opencode.dev.72602.online:32443/session \
-H "Content-Type: application/json" \
-d '{"model": "opencode/minimax-m2.5-free"}'

## {"id":"ses_30a879abeffe6KRC0Rmg4aPrmK","slug":"brave-eagle","version":"1.2.26","projectID":"global","directory":"/home/opencode/workspace","title":"New session - 2026-03-16T07:07:14.113Z","time":{"created":1773644834113,"updated":1773644834113}}

5.reuse the same session

Details
curl -k -X POST https://opencode.dev.72602.online:32443/session/ses_30a879abeffe6KRC0Rmg4aPrmK/message \
-H "Content-Type: application/json" \
-d '{"parts": [{"type": "text", "text": "你好"}]}'

## {"info":{"role":"assistant","time":{"created":1773644844131,"completed":1773644848700},"parentID":"msg_cf5788c12001RS4wX3hwMRe0If","modelID":"minimax-m2.5","providerID":"minimax","mode":"build","agent":"build","path":{"cwd":"/home/opencode/workspace","root":"/"},"cost":0,"tokens":{"total":10628,"input":10567,"output":61,"reasoning":0,"cache":{"read":0,"write":0}},"finish":"stop","id":"msg_cf5788c63001hBrorYejcHc1tO","sessionID":"ses_30a879abeffe6KRC0Rmg4aPrmK"},"parts":[{"type":"step-start","id":"prt_cf57899120016WXp4jT4AHeTiG","sessionID":"ses_30a879abeffe6KRC0Rmg4aPrmK","messageID":"msg_cf5788c63001hBrorYejcHc1tO"},{"type":"text","text":"<think>The user said \"你好\" which means \"Hello\" in Chinese. According to the instructions, I should be concise and direct. I should respond briefly without unnecessary preamble. Since this is a simple greeting, I can just respond with a greeting back.\n</think>\n\n你好!有什么可以帮你的吗?","time":{"start":1773644848689,"end":1773644848689},"id":"prt_cf5789913001dUZnoW9w63ThkC","sessionID":"ses_30a879abeffe6KRC0Rmg4aPrmK","messageID":"msg_cf5788c63001hBrorYejcHc1tO"},{"type":"step-finish","reason":"stop","cost":0,"tokens":{"total":10628,"input":10567,"output":61,"reasoning":0,"cache":{"read":0,"write":0}},"id":"prt_cf5789e35001dLGIXJb5WHizMX","sessionID":"ses_30a879abeffe6KRC0Rmg4aPrmK","messageID":"msg_cf5788c63001hBrorYejcHc1tO"}]}

Preliminary

1. Kubernetes is installed; if not, check 🔗link


2. Helm is installed; if not, check 🔗link


3. ArgoCD is installed; if not, check 🔗link


0. (optional) deploy `oauth2-proxy` for GitHub OAuth 2FA

Details
kubectl get namespaces oauth2-proxy > /dev/null 2>&1 || kubectl create namespace oauth2-proxy

kubectl -n oauth2-proxy create secret generic oauth2-proxy-secret \
  --from-literal=client-id=<your-github-oauth-client-id> \
  --from-literal=client-secret=<your-github-oauth-client-secret> \
  --from-literal=cookie-secret=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 32)

kubectl -n argocd apply -f - <<'EOF'
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: oauth2-proxy
  namespace: argocd
spec:
  project: default
  source:
    repoURL: oci://ghcr.io/aaronyang0628/oauth2-proxy
    targetRevision: 7.7.0
    chart: oauth2-proxy
    helm:
      values: |
        config:
          clientID: ""
          existingSecret: oauth2-proxy-secret
        extraEnv:
          - name: OAUTH2_PROXY_CLIENT_ID
            valueFrom:
              secretKeyRef:
                name: oauth2-proxy-secret
                key: client-id
          - name: OAUTH2_PROXY_CLIENT_SECRET
            valueFrom:
              secretKeyRef:
                name: oauth2-proxy-secret
                key: client-secret
          - name: OAUTH2_PROXY_COOKIE_SECRET
            valueFrom:
              secretKeyRef:
                name: oauth2-proxy-secret
                key: cookie-secret
        provider: github
        upstreams:
          - http://opencode:4000
        ingress:
          enabled: true
          className: nginx
          annotations:
            cert-manager.io/cluster-issuer: letsencrypt
          hosts:
            - host: ops.agent.72602.online
              paths:
                - /
          tls:
            - secretName: ops.agent.72602.online-tls
              hosts:
                - ops.agent.72602.online
  destination:
    server: https://kubernetes.default.svc
    namespace: oauth2-proxy
  syncPolicy:
    syncOptions:
      - CreateNamespace=true
EOF

1.prepare `opencode-configuration.yaml`

Details
kubectl get namespaces opencode > /dev/null 2>&1 || kubectl create namespace opencode

kubectl -n opencode create secret generic opencode-server-secret \
  --from-literal=OPENCODE_SERVER_PASSWORD=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 16)

2.prepare `deploy-opencode.yaml`

Details
kubectl -n argocd apply -f - <<'EOF'
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: opencode
  namespace: argocd
spec:
  project: default
  source:
    repoURL: oci://ghcr.io/aaronyang0628/opencode
    targetRevision: 0.20.0
    chart: opencode
    helm:
      values: |
        image:
          repository: ghcr.io/nimbleflux/opencode-docker
          tag: 1.2.26
          pullPolicy: Always
        replicaCount: 1
        command:
          - opencode
        args:
          - serve
          - --port
          - "4000"
          - --hostname
          - "0.0.0.0"
        service:
          type: ClusterIP
          port: 4000
        env:
          OPENCODE_PORT: "4000"
        extraVolumes:
          - name: opencode-config
            configMap:
              name: opencode-config
        extraVolumeMounts:
          - name: opencode-config
            mountPath: /home/opencode/.config/opencode/opencode.json
            subPath: opencode.json
            readOnly: true
        persistence:
          enabled: true
          storageClass: local-path
          config:
            enabled: false 
          data:
            enabled: true
            size: 1Gi
          workspace:
            enabled: true
            size: 5Gi
          playbook:
            enabled: true
            mountPath: /home/opencode/workspace/playbook
            example:
              enabled: true
        resources:
          requests:
            cpu: 500m
            memory: 1Gi
          limits:
            cpu: 2
            memory: 4Gi
        probes:
          liveness:
            tcpSocket:
              port: 4000
            initialDelaySeconds: 15
            periodSeconds: 30
          readiness:
            tcpSocket:
              port: 4000
            initialDelaySeconds: 10
            periodSeconds: 10
          startup:
            tcpSocket:
              port: 4000
            initialDelaySeconds: 5
            periodSeconds: 5
            failureThreshold: 30
        ingress:
          enabled: true
          className: nginx
          annotations:
            kubernetes.io/ingress.class: nginx
            cert-manager.io/cluster-issuer: letsencrypt
            nginx.ingress.kubernetes.io/proxy-connect-timeout: "300"
            nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
            nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
            nginx.ingress.kubernetes.io/proxy-body-size: "50m"
            nginx.ingress.kubernetes.io/upstream-keepalive-connections: "50"
            nginx.ingress.kubernetes.io/upstream-keepalive-timeout: "60"
          hosts:
            - host: ops.agent.72602.online
              paths:
                - path: /
                  pathType: Prefix
          tls:
          - hosts:
            - ops.agent.72602.online
            secretName: ops.agent.72602.online-tls
        globalLabels:
          app.kubernetes.io/part-of: opencode
          environment: production
        bridge:
          enabled: true
          image:
            repository: crpi-wixjy6gci86ms14e.cn-hongkong.personal.cr.aliyuncs.com/ay-dev/opencode-bridge
            tag: "v20260326r4"
          env:
            defaultModel: "openai/gpt-5.3-codex-spark"
            openaiStreamChunkSize: "4"
            openaiStreamChunkDelayMs: "10"
            enableLeadingEchoFilter: "false"
          resources:
            limits:
              cpu: 500m
              memory: 256Mi
            requests:
              cpu: 100m
              memory: 128Mi
          ingress:
            enabled: true
            annotations:
              kubernetes.io/ingress.class: nginx
              cert-manager.io/cluster-issuer: letsencrypt
              nginx.ingress.kubernetes.io/proxy-buffering: "off"
              nginx.ingress.kubernetes.io/proxy-request-buffering: "off"
              nginx.ingress.kubernetes.io/proxy-connect-timeout: "300"
              nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
              nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
              nginx.ingress.kubernetes.io/proxy-body-size: "50m"
              nginx.ingress.kubernetes.io/upstream-keepalive-connections: "50"
              nginx.ingress.kubernetes.io/upstream-keepalive-timeout: "60"
            hosts:
              - host: opencode-bridge.72602.online
                paths:
                  - path: /
                    pathType: Prefix
            tls:
              - secretName: opencode-bridge-tls
                hosts:
                  - opencode-bridge.72602.online

  destination:
    server: https://kubernetes.default.svc
    namespace: opencode
  syncPolicy:
    syncOptions:
      - CreateNamespace=true
      - ServerSideApply=true
EOF

3.sync by argocd

Details
argocd app sync argocd/opencode

4.then you can talk with LLM with rest api

Details
curl -s "https://opencode-bridge.72602.online/v1/models"

## {"id":"ses_30a879abeffe6KRC0Rmg4aPrmK","slug":"brave-eagle","version":"1.2.26","projectID":"global","directory":"/home/opencode/workspace","title":"New session - 2026-03-16T07:07:14.113Z","time":{"created":1773644834113,"updated":1773644834113}}

4.then you can talk with LLM with rest api

Details
curl -k -X POST https://ops.agent.72602.online/session \
-H "Content-Type: application/json" \
-d '{"model": "MiniMaxAI/MiniMax-M2.5"}'

## {"id":"ses_30a879abeffe6KRC0Rmg4aPrmK","slug":"brave-eagle","version":"1.2.26","projectID":"global","directory":"/home/opencode/workspace","title":"New session - 2026-03-16T07:07:14.113Z","time":{"created":1773644834113,"updated":1773644834113}}

5.reuse the same session

Details
curl -k -X POST https://ops.agent.72602.online/session/ses_30a879abeffe6KRC0Rmg4aPrmK/message \
-H "Content-Type: application/json" \
-d '{"parts": [{"type": "text", "text": "你好"}]}'

## {"info":{"role":"assistant","time":{"created":1773644844131,"completed":1773644848700},"parentID":"msg_cf5788c12001RS4wX3hwMRe0If","modelID":"minimax-m2.5","providerID":"minimax","mode":"build","agent":"build","path":{"cwd":"/home/opencode/workspace","root":"/"},"cost":0,"tokens":{"total":10628,"input":10567,"output":61,"reasoning":0,"cache":{"read":0,"write":0}},"finish":"stop","id":"msg_cf5788c63001hBrorYejcHc1tO","sessionID":"ses_30a879abeffe6KRC0Rmg4aPrmK"},"parts":[{"type":"step-start","id":"prt_cf57899120016WXp4jT4AHeTiG","sessionID":"ses_30a879abeffe6KRC0Rmg4aPrmK","messageID":"msg_cf5788c63001hBrorYejcHc1tO"},{"type":"text","text":"<think>The user said \"你好\" which means \"Hello\" in Chinese. According to the instructions, I should be concise and direct. I should respond briefly without unnecessary preamble. Since this is a simple greeting, I can just respond with a greeting back.\n</think>\n\n你好!有什么可以帮你的吗?","time":{"start":1773644848689,"end":1773644848689},"id":"prt_cf5789913001dUZnoW9w63ThkC","sessionID":"ses_30a879abeffe6KRC0Rmg4aPrmK","messageID":"msg_cf5788c63001hBrorYejcHc1tO"},{"type":"step-finish","reason":"stop","cost":0,"tokens":{"total":10628,"input":10567,"output":61,"reasoning":0,"cache":{"read":0,"write":0}},"id":"prt_cf5789e35001dLGIXJb5WHizMX","sessionID":"ses_30a879abeffe6KRC0Rmg4aPrmK","messageID":"msg_cf5788c63001hBrorYejcHc1tO"}]}

1. following the steps in `https://opencode.ai`

Details
curl -fsSL https://opencode.ai/install | bash

6.use bridge to manage session

bridge

🌐Hugo Docs Site

The Hugo documentation site is deployed via ArgoCD on ops.docs.72602.online (formerly port.72602.online).

Deployment Environment

Preliminary

1. Kubernetes is installed; if not, check 🔗link


2. Helm is installed; if not, check 🔗link


3. ArgoCD is installed; if not, check 🔗link


1.prepare `deploy-hugo-docs.yaml`

Details
kubectl -n argocd apply -f - <<'EOF'
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: hugo-docs
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/aaronyang0628/ops-docs.git
    targetRevision: main
    path: .
  destination:
    server: https://kubernetes.default.svc
    namespace: hugo-docs
  syncPolicy:
    syncOptions:
      - CreateNamespace=true
    automated:
      prune: true
      selfHeal: true
EOF

2.sync by argocd

Details
argocd app sync argocd/hugo-docs

🤖Multi-Agent System

The opencode deployment includes two specialized agents for cluster and documentation maintenance:

AgentRoleTarget
k3s-maintainerCluster operationsk3s cluster health, pod management, node maintenance
doc-maintainerDocumentation updatesHugo docs site content, ArgoCD Application updates

Agent Configuration (applied as ConfigMaps)

Details
kubectl -n opencode apply -f - <<'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
  name: k3s-maintainer-config
data:
  opencode.json: |
    {
      "provider": {
        "openai": {
          "options": {
            "baseURL": "https://v2.qixuw.com/v1",
            "apiKey": "sk-ss"
          },
          "models": {
            "gpt-5.3-codex-spark": {
              "name": "GPT-5.3 Codex Spark",
              "limit": { "context": 128000, "output": 32000 }
            }
          }
        }
      },
      "mcp": {
        "k8s-mcp": {
          "type": "remote",
          "url": "http://k8s-mcp.opencode.svc.cluster.local:8080/mcp",
          "enabled": true,
          "timeout": 15000
        }
      },
      "agent": {
        "build": { "options": { "store": false } },
        "plan": { "options": { "store": false } }
      }
    }
EOF

Deploy agents via ArgoCD - each agent runs as a separate opencode server Pod with its own ConfigMap

Details
kubectl -n argocd apply -f - <<'EOF'
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: k3s-maintainer
  namespace: argocd
spec:
  project: default
  source:
    repoURL: oci://ghcr.io/aaronyang0628/opencode
    targetRevision: 0.20.0
    chart: opencode
    helm:
      values: |
        image:
          repository: ghcr.io/nimbleflux/opencode-docker
          tag: 1.2.26
        replicaCount: 1
        command: ["opencode"]
        args: ["serve", "--port", "4001", "--hostname", "0.0.0.0"]
        service:
          type: ClusterIP
          port: 4001
        env:
          OPENCODE_PORT: "4001"
        extraVolumes:
          - name: agent-config
            configMap:
              name: k3s-maintainer-config
        extraVolumeMounts:
          - name: agent-config
            mountPath: /home/opencode/.config/opencode/opencode.json
            subPath: opencode.json
        persistence:
          enabled: true
          storageClass: local-path
          config:
            enabled: false
          data:
            enabled: true
            size: 1Gi
          workspace:
            enabled: true
            size: 5Gi
        resources:
          requests:
            cpu: 500m
            memory: 1Gi
          limits:
            cpu: 2
            memory: 4Gi
  destination:
    server: https://kubernetes.default.svc
    namespace: opencode
  syncPolicy:
    syncOptions:
      - CreateNamespace=true
      - ServerSideApply=true
EOF

⚡Optimizations

Several optimizations were applied to improve the ArgoCD workflow:

OptimizationBeforeAfter
GitHub proxy for ArgoCDDirect GitHub accessghfast.top mirror
Git repo size117 MB44 MB
ArgoCD sync timeslow (~minutes)~7 seconds

1. GitHub Proxy - configure ArgoCD to use `ghfast.top` for faster OCI/Helm chart pulls

Details
# In argocd-cm ConfigMap:
data:
  repositories: |
    - url: oci://ghcr.io
      proxy: https://ghfast.top

2. Repo Size Reduction - cleaned large files and unused assets from the git repository

Details
# Remove git history and prune
git filter-repo --strip-blobs-bigger-than 1M
git gc --aggressive --prune=now

3. Fast ArgoCD Sync - achieved by combining ServerSideApply, lean manifests, and cached images

Details
syncPolicy:
  syncOptions:
    - ServerSideApply=true

🛎️FAQ

Q1: OpenCode Pod runs but API returns 401/403

Symptom

  • curl to /session or bridge endpoint returns unauthorized.

Check

kubectl -n opencode get secret opencode-server-secret -o yaml
kubectl -n opencode get configmap opencode-config -o yaml
kubectl -n opencode logs deploy/opencode --tail=100

Fix

  • Confirm OPENCODE_SERVER_PASSWORD secret exists and is mounted correctly.
  • Confirm client request carries expected auth configuration.
  • Re-apply ConfigMap/Application and sync again.

Expected

  • Session creation and message requests return successful JSON responses.
Q2: Model list is empty or model invocation fails

Symptom

  • /v1/models returns empty list, or chat request returns provider/model error.

Check

kubectl -n opencode get configmap opencode-config -o jsonpath='{.data.opencode\.json}'
kubectl -n opencode logs deploy/opencode --tail=200

Fix

  • Verify provider baseURL, apiKey, and model ID in opencode.json.
  • Ensure selected default model exists in configured provider models.
  • Re-apply config and restart workload if needed.

Expected

  • /v1/models shows expected model entries and session message calls succeed.