Installation Guide¶
There are three Helm charts, meant to be installed in order:
| Chart | Purpose |
|---|---|
helm/kube-copilot-agent |
The operator (CRDs + controller) |
helm/github-copilot-agent |
A GitHub Copilot agent instance |
helm/kube-copilot-ui |
The web UI |
Prerequisites¶
- kubectl v1.20+
- Helm v3.10+
- Access to a Kubernetes or OpenShift cluster
- A GitHub account with Copilot access
- A GitHub Personal Access Token (PAT) with
copilotscope
Step 1 — Install the Operator¶
helm upgrade --install kube-copilot-agent ./helm/kube-copilot-agent \
--namespace kube-copilot-agent \
--create-namespace
If the namespace already exists:
helm upgrade --install kube-copilot-agent ./helm/kube-copilot-agent \
--namespace kube-copilot-agent \
--set createNamespace=false
Note
The namespace hook runs only on helm install, not on helm upgrade. This means upgrading the chart will never delete or recreate the operator namespace and its contents.
Key operator values:
| Value | Default | Description |
|---|---|---|
namespace |
kube-copilot-agent |
Namespace to deploy into |
createNamespace |
true |
Create the namespace as part of the chart |
image.repository |
quay.io/gfontana/kube-copilot-agent |
Operator image |
image.tag |
v1.0 |
Operator image tag |
image.pullPolicy |
Always |
Image pull policy |
agentImage.repository |
quay.io/gfontana/kube-github-copilot-agent-server |
Default agent image |
agentImage.tag |
v1.0 |
Default agent image tag |
replicaCount |
1 |
Operator replicas |
installCRDs |
true |
Install CRDs with the chart |
rbac.create |
true |
Create RBAC resources |
leaderElect |
true |
Enable leader election |
Step 2 — Create Credentials¶
Create a secret with your GitHub PAT:
kubectl create secret generic github-token \
--from-literal=GITHUB_TOKEN=<your-pat> \
-n kube-copilot-agent
Optionally, provide a kubeconfig so the agent can inspect your cluster:
kubectl create secret generic cluster-kubeconfig \
--from-file=config=<path-to-kubeconfig> \
-n kube-copilot-agent
ServiceAccount-Based Permissions¶
Instead of supplying a kubeconfig secret manually, you can let the operator provision RBAC resources automatically. Set spec.rbac on the agent CR (or use the rbac Helm values) to create a dedicated ServiceAccount, Role/ClusterRole, bindings, and a generated kubeconfig Secret — all with the least-privilege rules you specify.
See Configuration — ServiceAccount-Based Permissions for the full reference and examples.
Note
spec.rbac and spec.kubeconfigSecretRef are mutually exclusive; set only one.
Step 3 — Deploy the GitHub Copilot Agent¶
The github-copilot-agent chart creates the KubeCopilotAgent CR, a GitHub token Secret, and ConfigMaps for skills and AGENT.md. Default skills (monitor, deploy, troubleshoot) and a SysAdmin persona are included out of the box.
Minimal install (uses built-in skills and AGENT.md):
helm upgrade --install my-agent ./helm/github-copilot-agent \
--namespace kube-copilot-agent \
--set githubToken.value=<your-pat>
With an existing token secret:
helm upgrade --install my-agent ./helm/github-copilot-agent \
--namespace kube-copilot-agent \
--set githubToken.existingSecret=github-token
With a kubeconfig secret (so the agent can talk to the cluster):
helm upgrade --install my-agent ./helm/github-copilot-agent \
--namespace kube-copilot-agent \
--set githubToken.existingSecret=github-token \
--set kubeconfigSecretRef=cluster-kubeconfig
Custom skills and AGENT.md via a values file:
# my-agent-values.yaml
name: my-agent
githubToken:
existingSecret: github-token
kubeconfigSecretRef: cluster-kubeconfig
createSkillsConfigMap: true
skillsContent:
my-skill.md: |
---
name: my-skill
description: Does something useful
---
# My Skill
...
createAgentConfigMap: true
agentContent:
AGENT.md: |
# My Agent
You are a helpful Kubernetes assistant.
helm upgrade --install my-agent ./helm/github-copilot-agent \
--namespace kube-copilot-agent \
-f my-agent-values.yaml
Key agent values:
| Value | Default | Description |
|---|---|---|
name |
github-copilot-agent |
Name of the KubeCopilotAgent CR |
namespace |
kube-copilot-agent |
Target namespace |
githubToken.value |
"" |
PAT value (creates a new Secret) |
githubToken.existingSecret |
"" |
Reference an existing Secret |
githubToken.secretKey |
GITHUB_TOKEN |
Key inside the secret |
image |
"" |
Override the agent container image |
storageSize |
1Gi |
PVC size for session history |
kubeconfigSecretRef |
"" |
Existing Secret name with a kubeconfig; mutually exclusive with rbac |
rbac |
{} |
ServiceAccount-based RBAC config (serviceAccountName, rules, clusterRules); mutually exclusive with kubeconfigSecretRef — see ServiceAccount-Based Permissions |
createSkillsConfigMap |
true |
Create a skills ConfigMap from skillsContent |
skillsConfigMap |
"" |
Reference an existing skills ConfigMap |
createAgentConfigMap |
true |
Create an AGENT.md ConfigMap from agentContent |
agentConfigMap |
"" |
Reference an existing AGENT.md ConfigMap |
Wait for the agent to become ready:
Step 4 — Deploy the Web UI¶
On OpenShift (creates a Route with TLS):
helm upgrade --install kube-copilot-ui ./helm/kube-copilot-ui \
--namespace kube-copilot-agent \
--set route.enabled=true
Then get the URL:
On plain Kubernetes (port-forward):
kubectl port-forward svc/kube-copilot-ui 8080:80 -n kube-copilot-agent
# Open: http://localhost:8080
Key UI values:
| Value | Default | Description |
|---|---|---|
namespace |
kube-copilot-agent |
Namespace to deploy into |
image.repository |
quay.io/gfontana/kube-copilot-agent-ui |
UI image |
image.tag |
v1.0 |
UI image tag |
operatorNamespace |
kube-copilot-agent |
Namespace the UI watches for agents |
commandTimeout |
300 |
Seconds to wait for an agent response |
imagePullSecret |
"" |
Pull secret name (for private registries) |
rbac.create |
true |
Create Role/RoleBinding |
route.enabled |
false |
Create an OpenShift Route |
route.timeout |
360s |
HAProxy timeout for SSE streams |
Security
The Web UI pod runs with hardened security contexts: runAsNonRoot: true, seccompProfile: RuntimeDefault, allowPrivilegeEscalation: false, and all Linux capabilities dropped. No additional configuration is required.
Step 5 — (Optional) Deploy the OpenShift Console Plugin¶
If you're running on OpenShift, you can embed the KubeCopilot UI directly inside the OpenShift Web Console as a dynamic plugin.
graph LR
subgraph ocp["OpenShift Console"]
nav["🧭 Navigation<br/><sub>Home → KubeCopilot AI</sub>"]
page["📄 Plugin Page<br/><sub>React component</sub>"]
end
subgraph plugin["Console Plugin Pod"]
nginx["nginx<br/><sub>serves JS/CSS assets</sub>"]
end
subgraph webui["Web UI Pod"]
fastapi["FastAPI<br/><sub>chat API + static HTML</sub>"]
end
nav --> page
page --> |"iframe ?embedded=true"| fastapi
ocp --> |"module federation"| nginx
style ocp fill:#1a1a2e,stroke:#00bcd4,color:#e0e0e0
style plugin fill:#16213e,stroke:#e94560,color:#e0e0e0
style webui fill:#0f3460,stroke:#ffc107,color:#e0e0e0
Build the plugin image:
cd openshift-console-plugin
podman build -t quay.io/yourorg/kube-copilot-console-plugin:latest .
podman push quay.io/yourorg/kube-copilot-console-plugin:latest
Install via Helm:
helm upgrade --install kube-copilot-console-plugin ./helm/kube-copilot-console-plugin \
--namespace kube-copilot-agent \
--set plugin.image=quay.io/yourorg/kube-copilot-console-plugin:latest \
--set webUI.serviceName=kube-copilot-ui \
--set webUI.servicePort=8000
After installation, refresh the OpenShift Console — a new "KubeCopilot AI" nav item appears under Home in both the Administrator and Developer perspectives.
If plugin.jobs.patchConsoles.enabled is false, enable the plugin manually:
oc patch consoles.operator.openshift.io cluster --type=json \
-p '[{"op": "add", "path": "/spec/plugins/-", "value": "kube-copilot-console-plugin"}]'
Verify the plugin is registered:
How it works:
- A
ConsolePluginCR registers the plugin with the OpenShift Console operator - A post-install Job patches the Console operator config to enable the plugin
- The plugin page loads the existing Web UI inside an iframe with
?embedded=true - In embedded mode, the Web UI hides its own header and sizes itself to fill the Console content area; the plugin uses a
ResizeObserveron the main content element for accurate layout when the sidebar is toggled, plus aMutationObserverfor class/style changes - Responsive sidebar: in embedded mode the sidebar width narrows to 180 px at ≤ 900 px viewport width and is hidden entirely at ≤ 600 px to maximise the chat area in small frames
- Theme sync: the plugin forwards OpenShift Console dark/light mode changes to the iframe via
postMessage
Key Helm values:
| Value | Default | Description |
|---|---|---|
plugin.image |
(required) | Console plugin container image |
plugin.name |
kube-copilot-console-plugin |
Name of the ConsolePlugin CR |
plugin.replicas |
2 |
Number of plugin pod replicas |
plugin.port |
9443 |
HTTPS port for nginx (auto-TLS via serving cert) |
plugin.jobs.patchConsoles.enabled |
true |
Auto-enable the plugin in the OpenShift Console via a post-install Job |
webUI.serviceName |
kube-copilot-ui |
Name of the KubeCopilot Web UI service |
webUI.serviceNamespace |
(release namespace) | Namespace of the Web UI service |
webUI.servicePort |
8000 |
Port of the Web UI service |