Subsections of Application

N8N

🚀Installation

Environment
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. Database postgresql has been installed, if not check 🔗link


1.prepare `n8n-middleware-credentials.yaml`

Details
kubectl get namespaces n8n > /dev/null 2>&1 || kubectl create namespace n8n
N8N_PASSWORD=$(kubectl -n database get secret postgresql-credentials -o jsonpath='{.data.password}' | base64 -d)
kubectl -n n8n create secret generic n8n-middleware-credential \
--from-literal=postgres-password="${N8N_PASSWORD}"

2.prepare `deploy-n8n.yaml`

Details
kubectl -n argocd apply -f - <<EOF
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: n8n
spec:
  project: default
  source:
    repoURL: https://community-charts.github.io/helm-charts
    targetRevision: 1.16.36
    helm:
      releaseName: n8n
      values: |
        global:
          security:
            allowInsecureImages: true
        image:
          repository: n8nio/n8n
        log:
          level: info
        encryptionKey: "ay-dev-n8n"
        timezone: Asia/Shanghai
        db:
          type: postgresdb
        externalPostgresql:
          host: postgresql-hl.database.svc.cluster.local
          port: 5432
          username: "n8n"
          database: "n8n"
          existingSecret: "n8n-middleware-credential"
        main:
          count: 1
          extraEnvVars:
            "N8N_BLOCK_ENV_ACCESS_IN_NODE": "false"
            "N8N_FILE_SYSTEM_ALLOWED_PATHS": "/home/node/.n8n-files"
            "EXECUTIONS_TIMEOUT": "300"
            "EXECUTIONS_TIMEOUT_MAX": "600"
            "DB_POSTGRESDB_POOL_SIZE": "10"
            "CACHE_ENABLED": "true"
            "N8N_CONCURRENCY_PRODUCTION_LIMIT": "5"
            "NODE_TLS_REJECT_UNAUTHORIZED": "0"
            "N8N_SECURE_COOKIE": "false"
            "WEBHOOK_URL": "https://webhook.n8n.dev.72602.online"
            "QUEUE_BULL_REDIS_TIMEOUT_THRESHOLD": "60000"
            "N8N_COMMUNITY_PACKAGES_ENABLED": "true"
            "N8N_GIT_NODE_DISABLE_BARE_REPOS": "true"
            "N8N_LICENSE_AUTO_RENEW_ENABLED": "true"
            "N8N_LICENSE_RENEW_ON_INIT": "true"
          persistence:
            enabled: true
            accessMode: ReadWriteOnce
            storageClass: "local-path"
            size: 50Gi
          volumes:
            - name: downloads-volume
              hostPath:
                path: /home/aaron/Downloads
                type: DirectoryOrCreate
          volumeMounts:
            - name: downloads-volume
              mountPath: /home/node/.n8n-files
          resources:
            requests:
              cpu: 1000m
              memory: 1024Mi
            limits:
              cpu: 2000m
              memory: 2048Mi
        worker:
          mode: queue
          count: 2
          waitMainNodeReady:
            enabled: false
          extraEnvVars:
            "N8N_FILE_SYSTEM_ALLOWED_PATHS": "/home/node/.n8n-files"
            "EXECUTIONS_TIMEOUT": "300"
            "EXECUTIONS_TIMEOUT_MAX": "600"
            "DB_POSTGRESDB_POOL_SIZE": "5"
            "QUEUE_BULL_REDIS_TIMEOUT_THRESHOLD": "60000"
            "N8N_COMMUNITY_PACKAGES_ENABLED": "true"
            "N8N_GIT_NODE_DISABLE_BARE_REPOS": "true"
            "N8N_LICENSE_AUTO_RENEW_ENABLED": "true"
            "N8N_LICENSE_RENEW_ON_INIT": "true"
          persistence:
            enabled: true
            accessMode: ReadWriteOnce
            storageClass: "local-path"
            size: 50Gi
          volumes:
            - name: downloads-volume
              hostPath:
                path: /home/aaron/Downloads
                type: DirectoryOrCreate
          volumeMounts:
            - name: downloads-volume
              mountPath: /home/node/.n8n-files
          resources:
            requests:
              cpu: 500m
              memory: 1024Mi
            limits:
              cpu: 1000m
              memory: 2048Mi
        nodes:
          builtin:
            enabled: true
            modules:
              - crypto
              - fs
          external:
            allowAll: true
            packages:
              - n8n-nodes-globals
        npmRegistry:
          enabled: true
          url: http://mirrors.cloud.tencent.com/npm/
        redis:
          enabled: true
          image:
            registry: m.daocloud.io/docker.io
            repository: bitnamilegacy/redis
          master:
            resourcesPreset: "small"
            persistence:
              enabled: true
              accessMode: ReadWriteOnce
              storageClass: "local-path"
              size: 10Gi
        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: "300"
            nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
            nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
            nginx.ingress.kubernetes.io/proxy-body-size: "50m"
            nginx.ingress.kubernetes.io/upstream-keepalive-connections: "50"
            nginx.ingress.kubernetes.io/upstream-keepalive-timeout: "60"
            nginx.ingress.kubernetes.io/enable-cors: "true"
            nginx.ingress.kubernetes.io/cors-allow-origin: "https://webhook.n8n.dev.72602.online:32443"
            nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, OPTIONS, PUT, DELETE"
            nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization"
            nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
          hosts:
            - host: n8n.dev.72602.online
              paths:
                - path: /
                  pathType: Prefix
            - host: webhook.n8n.dev.72602.online
              paths:
                - path: /
                  pathType: Prefix
          tls:
          - hosts:
            - n8n.dev.72602.online
            - webhook.n8n.dev.72602.online
            secretName: n8n.dev.72602.online-tls
        webhook:
          mode: queue
          url: "https://webhook.n8n.dev.72602.online"
          autoscaling:
            enabled: false
          waitMainNodeReady:
            enabled: true
          resources:
            requests:
              cpu: 200m
              memory: 256Mi
            limits:
              cpu: 512m
              memory: 512Mi
    chart: n8n
  destination:
    server: https://kubernetes.default.svc
    namespace: n8n
  syncPolicy:
    syncOptions:
      - CreateNamespace=true
      - ApplyOutOfSyncOnly=false

EOF

3.sync by argocd

Details
argocd app sync argocd/n8n
Using AY Helm Mirror

for more information, you can check 🔗https://github.com/AaronYang0628/helm-chart-mirror

helm repo add ay-helm-mirror https://aaronyang0628.github.io/helm-chart-mirror/charts
  helm repo update
  helm install ay-helm-mirror/chart-name --generate-name --version a.b.c
Using AY ACR Image Mirror
Using DaoCloud Mirror
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. Database postgresql has been installed, if not check 🔗link


1.verify retained credentials and storage

Details
kubectl get namespace n8n
kubectl -n n8n get secret n8n-middleware-credential n8n-encryption-key-existing
kubectl -n n8n get pvc
Important

The live credentials and PVCs are retained state. Do not delete, recreate, or replace them when updating the Argo CD Application.

2.review and publish the canonical source `manifests/n8n-argocd.yaml`

The n8n Argo CD Application is parent-managed by argocd/ops-docs from the repository’s main branch and manifests path. n8n itself is manually synced after the parent Application has converged. The current chart is 1.24.42 and n8n is 2.40.5.

Details
git diff --check
git diff -- manifests/n8n-argocd.yaml
git status --short
git add manifests/n8n-argocd.yaml
git commit -m "fix(n8n): configure AI model requests"
git push origin main

3.wait for parent convergence, then manually sync n8n

Details
argocd app get argocd/ops-docs --insecure --grpc-web
argocd app sync argocd/n8n --insecure --grpc-web
argocd app get argocd/n8n --insecure --grpc-web
kubectl -n n8n rollout status deployment/n8n --timeout=300s

Verify parent argocd/ops-docs is synced before manually syncing argocd/n8n. Review the Application diff and confirm the existing credentials and PVCs remain unchanged.

4.verify

Details
argocd app get argocd/n8n --insecure --grpc-web
kubectl -n n8n rollout status deployment/n8n --timeout=300s
kubectl -n n8n get pods
curl -sS -o /dev/null -w '%{http_code}\n' https://n8n.72602.space/healthz
curl -sS -o /dev/null -w '%{http_code}\n' https://n8n.72602.space/healthz/readiness
curl -sS -o /dev/null -w '%{http_code}\n' https://n8n.72602.space/

Confirm the Application is Synced and Healthy, the main Pod is Ready without restarts, and the health/readiness endpoints and public editor return HTTP 200.

🛎️FAQ

Q1: n8n cannot connect to PostgreSQL

Symptom

  • n8n Pod starts but keeps retrying DB connection.

Check

kubectl -n n8n get pods
kubectl -n n8n logs deploy/n8n -c n8n --tail=100
kubectl -n n8n get secret n8n-middleware-credential -o yaml
kubectl -n database get svc postgresql-hl

Fix

  • Confirm secret key name matches chart expectation (postgres-password).
  • Confirm DB host/port/user/database in values are correct.
  • Ensure PostgreSQL is healthy before syncing n8n.

Expected

  • n8n Pod reaches Running and UI becomes accessible.
Q2: 72602 Argo CD reports Redis Secret and checksum drift

Symptom

  • Secret/n8n-redis and StatefulSet/n8n-redis-master repeatedly report drift even though Redis is healthy.

Root cause

  • The Redis subchart renders a generated password when no fixed password is supplied. A new desired render changes /data/redis-password and the derived pod-template checksum/secret without indicating live credential corruption.

Fix

  • Preserve all live n8n credentials and PVCs. Do not delete, recreate, or replace them to resolve this drift.
  • Keep ignoreDifferences limited to /data/redis-password and the Redis StatefulSet’s checksum/secret, with RespectIgnoreDifferences=true.
  • Review the remaining diff, then sync the Application only when it contains the intended values change.
argocd app diff argocd/n8n --insecure --grpc-web --refresh
argocd app sync argocd/n8n --insecure --grpc-web
argocd app get argocd/n8n --insecure --grpc-web
kubectl -n n8n rollout status deployment/n8n --timeout=300s
kubectl -n n8n rollout status statefulset/n8n-redis-master --timeout=300s

Rollback

  • Remove only the two ignoreDifferences entries and RespectIgnoreDifferences=true, then reapply the Application. This restores drift reporting without changing the Secret or PVC.

Expected

  • Argo CD reports Synced and Healthy; n8n and Redis remain Ready, and the existing PVCs remain Bound.
Q3: Community nodes fail — “Unrecognized node type” after pod restart

Symptom

  • Webhook 或 workflow 报 Unrecognized node type: n8n-nodes-xxx
  • 社区包在 Pod 重启后消失

Root cause

  • Helm chart 内置 initContainer 使用 node:20-alpine,缺少 Python
  • 含 native 依赖的包(如 isolated-vm)npm install 失败,导致所有社区包未安装
  • 对 webhook pod,chart 默认不提供社区节点 volume/initContainer

Fix (permanent, survives ArgoCD sync)

​

核心思路:chart 内置 initContainer 空跑,自定义 initContainer 注入到 `main/worker/webhook.initContainers`。

nodes:
  external:
    packages: []   # 清空 chart 内置包列表,避免 native build 失败
main:
  volumes:
    - name: community-node-modules
      emptyDir: {}
  volumeMounts:
    - name: community-node-modules
      mountPath: /home/node/.n8n/nodes
  initContainers:
    - name: npm-install-community
      image: node:20-alpine
      command: ['/bin/sh', '-c']
      args:
        - |
          export COMMUNITY_PACKAGES="n8n-nodes-globals n8n-nodes-wechat-formatter n8n-nodes-browserless-api"
          mkdir -p /nodesdata/nodes
          echo "$COMMUNITY_PACKAGES" | sha256sum > /nodesdata/nodes/packages.hash.new
          if [ ! -f /nodesdata/nodes/packages.hash ] || ! cmp /nodesdata/nodes/packages.hash /nodesdata/nodes/packages.hash.new; then
            npm install --loglevel info --no-save --ignore-scripts $COMMUNITY_PACKAGES --prefix /nodesdata/nodes
            mv /nodesdata/nodes/packages.hash.new /nodesdata/nodes/packages.hash
          fi
      env:
        - name: HTTP_PROXY
          value: http://192.168.0.25:17890
        - name: HTTPS_PROXY
          value: http://192.168.0.25:17890
      volumeMounts:
        - name: community-node-modules
          mountPath: /nodesdata/nodes
      securityContext:
        runAsUser: 1000
        runAsGroup: 1000
        runAsNonRoot: true
# worker 和 webhook 同样添加上述 volumes/volumeMounts/initContainers
worker:
  volumes: ...
  volumeMounts: ...
  initContainers: ...
webhook:
  volumes: ...
  volumeMounts: ...
  initContainers: ...

--ignore-scripts 是关键:跳过 isolated-vm 等 native 依赖编译,node:20-alpine 不含 Python 也能装。

同上,只需修改: - `HTTP_PROXY`/`HTTPS_PROXY` 按 ZJ 集群代理地址填写 - `COMMUNITY_PACKAGES` 按需调整

Manual emergency fix (quick)

# 在每个 Pod 内手动安装
kubectl exec -n n8n deploy/n8n -- sh -c \
  "cd /home/node/.n8n/nodes && npm install --ignore-scripts n8n-nodes-globals n8n-nodes-wechat-formatter n8n-nodes-browserless-api"
kubectl exec -n n8n statefulset/n8n-worker -- sh -c \
  "cd /home/node/.n8n/nodes && npm install --ignore-scripts n8n-nodes-globals n8n-nodes-wechat-formatter n8n-nodes-browserless-api"
# 重启 n8n 加载新节点
kubectl delete pods -n n8n -l app.kubernetes.io/component=main
kubectl delete pods -n n8n -l app.kubernetes.io/component=worker

Expected

  • kubectl exec -n n8n deploy/n8n -- ls /home/node/.n8n/nodes/node_modules/ | grep n8n 有输出
  • Webhook 返回正常响应(非 Unrecognized node type)
Q4: AI Agent requests fail through the proxy or during tool rounds

Symptoms

  • An AI Agent call fails with AI_APICallError: Cannot connect to API: other side closed and UND_ERR_SOCKET.
  • OpenAI-compatible Responses requests can work on the first turn but fail with HTTP 502 when a later tool round contains item_reference.

Root causes

  • @n8n/agents createModel unconditionally constructs a ProxyAgent from uppercase HTTP_PROXY/HTTPS_PROXY and does not honor NO_PROXY. Internal cluster traffic is sent to the host proxy and can be closed.
  • The OpenAI provider uses /v1/responses; default stored response history includes item_reference in multi-step tool requests, which the configured upstream does not handle.

Fix

  • Use the canonical manifests/n8n-argocd.yaml; do not create a second inline Application definition.
  • Add literal lowercase http_proxy, https_proxy, and no_proxy entries to main.extraEnv before the existing API-key Secret reference; set both proxy values to http://192.168.0.25:17890 and no_proxy to registry.npmjs.org,npmjs.org,npmmirror.com,registry.npmmirror.com,.svc,.cluster.local,10.0.0.0/8. Keep uppercase NO_PROXY with the same list in main.extraEnvVars. Chart 1.24.42 uppercases every main.extraEnvVars key, so lowercase entries there do not work; inspect the Helm-rendered final environment, not only the YAML spellings. Leave worker and init-container proxy settings unchanged.
  • Set N8N_INSTANCE_AI_MODEL=custom/gpt-6-astra, N8N_INSTANCE_AI_MODEL_URL=http://sub2api.application.svc.cluster.local:8080/v1, and N8N_INSTANCE_AI_SEARXNG_URL=http://searxng.searxng.svc.cluster.local:8080/. Reference the key through n8n-assistant-model Secret key api-key; do not put the key in values or logs.
  • Lowercase proxy variables remain available to normal n8n HTTP transports, while the AI model factory uses the direct internal endpoint.

Verification scope

  • Confirmed synthetic @n8n/agents createModel streaming tests reproduce the uppercase-proxy socket failure and pass when the internal model URL is direct.
  • A direct Responses request succeeds on the first turn but its second item_reference request returns 502; a store:false roundtrip passes. Selecting the custom provider’s stateless /v1/chat/completions route passes a synthetic tool roundtrip (two steps, one tool call, no stream errors, finishReason=stop).
  • Repair commit 768558f is deployed. Argo CD Application argocd/n8n is Synced and Healthy with Manual sync policy, chart 1.24.42, and image 2.40.5. Main Pod n8n-7bbfdd6f4d-grm7p, created 2026-09-30T05:57:07Z, is Ready 1/1 with zero restarts.
  • The final main Pod has no uppercase HTTP_PROXY/HTTPS_PROXY; lowercase http_proxy/https_proxy and both NO_PROXY/no_proxy are present. Normal environment proxy resolution routes internal requests DIRECT and external requests through http://192.168.0.25:17890.
  • In an isolated subprocess using the final main Pod environment without candidate overrides, the n8n image’s actual createInstanceAgent and streamAgentRun completed a research run with custom/gpt-6-astra and @n8n/ai-utilities searxngSearch: exactly one search returned three results; both /v1/chat/completions calls returned HTTP 200; events were text-delta 20, tool-call 1, and tool-result 1; final status was completed.
  • In that subprocess, other workflow, credential, and data-service adapters were empty or read-only, and no persisted browser session was used. The n8n UI has not been clicked, so this does not establish full UI validation.
  • Main /healthz and /healthz/readiness and the public editor return HTTP 200. A public unknown synthetic /webhook/ route returns the expected unregistered-webhook HTTP 404. Main, worker, webhook, MCP, and Redis components are Ready with zero restarts; fresh main logs contain zero assistant socket errors.

Deploy and rollback

  • Review and push the manifest change to main, wait for parent argocd/ops-docs convergence, then manually sync argocd/n8n in the order above.
  • If the repair must be rolled back, create and push a new Git revert of 768558f, wait for parent convergence, and manually sync n8n again. Do not restore the old inline Application recipe or revert unrelated changes.
Mar 7, 2024

Wechat Markdown Editor

Official Documentation: https://github.com/doocs/md

🚀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 `deploy-wx-article-editor.yaml`

Details
kubectl -n argocd apply -f - <<'EOF'
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: wx-article-editor
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://bjw-s-labs.github.io/helm-charts
    chart: app-template
    targetRevision: 4.4.0
    helm:
      values: |
        controllers:
          main:
            containers:
              app:
                image:
                  repository: m.daocloud.io/docker.io/doocs/md
                  tag: latest
                  pullPolicy: IfNotPresent
                probes:
                  liveness:
                    enabled: true
                  readiness:
                    enabled: true
                  startup:
                    enabled: true

        service:
          app:
            controller: main
            ports:
              http:
                port: 80

        ingress:
          app:
            enabled: true
            className: nginx
            annotations:
              kubernetes.io/ingress.class: nginx
              cert-manager.io/cluster-issuer: self-signed-ca-issuer
            hosts:
              - host: md.dev.72602.online
                paths:
                  - path: /
                    pathType: Prefix
                    service:
                      identifier: app
                      port: http
            tls:
              - secretName: md.dev.72602.online-tls
                hosts:
                  - md.dev.72602.online
  destination:
    server: https://kubernetes.default.svc
    namespace: application
  syncPolicy:
    syncOptions:
      - CreateNamespace=true
      - ServerSideApply=true
EOF

2.sync by argocd

Details
argocd app sync argocd/wx-article-editor

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-wx-article-editor.yaml`

Details
kubectl -n argocd apply -f - <<'EOF'
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: wx-article-editor
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://bjw-s-labs.github.io/helm-charts
    chart: app-template
    targetRevision: 4.4.0
    helm:
      values: |
        controllers:
          main:
            containers:
              app:
                image:
                  repository: m.daocloud.io/docker.io/doocs/md
                  tag: latest
                  pullPolicy: IfNotPresent
                probes:
                  liveness:
                    enabled: true
                  readiness:
                    enabled: true
                  startup:
                    enabled: true

        service:
          app:
            controller: main
            ports:
              http:
                port: 80

        ingress:
          app:
            enabled: true
            className: nginx
            annotations:
              kubernetes.io/ingress.class: nginx
              cert-manager.io/cluster-issuer: letsencrypt
            hosts:
              - host: md.72602.online
                paths:
                  - path: /
                    pathType: Prefix
                    service:
                      identifier: app
                      port: http
            tls:
              - secretName: md.72602.online-tls
                hosts:
                  - md.72602.online
  destination:
    server: https://kubernetes.default.svc
    namespace: application
  syncPolicy:
    syncOptions:
      - CreateNamespace=true
      - ServerSideApply=true
EOF

2.sync by argocd

Details
argocd app sync argocd/wx-article-editor

1.run container

Details
docker run -d --name wx-article-editor -p 8080:80 doocs/md:latest

2.access in browser

Details
open http://localhost:8080

Verify

Details
kubectl -n application get pods
kubectl -n application get ingress

If deployed in ZJ environment, open https://md.dev.72602.online.

If deployed in 72602 environment, open https://md.72602.online.

🛎️FAQ

Q1: Page is blank after opening domain

Check Pod and Ingress first:

kubectl -n application get pods
kubectl -n application logs deploy/wx-article-editor --tail=100
kubectl -n application describe ingress

Then verify the domain resolves to your ingress entry node.

Q2: Browser does not trust HTTPS certificate

If you use self-signed issuer in ZJ, export CA cert and import into browser:

kubectl -n basic-components get secret root-secret -o jsonpath='{.data.tls\.crt}' | base64 -d > cert-manager-self-signed-ca-secret.crt
Mar 7, 2024

Charge Spot Quest

Overview

Charge Spot Quest is the 邻里互助·共享充电 UI + booking API. It is deployed via the 72602 ArgoCD GitOps pipeline using Helm chart charge-spot-quest (version 0.1.15) with in-cluster SQLite.

  • ArgoCD Application: argocd/charge-spot-quest (child of argocd/ops-docs)
  • Namespace: charge-spot
  • Service: charge-spot-quest (port 8080)
  • Ingress: charge.72602.space (TLS via cert-manager)
  • Database: SQLite PVC charge-spot-quest-sqlite (1Gi, local-path)

Subsections of Charge Spot Quest

Install (ArgoCD)

🚀Installation

Environment
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 `charge` DNS A record

Details
# zone 72602.space, RR charge, type A, value 47.110.67.161, TTL 600
# create only when the matching enabled record is absent

2.prepare `charge-spot-quest-argocd.yaml`

Details
git -C /home/aaron/Ops/docs fetch origin main
git -C /home/aaron/Ops/docs \
  show origin/main:manifests/charge-spot-quest-argocd.yaml >/dev/null

argocd app get ops-docs --hard-refresh
argocd app sync ops-docs --revision main
argocd app wait ops-docs --sync --timeout 300

kubectl wait --for=jsonpath='{.status.phase}'=Active \
  namespace/charge-spot --timeout=120s

The parent ops-docs Application reads the manifests path and creates the child Application. The child creates namespace charge-spot through CreateNamespace=true. SQLite is enabled; bundled and external PostgreSQL stay off.

3.prepare `charge-spot-dingtalk`

Details
kubectl -n charge-spot create secret generic charge-spot-dingtalk \
  --from-literal=webhook_url='https://oapi.dingtalk.com/robot/send?access_token=<replace-me>' \
  --from-literal=sec_secret='SEC<replace-me>' \
  --from-literal=revoke_secret="$(openssl rand -hex 32)"

Create the Secret on the cluster only. GitOps values set dingtalk.enabled, dingtalk.existingSecret=charge-spot-dingtalk, and dingtalk.publicBaseUrl=https://charge.72602.space. Do not commit webhook, SEC, or revoke tokens.

4.sync by argocd

Details
argocd app get charge-spot-quest --hard-refresh
argocd app sync charge-spot-quest
argocd app wait charge-spot-quest --sync --health --timeout 600

5.verify

Details
kubectl -n argocd get application charge-spot-quest \
  -o jsonpath='{.spec.source.repoURL}{"\n"}{.spec.source.path}{"\n"}{.spec.source.targetRevision}{"\n"}'

kubectl -n charge-spot get deployment charge-spot-quest \
  -o jsonpath='{range .spec.template.spec.containers[*]}{.name}{"="}{.image}{"\n"}{end}'

kubectl -n charge-spot rollout status deployment/charge-spot-quest --timeout=600s
kubectl -n charge-spot get pods,svc,ingress,pvc
kubectl -n charge-spot get certificate
kubectl -n charge-spot get pods -l app.kubernetes.io/component=postgresql
kubectl -n charge-spot get secret charge-spot-dingtalk \
  -o go-template='{{range $k,$v := .data}}{{$k}}{{"\n"}}{{end}}'
kubectl -n charge-spot get deployment charge-spot-quest \
  -o jsonpath='{range .spec.template.spec.containers[0].env[*]}{.name}{"\n"}{end}'

curl -fsS https://charge.72602.space/health
curl -fsS https://charge.72602.space/readyz
curl -fsS -o /dev/null -w '%{content_type}\n' https://charge.72602.space/
curl -fsS https://charge.72602.space/api/spots >/dev/null

Expected release values: chart charge-spot-quest version 0.1.15 and image ghcr.io/aaronyang0628/charge-spot-quest@sha256:31707edea46707434595c091cf6bdd4da0c6cb652f9831f8feccddda65ada1c2 (upstream did not publish a 0.1.15 GHCR tag; the digest pins the built content, also available as sha-3efdcf1). Ingress / returns text/html. PVC charge-spot-quest-sqlite is Bound at 1Gi. TLS certificate charge.72602.space-tls should be Ready with expiry 2026-12-14T06:20:17Z.

📦Rollback Guidance

If a deployment must be reverted, create a reviewed Git revert for manifests/charge-spot-quest-argocd.yaml, push it, and sync the parent application. The SQLite PVC and TLS certificate are not deleted by rollback.

cd /home/aaron/Ops/docs
git fetch origin main
git revert --no-edit 9a15bea
git push origin main
argocd app sync ops-docs --revision main
argocd app wait ops-docs --sync --health --timeout 300