ArgoCD Configuration
After installing the ArgoPlane Helm chart, you need to configure ArgoCD to route extension requests, mount custom styles, and load UI bundles. The chart deploys backends and generates ConfigMaps with all the config you need. This page walks through wiring it up.
How ArgoCD extensions work
ArgoCD extensions have three layers:
- UI bundle (JavaScript): registers tabs, panels, or pages via
window.extensionsAPI. ArgoCD loads any file matchingextension*.jsfrom/tmp/extensions/inside the argocd-server pod. - Proxy routing (
argocd-cm): maps/extensions/<name>/*requests to a backend service URL. - RBAC (
argocd-rbac-cm): grants roles permission to invoke specific extensions.
The Helm chart handles layer 2 and 3 via ConfigMaps. Layer 1 (UI bundles) needs an init container or sidecar on argocd-server.
Step 1: Enable proxy extensions
Tell ArgoCD to enable the proxy extension mechanism:
kubectl -n argocd patch cm argocd-cmd-params-cm --type merge
-p '{"data":{"server.enable.proxy.extension":"true"}}' Step 2: Add proxy routing
The chart generates argoplane-proxy-config with the correct routing entries. Merge them into argocd-cm:
kubectl -n argocd patch cm argocd-cm --type merge -p '{
"data": {
"extension.config.metrics": "services:\n- url: http://argoplane-metrics-backend.argocd.svc:8080\n",
"extension.config.backups": "services:\n- url: http://argoplane-backups-backend.argocd.svc:8081\n",
"extension.config.networking": "services:\n- url: http://argoplane-networking-backend.argocd.svc:8082\n",
"extension.config.logs": "services:\n- url: http://argoplane-logs-backend.argocd.svc:8083\n",
"extension.config.vulnerabilities": "services:\n- url: http://argoplane-vulnerabilities-backend.argocd.svc:8084\n",
"extension.config.events": "services:\n- url: http://argoplane-events-backend.argocd.svc:8085\n"
}
}' Each entry routes /extensions/<name>/* to the corresponding backend service. ArgoCD validates the user’s auth token before proxying.
Step 3: Configure RBAC
ArgoCD v3 requires explicit RBAC for extensions. The chart generates argoplane-rbac-config with policies. View them:
kubectl -n argocd get cm argoplane-rbac-config
-o jsonpath='{.data.argoplane-policy.csv}' Add the output to your argocd-rbac-cm ConfigMap’s policy.csv field:
p, role:admin, extensions, invoke, metrics, allow
p, role:admin, extensions, invoke, backups, allow
p, role:admin, extensions, invoke, networking, allow
p, role:admin, extensions, invoke, logs, allow
p, role:admin, extensions, invoke, vulnerabilities, allow
p, role:admin, extensions, invoke, events, allow
p, role:developer, extensions, invoke, metrics, allow
p, role:developer, extensions, invoke, backups, allow
p, role:developer, extensions, invoke, logs, allow
p, role:developer, extensions, invoke, vulnerabilities, allow
p, role:developer, extensions, invoke, events, allow Step 4: Load UI extension bundles
ArgoCD discovers UI extensions by scanning /tmp/extensions/ for files matching extension*.js. The recommended approach for production is an init container that copies bundles from a ConfigMap or OCI image.
Option A: Init container with ConfigMap (recommended)
Package your built extension bundles into a ConfigMap, then use an init container to copy them into the shared /tmp/extensions/ volume.
1. Create a ConfigMap from the built bundles:
kubectl -n argocd create configmap argoplane-ui-extensions
--from-file=extension-metrics.js=extensions/metrics/ui/dist/extension-metrics.js
--from-file=extension-backups.js=extensions/backups/ui/dist/extension-backups.js
--from-file=extension-networking.js=extensions/networking/ui/dist/extension-networking.js
--dry-run=client -o yaml | kubectl apply --server-side -f - 2. Patch argocd-server with an init container and shared volume:
kubectl -n argocd patch deployment argocd-server --type json -p '[
{
"op": "add",
"path": "/spec/template/spec/volumes/-",
"value": {
"name": "argoplane-extensions",
"configMap": {
"name": "argoplane-ui-extensions"
}
}
},
{
"op": "add",
"path": "/spec/template/spec/initContainers",
"value": [{
"name": "copy-argoplane-extensions",
"image": "busybox:1.36",
"command": ["sh", "-c",
"cp /extensions-src/*.js /tmp/extensions/"
],
"volumeMounts": [
{
"name": "argoplane-extensions",
"mountPath": "/extensions-src",
"readOnly": true
},
{
"name": "extensions",
"mountPath": "/tmp/extensions"
}
]
}]
}
]' Why an init container instead of a direct volume mount? ArgoCD expects files directly in /tmp/extensions/, but ConfigMap volume mounts create a directory structure with symlinks. The init container flattens the files into the expected location. It also allows combining extensions from multiple sources.
Option B: Init container with OCI image
For production, use the pre-built ArgoPlane UI extensions image as an init container. The image contains all UI bundles and a script that selectively copies only the ones you enable.
spec:
template:
spec:
initContainers:
- name: argoplane-extensions
image: ghcr.io/natrontech/argoplane-ui-extensions:v0.1.0
env:
- name: ENABLED_EXTENSIONS
value: "metrics,backups,argoplane"
volumeMounts:
- name: extensions
mountPath: /tmp/extensions
containers:
- name: argocd-server
volumeMounts:
- name: extensions
mountPath: /tmp/extensions
volumes:
- name: extensions
emptyDir: {} The ENABLED_EXTENSIONS env var is a comma-separated list of extension names. Only matching UI bundles (extension-<name>.js) are copied to /tmp/extensions/. If you omit the env var entirely, all bundles are copied (backwards compatible).
This approach is cleaner for CI/CD pipelines: build once, tag with version, deploy via image reference.
Loading only enabled UI bundles
When you disable an extension backend via extensions.<name>.enabled: false in the Helm chart, the proxy routing, RBAC, and backend Deployment are all skipped. However, the UI bundle is separate: it lives in the init container image and gets loaded into ArgoCD independently.
Without the ENABLED_EXTENSIONS filter, disabled extensions still show tabs and panels in ArgoCD. They appear broken (empty or error state) because there’s no backend to serve data. To prevent this, set ENABLED_EXTENSIONS on the init container to match your enabled backends.
For example, if you only enable metrics and backups:
extensions:
metrics:
enabled: true
backups:
enabled: true
networking:
enabled: false
logs:
enabled: false
vulnerabilities:
enabled: false
events:
enabled: false Set the init container env to:
env:
- name: ENABLED_EXTENSIONS
value: "metrics,backups,argoplane" Always include argoplane in the list. It’s the consolidation extension that combines all enabled extension tabs into a single unified “ArgoPlane” tab. If you use branding, also add argoplane-links.
Option C: kubectl cp (development only)
For local development, copy bundles directly into the running pod:
ARGOCD_POD=$(kubectl -n argocd get pods
-l app.kubernetes.io/name=argocd-server
-o jsonpath='{.items[0].metadata.name}')
kubectl exec -n argocd $ARGOCD_POD -- mkdir -p /tmp/extensions
for ext in metrics backups networking logs vulnerabilities events; do
kubectl cp extensions/$ext/ui/dist/extension-$ext.js
argocd/$ARGOCD_POD:/tmp/extensions/extension-$ext.js
done Step 5: Custom styles (optional)
The Helm chart can deploy a ConfigMap with the ArgoPlane CSS theme and login wallpaper. Enable it with argocd.styles.enabled=true.
1. Tell ArgoCD where to find the CSS:
kubectl -n argocd patch cm argocd-cm --type merge
-p '{"data":{"ui.cssurl":"./custom/argoplane.css"}}' 2. Mount the styles ConfigMap into argocd-server:
kubectl -n argocd patch deployment argocd-server --type json -p '[
{
"op": "add",
"path": "/spec/template/spec/volumes/-",
"value": {
"name": "argoplane-styles",
"configMap": { "name": "argoplane-styles" }
}
},
{
"op": "add",
"path": "/spec/template/spec/containers/0/volumeMounts/-",
"value": {
"name": "argoplane-styles",
"mountPath": "/shared/app/custom"
}
}
]' ArgoCD serves files from /shared/app/custom/ at the relative URL ./custom/. The CSS transforms ArgoCD’s UI with ArgoPlane’s pixel-art aesthetic: flat design, warm grays, pastel orange accent.
Step 6: Branding (optional)
Enable argocd.branding.enabled=true to deploy the branding JS extension. Mount it:
kubectl -n argocd patch deployment argocd-server --type json -p '[
{
"op": "add",
"path": "/spec/template/spec/volumes/-",
"value": {
"name": "argoplane-branding",
"configMap": { "name": "argoplane-links" }
}
},
{
"op": "add",
"path": "/spec/template/spec/containers/0/volumeMounts/-",
"value": {
"name": "argoplane-branding",
"mountPath": "/tmp/extensions/branding",
"readOnly": true
}
}
]' Step 7: Restart argocd-server
After all patches:
kubectl -n argocd rollout restart deployment argocd-server
kubectl -n argocd rollout status deployment argocd-server Complete example: Kustomize overlay
For production, manage all ArgoCD patches as a Kustomize overlay instead of imperative kubectl commands.
Create argocd-patches/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: argocd
patches:
# Enable proxy extensions
- target:
kind: ConfigMap
name: argocd-cmd-params-cm
patch: |
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cmd-params-cm
data:
server.enable.proxy.extension: "true"
# Add proxy routing + CSS URL
- target:
kind: ConfigMap
name: argocd-cm
patch: |
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
data:
ui.cssurl: "./custom/argoplane.css"
extension.config.metrics: |
services:
- url: http://argoplane-metrics-backend.argocd.svc:8080
extension.config.backups: |
services:
- url: http://argoplane-backups-backend.argocd.svc:8081
extension.config.networking: |
services:
- url: http://argoplane-networking-backend.argocd.svc:8082
extension.config.logs: |
services:
- url: http://argoplane-logs-backend.argocd.svc:8083
extension.config.vulnerabilities: |
services:
- url: http://argoplane-vulnerabilities-backend.argocd.svc:8084
extension.config.events: |
services:
- url: http://argoplane-events-backend.argocd.svc:8085
# RBAC for extensions
- target:
kind: ConfigMap
name: argocd-rbac-cm
patch: |
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
data:
policy.csv: |
p, role:admin, extensions, invoke, metrics, allow
p, role:admin, extensions, invoke, backups, allow
p, role:admin, extensions, invoke, networking, allow
p, role:admin, extensions, invoke, logs, allow
p, role:admin, extensions, invoke, vulnerabilities, allow
p, role:admin, extensions, invoke, events, allow
p, role:developer, extensions, invoke, metrics, allow
p, role:developer, extensions, invoke, backups, allow
p, role:developer, extensions, invoke, logs, allow
p, role:developer, extensions, invoke, vulnerabilities, allow
p, role:developer, extensions, invoke, events, allow
policy.default: role:admin
# Patch argocd-server with init container + volume mounts
- target:
kind: Deployment
name: argocd-server
patch: |
apiVersion: apps/v1
kind: Deployment
metadata:
name: argocd-server
spec:
template:
spec:
initContainers:
- name: argoplane-extensions
image: ghcr.io/natrontech/argoplane-ui-extensions:v0.1.0
env:
- name: ENABLED_EXTENSIONS
value: "metrics,backups,networking,logs,vulnerabilities,events,argoplane"
volumeMounts:
- name: extensions
mountPath: /tmp/extensions
containers:
- name: argocd-server
volumeMounts:
- name: argoplane-styles
mountPath: /shared/app/custom
- name: argoplane-branding
mountPath: /tmp/extensions/branding
readOnly: true
volumes:
- name: argoplane-styles
configMap:
name: argoplane-styles
- name: argoplane-branding
configMap:
name: argoplane-links
- name: extensions
emptyDir: {} Apply with:
kubectl apply -k argocd-patches/ Complete example: ArgoCD Application (GitOps)
Deploy ArgoPlane and its ArgoCD configuration together as a single ArgoCD Application:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: argoplane
namespace: argocd
spec:
project: default
sources:
# ArgoPlane Helm chart (backends, ConfigMaps)
- repoURL: https://github.com/natrontech/argoplane
path: deploy/helm/argoplane
targetRevision: main
helm:
valueFiles:
- values-prod.yaml
# ArgoCD patches (proxy config, RBAC, init containers)
- repoURL: https://github.com/your-org/platform-config
path: argocd-patches
targetRevision: main
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true ArgoCD v3 changes
Key changes in ArgoCD v3 that affect extension configuration:
| Change | Impact |
|---|---|
| Fine-grained RBAC | update/delete on applications no longer cascades to sub-resources. Grant update/* and delete/* explicitly if needed. |
| Logs RBAC enforced | Users need explicit logs, get permission. |
| Extensions require RBAC | Every extension needs p, role:<role>, extensions, invoke, <name>, allow. |
| Annotation-based tracking | Resource tracking uses annotations by default, not labels. |
| Health in Redis | Resource health is stored in Redis, not in Application status. |