How to Migrate From the Archived Kubernetes Dashboard to Headlamp
Kubernetes Dashboard is now archived. This step by step tutorial migrates a cluster to Headlamp instead: desktop and in-cluster installs, RBAC-aware authentication, deploying and debugging a real...
Kubernetes Dashboard, the web UI that generations of cluster operators reached for with kubectl proxy or a quick port-forward, is now archived. Its own GitHub repository carries a notice that the project has no active maintainers and points users toward a replacement: Headlamp, a UI that recently moved under the Kubernetes SIG UI umbrella. This tutorial walks through the full move, from your first kubectl sanity check to safely uninstalling Dashboard, using the official Kubernetes Blog migration guide, the Headlamp project documentation, and the Kubernetes Dashboard repository itself as primary references. Every command below is verified against those sources and labeled with the tool and version context it assumes.
Table Of Content
- Prerequisites
- What Actually Changes When You Move From Dashboard to Headlamp
- How Kubernetes Dashboard Works
- How Headlamp Works
- Why This Migration Matters Right Now
- Step 1: Confirm kubectl and Your Kubeconfig Actually Work
- Step 2: Choose a Rollout Plan and Where Headlamp Will Run
- Parallel Rollout or Cutover
- Desktop, In-Cluster, or Both
- Step 3: Install Headlamp on Your Desktop
- Windows
- macOS
- Linux
- Verify the Desktop Install
- Step 4: Install Headlamp In-Cluster for Shared Access
- Add the Helm Repository and Install
- Verify the Deployment
- Access It With Port-Forwarding First
- Expose It for the Whole Team (Optional)
- Step 5: Set Up Authentication That Respects Your RBAC
- Desktop: Nothing Extra to Configure
- In-Cluster, Option A: A Service Account Token
- In-Cluster, Option B: OIDC Single Sign-On
- Step 6: Get Oriented Inside Headlamp
- Step 7: Deploy and Debug a Workload
- Generate and Apply a Test Deployment
- Read Logs
- Exec Into the Pod
- Check Metrics
- Read Events When Something Breaks
- Step 8: Retire Kubernetes Dashboard
- Confirm Headlamp Covers Your Needs First
- Uninstall Dashboard
- Clean Up Leftover Access
- Common Mistakes and Gotchas
- Verify the Whole Migration Worked
- Next Steps
You do not need any prior Headlamp experience to follow this. You do need a working Kubernetes cluster and basic comfort with kubectl. By the end, you will have Headlamp running (on your desktop, in your cluster, or both), a working login path that respects your existing RBAC permissions, and a clean removal of the old Dashboard.
Prerequisites
- A Kubernetes cluster you can already reach with
kubectl: a local cluster like minikube or kind, or a managed cluster such as EKS, AKS, or GKE. Examples below use generic commands that work the same way regardless of where the cluster runs. kubectlinstalled and pointed at that cluster with a working kubeconfig file. If you are not sure what a kubeconfig is: it is the file (usually~/.kube/config) that stores the cluster address, certificate, and credentialskubectluses to authenticate every request. Headlamp reads the same file.- Helm 3 installed, only if you plan to install Headlamp inside your cluster (the in-cluster path in this guide). Desktop-only installs do not need Helm.
- Enough RBAC permission in the cluster to create namespaces, service accounts, and cluster role bindings, if you are installing in-cluster. Read-only access is enough if you only want the desktop app.
- Basic familiarity with running commands in a terminal. No prior Helm or Headlamp experience assumed; both are explained as they come up.
What Actually Changes When You Move From Dashboard to Headlamp
Both tools show you what is running in a cluster, but the way they get their permissions and where they run is different enough that it is worth understanding before you install anything.
How Kubernetes Dashboard Works
Dashboard is a web application that lives entirely inside your cluster. You install it with Helm, it usually serves one cluster at a time, and you typically reach it through kubectl port-forward or an ingress. Logging in means pasting a bearer token, most often one generated from a Kubernetes service account. Creating a resource is done through a form: pick an image, set replicas, choose a service type, and Dashboard builds the underlying object for you.
How Headlamp Works
Headlamp behaves more like a graphical kubectl. It can run on your desktop or inside a cluster, and either way it authenticates the same way your other Kubernetes tools do: on desktop it reads your kubeconfig directly, and in-cluster it uses a Kubernetes ServiceAccount and follows whatever RBAC rules that account has. One installation can show multiple clusters at once, side by side, instead of one Dashboard per cluster. Creating a resource means writing or pasting YAML rather than filling in a form, and the interface adds a visual Map View that shows how resources like Deployments, ReplicaSets, Pods, and Services connect to each other, on top of the familiar list views.
Why This Migration Matters Right Now
This is not a matter of taste between two similar tools. The Kubernetes Dashboard repository’s README states plainly that the project is archived and no longer maintained “due to lack of active maintainers and contributors,” and recommends Headlamp by name as the successor, noting that Headlamp was recently moved under the Kubernetes SIG UI. An archived project still runs, but it will not receive security patches, bug fixes, or support for new Kubernetes API versions going forward. If Dashboard is anywhere in your cluster today, this is a “when,” not an “if.”
Step 1: Confirm kubectl and Your Kubeconfig Actually Work
Before installing anything, prove that the identity you will hand to Headlamp actually works. Run:
# Context: any terminal with kubectl installed, targeting the cluster you plan to migrate.
kubectl config current-context
You should see the name of a cluster context printed back, for example minikube for a local cluster, or a longer provider-specific identifier for a managed one (EKS often shows a full cluster ARN, while GKE and AKS use their own naming schemes). That confirms kubectl has a context selected at all. Next, prove that context can actually talk to the API server:
# Context: same terminal, same kubeconfig.
kubectl get nodes
What this does and why it matters: this lists every node in the cluster and requires a working connection plus valid credentials, so a successful result here means the exact same kubeconfig Headlamp will use is already good. If you cannot list nodes because your account is scoped down, try a namespace you know you have access to instead: kubectl get pods -n <namespace>. Either command succeeding is enough proof that Headlamp, which reuses this same file, will be able to authenticate too.
Step 2: Choose a Rollout Plan and Where Headlamp Will Run
Two decisions shape everything that follows, and it is worth making them deliberately instead of by default.
Parallel Rollout or Cutover
A parallel rollout installs Headlamp alongside the existing Dashboard, lets your team try it for a while, and only removes Dashboard once everyone is comfortable. A cutover installs Headlamp, immediately updates docs and bookmarks to point at it, and removes Dashboard soon after. For any cluster more than one person touches, a parallel rollout is safer: it gives you a rollback path if something in your specific RBAC setup behaves differently than expected, and this tutorial follows that path, ending with Dashboard removal only as the final step.
Desktop, In-Cluster, or Both
Headlamp supports two deployment models and you can use either or both:
- Desktop is the fastest way to start. It installs as a normal application, uses your existing kubeconfig, needs no cluster resources, and gives you multi-cluster support immediately since it just reads whichever kubeconfig contexts you already have.
- In-cluster deploys Headlamp as a workload inside the cluster, managed with Helm like any other application, and reachable at a shared URL. This is the model to pick when a whole team needs one consistent, browser-accessible UI rather than everyone running their own desktop copy.
This tutorial covers both, starting with desktop since it is the quickest way to confirm Headlamp works with your credentials before committing to a shared in-cluster deployment.
Step 3: Install Headlamp on Your Desktop
Pick the section for your operating system. All three are verified against the Headlamp desktop installation docs.
Windows
Headlamp publishes to both Winget and Chocolatey. Using Winget:
# Context: Windows PowerShell, Winget already installed (bundled with modern Windows).
winget install headlamp
Or, if you use Chocolatey instead:
# Context: Windows PowerShell, Chocolatey already installed.
choco install headlamp
Either package manager can also upgrade Headlamp later with winget upgrade headlamp or choco upgrade headlamp. If you would rather not use a package manager, a direct .exe installer is available from the project’s GitHub releases page; that path has no auto-upgrade, so you would reinstall manually for updates.
macOS
The supported path is Homebrew:
# Context: macOS Terminal, Homebrew already installed.
brew install --cask headlamp
What this does and why it matters: the --cask flag tells Homebrew this is a GUI application bundle, not a command-line formula, so it gets installed into /Applications the way a normal Mac app would. Upgrading later is brew upgrade headlamp. A .dmg download is also available directly from GitHub releases for anyone who prefers not to use Homebrew, but Homebrew’s version tracks upgrades for you automatically.
Linux
Headlamp ships as a Flatpak, an AppImage, and a tarball. Flatpak is the simplest to keep updated:
# Context: Linux desktop with Flatpak installed and the Flathub remote already added.
flatpak install flathub io.kinvolk.Headlamp
Launch it from your desktop’s application menu, or from the terminal with flatpak run io.kinvolk.Headlamp. If your kubeconfig relies on an external authentication plugin, such as aws, az, or gcloud for a managed cluster’s exec-based credentials, Flatpak’s sandbox can block Headlamp from calling out to those binaries. If cluster login fails specifically for a managed cluster but works for a local one, grant the sandbox permission to reach outside tools before troubleshooting further:
# Context: run once, before launching Headlamp, only if kubeconfig uses an exec-based credential plugin.
sudo flatpak override --talk-name=org.freedesktop.Flatpak io.kinvolk.Headlamp
Verify the Desktop Install
Open Headlamp. You should see a cluster selector populated with whatever contexts already exist in your kubeconfig. Pick one, open a namespace you know you can access, and confirm you can see its workloads. If a namespace looks empty when you know it has pods, double-check you selected the correct cluster context; Headlamp respects your RBAC, so it will also silently show nothing for a namespace your current identity cannot read, which looks identical to an empty namespace at a glance.
Step 4: Install Headlamp In-Cluster for Shared Access
Skip this step if desktop-only is enough for your team. For a shared, browser-accessible instance, the official in-cluster docs recommend Helm.
Add the Helm Repository and Install
This tutorial installs into a dedicated headlamp namespace so it is easy to inspect and remove later, rather than mixing it into kube-system:
# Context: any terminal with helm 3 and kubectl configured for the target cluster.
kubectl create namespace headlamp
helm repo add headlamp https://kubernetes-sigs.github.io/headlamp/
helm repo update
helm install headlamp headlamp/headlamp --namespace headlamp
What this does and why it matters: helm repo add registers Headlamp’s official chart repository locally so Helm knows where to fetch the chart definition from; helm repo update refreshes Helm’s local cache of what versions are available. The final command installs a release named headlamp from the headlamp/headlamp chart into the namespace you just created. If you would rather follow the exact quickstart shown in the official docs, it installs into kube-system with the release name my-headlamp instead; either namespace works, this guide just keeps it separate from Kubernetes’ own system namespace for a cleaner uninstall later.
Verify the Deployment
# Context: same terminal, right after the helm install command above.
kubectl get pods -n headlamp
kubectl get svc -n headlamp
The pod should reach Running status within a minute or so on most clusters, and the service list should show a headlamp ClusterIP service on port 80. If the pod stays in Pending, check kubectl describe pod -n headlamp for scheduling errors; the most common cause on small clusters is insufficient CPU or memory for scheduling.
Access It With Port-Forwarding First
Before setting up anything permanent, confirm the service actually works:
# Context: same terminal, headlamp pod already Running.
kubectl port-forward -n headlamp svc/headlamp 8080:80
Open http://localhost:8080 in a browser. Seeing the Headlamp login screen confirms the deployment itself is healthy, independent of any ingress or DNS configuration you set up next.
Expose It for the Whole Team (Optional)
For lasting shared access, put Headlamp behind your existing ingress controller instead of leaving port-forward running. The exact ingress YAML depends on your ingress controller, but two things matter regardless of which one you use: terminate TLS (do not expose cluster UI credentials over plain HTTP), and if you plan to use OIDC login (covered next), make sure your ingress forwards the X-Forwarded-Proto header, since Headlamp uses it to build the correct https:// callback URL for the login flow.
Step 5: Set Up Authentication That Respects Your RBAC
Headlamp does not maintain its own separate user database. It authenticates through Kubernetes itself, which means the cluster’s RBAC rules, the same ones that control what kubectl can and cannot do for a given identity, apply identically inside Headlamp.
Desktop: Nothing Extra to Configure
On desktop, Headlamp already authenticated when it read your kubeconfig in Step 3. There is no separate login step. If you keep multiple kubeconfig files instead of one merged file, point Headlamp at the right one with the KUBECONFIG environment variable, the same way you would for kubectl:
# Context: macOS/Linux shell, launching Headlamp from a terminal with a non-default kubeconfig path.
KUBECONFIG=/path/to/config headlamp
Multiple files at once work too: separate paths with : on macOS and Linux, or ; on Windows.
In-Cluster, Option A: A Service Account Token
This is the fastest way to log into an in-cluster Headlamp and matches the token-based login most Dashboard users are already used to. Per the official Headlamp authentication docs, create a service account:
# Context: kubectl with permission to create ServiceAccounts and ClusterRoleBindings.
kubectl -n kube-system create serviceaccount headlamp-admin
Grant it a role. The docs use cluster-admin as the simplest example, but treat that as a starting point for testing, not a production default; check the Kubernetes RBAC documentation if you want a narrower role scoped to specific namespaces or verbs instead:
# Context: same terminal, immediately after creating the service account.
kubectl create clusterrolebinding headlamp-admin --serviceaccount=kube-system:headlamp-admin --clusterrole=cluster-admin
Now generate the token. On Kubernetes 1.24 and later, service account tokens are no longer auto-created as long-lived Secrets, so you request one directly:
# Context: Kubernetes 1.24+. On older clusters, see the note below instead.
kubectl create token headlamp-admin -n kube-system
This prints a token string valid for a limited time by default. Paste it into Headlamp’s login prompt. On clusters older than 1.24, tokens are still stored in a Secret, so instead retrieve it with:
# Context: Kubernetes clusters older than 1.24 only.
export HEADLAMP_SECRET=$(kubectl get secrets --namespace kube-system -o custom-columns=":metadata.name" | grep "headlamp-admin-token")
kubectl get secret $HEADLAMP_SECRET --namespace kube-system --template={{.data.token}} | base64 --decode
In-Cluster, Option B: OIDC Single Sign-On
For shared production access, a per-person OIDC login is a better fit than one shared service account token, since it gives you per-user audit trails and lets you revoke one person’s access without breaking everyone else’s. Headlamp supports built-in OIDC configuration, which needs four things from your identity provider: a client ID, a client secret, an issuer URL, and optionally a list of scopes. Your identity provider also needs to allow Headlamp’s callback URL, which is always your Headlamp URL plus /oidc-callback, for example https://headlamp.example.com/oidc-callback. This is exactly where the X-Forwarded-Proto ingress setting from Step 4 matters: without it, Headlamp may generate an http:// callback instead of https://, and the identity provider will reject it as a mismatch. Full setup varies by identity provider, so treat this as a pointer to configure against your specific OIDC provider’s documentation rather than a copy-paste block.
Step 6: Get Oriented Inside Headlamp
Once you are logged in, the layout maps closely to what Dashboard users already know, organized into a few groups: Workloads for Pods, Deployments, StatefulSets, and Jobs; Network for Services and Ingress; Storage for PersistentVolumes and Claims; Configuration for ConfigMaps and Secrets; and Nodes for cluster infrastructure. Namespace filtering sits at the top of the screen, the same as in Dashboard.
Clicking into any resource shows its status, events, labels, annotations, and full YAML. If your RBAC role allows edits, you can change that YAML directly in the browser; if it does not, Headlamp shows the resource read-only, mirroring exactly what kubectl edit would allow or refuse for that same identity.
The one view with no real Dashboard equivalent is Map View, which draws the relationships between a Deployment, its ReplicaSets, its Pods, and any Services pointing at them as a connected diagram instead of separate lists. Reach for list views when you already know what you are looking for, and reach for Map View when you are trying to understand why something is broken and need to see how pieces connect at a glance.
Step 7: Deploy and Debug a Workload
This is the biggest behavior change from Dashboard. Dashboard let you fill in a form (image, replica count, service type) and built the object for you behind the scenes. Headlamp has no such wizard; you supply YAML directly. That is a deliberate design choice, not a missing feature: it matches how most teams actually run Kubernetes today, with manifests in Git and CI/CD applying them, and Headlamp is built for inspecting and debugging what those pipelines create rather than replacing them.
Generate and Apply a Test Deployment
If you want to try creating something by hand to see the flow, generate a safe, disposable YAML manifest instead of writing one from memory:
# Context: any terminal with kubectl configured; --dry-run=client means nothing is created yet, only YAML is printed.
kubectl create deployment nginx-demo --image=nginx --dry-run=client -o yaml > nginx-demo.yaml
Open nginx-demo.yaml in a text editor to see what a minimal Deployment actually looks like. In Headlamp, click Create, paste the file’s contents, review it, and click Apply. The Deployment appears in the Workloads list immediately. If the YAML has a mistake, Headlamp surfaces the same validation error the Kubernetes API itself would return, since it is submitting the manifest to the same API server kubectl apply would use.
Read Logs
Open Workloads → Pods, click the nginx-demo pod, and open the Logs tab. Logs stream live, which is useful during a rollout or an active incident. If the pod has more than one container, a selector lets you switch between them.
Exec Into the Pod
From the pod’s action menu, choose Terminal or Exec to open an interactive shell inside the container, the browser-based equivalent of kubectl exec -it. Like every other action in Headlamp, this follows RBAC: if your identity is not allowed to run kubectl exec against that pod, Headlamp will not offer the option either.
Check Metrics
CPU and memory graphs on pod and node views require metrics-server to already be installed in the cluster, exactly as they did in Dashboard. This is not a Headlamp bug: if metrics are missing, Headlamp shows a clear notice rather than a blank chart, and installing metrics-server separately (it is a standard, commonly pre-installed Kubernetes add-on) resolves it.
Read Events When Something Breaks
Every resource detail page has an events section showing warnings and errors tied to that Pod, Node, or Deployment. When a workload is stuck or crash-looping, this is usually the fastest place to find out why, often faster than jumping to logs first.
Step 8: Retire Kubernetes Dashboard
Only do this after your team has actually used Headlamp for real work and confirmed it covers what they need; that is the entire point of the parallel rollout from Step 2.
Confirm Headlamp Covers Your Needs First
Before removing anything, verify that the people who will lose Dashboard access can already do the following in Headlamp: reach the clusters they need, browse workloads across the namespaces they use, deploy with a pasted YAML manifest, view logs and events, and exec into a pod if their role allows it. If any of that is missing or broken for a specific user, it is almost always an RBAC scoping issue on their service account or OIDC identity, not a Headlamp limitation, since Headlamp only ever shows what the underlying Kubernetes credentials already permit.
Uninstall Dashboard
If Dashboard was installed with Helm, which is the only installation method the project supports as of its final releases, remove it with:
# Context: matches the standard "kubernetes-dashboard" release name and namespace used by Dashboard's official Helm chart.
helm uninstall kubernetes-dashboard -n kubernetes-dashboard
Confirm the workload is actually gone rather than just trusting the command’s exit status:
# Context: run a few seconds after the uninstall, once pod termination has had time to finish.
kubectl get pods -n kubernetes-dashboard
An empty list (or a “no resources found” message) confirms removal.
Clean Up Leftover Access
Dashboard installs typically create their own service accounts and role bindings. Review and remove anything that existed only to support Dashboard access, and update any internal documentation that still points teammates at old Dashboard URLs or port-forward instructions, so nobody follows a stale runbook back to a tool that no longer exists.
Common Mistakes and Gotchas
- Assuming a blank namespace view is a bug. It is usually RBAC doing exactly what it is supposed to: your current identity cannot read that namespace. Double-check with
kubectl auth can-i list pods -n <namespace>before troubleshooting Headlamp itself. - Expecting metrics to appear with no
metrics-serverinstalled. This trips up the same people it used to trip up in Dashboard. It is a separate, optional cluster component, not something Headlamp bundles. - OIDC login failing right after a redirect. This is almost always the missing
X-Forwarded-Protoingress header from Step 4, producing anhttp://callback URL your identity provider rejects because it was configured to expecthttps://. - Flatpak silently failing to use cloud-provider credential plugins on Linux. If login works for a local cluster but fails for a managed one, suspect Flatpak’s sandbox blocking the
aws,az, orgcloudbinary your kubeconfig’s exec plugin calls, and apply theflatpak overridecommand from Step 3. - Removing Dashboard before everyone has actually tried Headlamp. A parallel rollout only protects you if you wait for real usage and feedback before Step 8, not just a quick personal test.
- Treating
cluster-adminas the permanent answer. It is the fastest way to get a first login working in Step 5, not a production-safe default; narrow it once you have confirmed the rest of the setup works.
Verify the Whole Migration Worked
Before you consider this done, walk through this list end to end:
- Headlamp opens without errors, and the correct clusters and namespaces are visible for the people who need them.
- Desktop users can authenticate purely through their existing kubeconfig, with no extra login step.
- In-cluster users can sign in with either the service account token or OIDC, whichever you configured, and see only what their RBAC role allows.
- A test Deployment can be created from pasted YAML, its logs can be read, and (for permitted roles) a shell can be opened inside its pod.
- Metrics appear if
metrics-serveris installed, or a clear “not available” notice appears if it is not, rather than a silent blank chart. kubectl get pods -n kubernetes-dashboardreturns nothing, confirming the old Dashboard installation and its dedicated service accounts are fully removed.
Next Steps
Once the core migration is solid, Headlamp’s plugin system is the natural next thing to explore. The project maintains official plugins for specific workload types, including ones for Knative serverless workloads and Kubeflow AI/ML pipelines, browsable on Artifact Hub. If you started with a broad cluster-admin service account to get moving quickly in Step 5, revisiting that with a properly scoped role, or moving to OIDC entirely, is worth doing before this becomes the UI a whole team relies on daily. And if you manage more than one cluster, spend a few minutes in Map View on your busiest one; seeing how a real Deployment’s ReplicaSets, Pods, and Services actually connect is a fast way to build intuition that pure list views do not give you.








No Comment! Be the first one.