Backing Up and Restoring K2s Addons
K2s provides built-in CLI commands to back up and restore addon configuration and data. This allows you to preserve addon state across upgrade, migration, or disaster-recovery scenarios.
Each addon ships its own Backup.ps1 and Restore.ps1 scripts that know exactly which Kubernetes resources, configuration files, or persistent data to capture. The CLI orchestrates staging, zip creation/extraction, manifest validation, and the addon re-enable cycle automatically.
Prerequisites
- Administrator privileges — all backup and restore commands must run in an elevated shell.
- Cluster running — the K2s cluster must be started before executing backup or restore (exception: storage smb can back up local data even when the cluster is not running).
- Addon enabled — an addon must be enabled for backup to capture its state.
- Addon disabled — an addon must be disabled before restore. The CLI enforces this and returns an error otherwise.
Backup Command
Creates a zip archive containing the addon's backed-up resources and a backup.json manifest.
Flags
| Flag | Short | Description | Default |
|---|---|---|---|
--file |
-f |
Output zip file path | Auto-generated in C:\Temp\Addons |
Default Behavior
When -f is omitted the zip is written to C:\Temp\Addons with the naming pattern:
Spaces and slashes in the addon name are replaced with underscores (e.g. ingress nginx → ingress_nginx_backup_20260219_143012.zip).
Examples
# Backup a single addon to the default location
k2s addons backup registry
# Backup an addon implementation to a custom path
k2s addons backup "ingress nginx" -f D:\backups\ingress-nginx.zip
# Backup an addon implementation to the default folder
k2s addons backup "ingress traefik"
Restore Command
Restores an addon from a previously created backup zip. The restore flow is:
- Extract the zip to a temporary staging directory.
- Validate the
backup.jsonmanifest (addon name, implementation, K2s version). - Re-enable the addon (using
EnableForRestore.ps1if available, otherwise standardEnable.ps1). - Execute the addon's
Restore.ps1to apply backed-up resources. - Clean up staging files.
Flags
| Flag | Short | Description | Default |
|---|---|---|---|
--file |
-f |
Input zip file path | Newest matching zip in C:\Temp\Addons |
When -f is omitted the CLI searches C:\Temp\Addons for files matching {addon_name}_backup_*.zip and picks the most recently modified one.
⚠️ Warning: The addon must be disabled before running restore. If the addon is still enabled the command will fail with:
addon '<name>' must be disabled before restore.
Examples
# Restore from an explicit backup file
k2s addons restore registry -f D:\backups\registry-backup.zip
# Restore from the latest backup in the default folder
k2s addons restore "ingress nginx"
# Restore a specific addon implementation
k2s addons restore "storage smb" -f C:\Temp\Addons\storage_smb_backup_20260219_143012.zip
Typical Workflow
A common scenario is backing up addons before a K2s upgrade and restoring them afterwards:
# 1. Back up the addons you want to preserve
k2s addons backup registry
k2s addons backup "ingress nginx"
k2s addons backup security
# 2. Disable the addons
k2s addons disable registry
k2s addons disable ingress nginx
k2s addons disable security
# 3. Perform the upgrade
k2s system upgrade
# 4. Restore each addon (re-enables automatically)
k2s addons restore registry
k2s addons restore "ingress nginx"
k2s addons restore security
After restore each addon is re-enabled with its backed-up configuration applied on top.
What Gets Backed Up — Summary
The following table shows at a glance what each addon's backup contains.
| Addon | Backup Type | What Gets Backed Up | Notes |
|---|---|---|---|
| autoscaling | Config | ConfigMaps in autoscaling namespace |
EnableForRestore.ps1 with best-effort pod readiness |
| dashboard | Metadata | Ingress type, metrics-addon-enabled flag | Restore calls Update.ps1; may re-enable metrics addon |
| dicom | Config | Orthanc ConfigMap, ingress resources, Traefik middlewares | Restarts deployment after config restore |
| gpu-node | Metadata | Nothing (infrastructure-only) | Re-enable fully restores functionality |
| ingress nginx | Config | Controller ConfigMap, cluster-local Ingress | Waits for controller pod readiness |
| ingress nginx-gw | Config | Gateway CR, NginxGateway CR | Certificates regenerated on enable; not backed up |
| ingress traefik | Config | Cluster-local Ingress | Waits for traefik pod readiness |
| kubevirt | Metadata | Nothing (infrastructure-only) | Re-enable fully restores functionality |
| logging | Config | 4 ConfigMaps (OpenSearch, Fluent Bit Linux/Windows) | Rollout-restarts StatefulSet, Deployments, DaemonSets |
| metrics | Config | Metrics-server Deployment, APIService, Windows exporter resources | Rollout-restarts after apply |
| monitoring | Config | User Grafana dashboards/datasources, Ingress resources, non-Helm Prometheus CRs | Secrets and PV data not backed up; Helm-managed resources skipped |
| registry | Data | tar.gz of /registry/repository from control-plane VM, ConfigMap |
Overwrites existing data; SSH to VM |
| rollout argocd | Data | ArgoCD state export, ingress resources, Traefik middleware | Export contains credentials (repo creds) |
| rollout fluxcd | Config | All Flux CRs, referenced Secrets, webhook ingress | Secrets backed up (Flux requires them) |
| security | Data | CA root Secret, Keycloak PostgreSQL dump, enhanced-security marker | EnableForRestore.ps1 reconstructs original enable flags; drops/recreates Keycloak DB |
| storage smb | Data | SmbStorage.json, addon config snapshot, SMB share file data |
Disable/enable cycle with -Keep; works offline |
| viewer | Config | ConfigMap, Service, ingress resources, Traefik middleware | Runs Update.ps1 after restore |
Backup Types:
- Config — Kubernetes resources (ConfigMaps, Ingresses, CRDs) exported as YAML/JSON. No persistent volume data.
- Data — Includes files or database dumps copied from the cluster or VM, in addition to configuration.
- Metadata — Only
backup.jsonmanifest with flags/settings. No files are captured; re-enabling restores full functionality.
Per-Addon Details
autoscaling
Backup: Exports all ConfigMaps in the autoscaling namespace (excluding kube-root-ca.crt) as YAML files.
Restore: Uses EnableForRestore.ps1 which applies the KEDA manifest with best-effort readiness checks, allowing restore to proceed even if the keda-operator pod is temporarily unhealthy. Applies backed-up ConfigMaps with server-side apply fallback on conflict. Waits for KEDA pods (admission-webhooks, metrics-apiserver, operator).
dashboard
Backup: Metadata-only — records the active ingress type (none, nginx, traefik, or nginx-gw) and whether the metrics addon was enabled. No Kubernetes resources are exported.
Restore: Re-enables the metrics addon if it was enabled at backup time. Ensures the correct ingress addon is enabled. Calls Update.ps1 to regenerate authentication wiring. Waits for dashboard pod availability.
dicom
Backup: Exports the Orthanc json-configmap ConfigMap (required), plus optional ingress resources: nginx Ingress, traefik Ingress (including correct1/correct2 variants), nginx-gw HTTPRoutes (http + https), and Traefik middlewares (strip-prefix, cors-header, oauth2-proxy-auth). Resources are exported as minimal JSON with server-managed fields stripped.
Restore: Detects the active ingress controller and skips non-matching ingress resources. Waits for DICOM deployments, applies resources, restarts the DICOM deployment if configuration was restored, then runs Update.ps1.
gpu-node
Backup: No-op. This is an infrastructure-only addon — backup.json contains files: []. Re-enabling the addon fully restores GPU passthrough functionality.
ingress nginx
Backup: Exports the ingress-nginx-controller ConfigMap and the optional nginx-cluster-local Ingress resource.
Restore: Waits for the ingress-nginx controller pod, then applies resources with conflict fallback.
ingress nginx-gw
Backup: Exports the nginx-cluster-local Gateway and nginx-gw-config NginxGateway CR as minimal JSON. TLS certificates are intentionally not backed up — they are regenerated when the addon is re-enabled.
Restore: Applies backed-up resources, then applies the NginxProxy configuration with the current control-plane IP. Waits for the controller pod. Runs Update.ps1.
ingress traefik
Backup: Exports the traefik-cluster-local Ingress as YAML.
Restore: Waits for the traefik pod to become ready, then applies the Ingress with conflict fallback.
kubevirt
Backup: No-op. Infrastructure-only addon — backup.json contains files: []. Re-enabling fully restores KubeVirt functionality.
logging
Backup: Exports four ConfigMaps as minimal JSON: opensearch-cluster-master-config, fluent-bit, fluent-bit-win-parsers, fluent-bit-win-config.
Restore: Applies all configuration files, then performs best-effort rollout restarts of the OpenSearch StatefulSet, Dashboards Deployment, and Fluent Bit DaemonSets (Linux and Windows). Waits for rollout completion with a 600-second timeout.
metrics
Backup: Exports the metrics-server Deployment (from metrics namespace), the v1beta1.metrics.k8s.io APIService (cluster-scoped), and Windows exporter resources in kube-system namespace (ConfigMap, DaemonSet, Service) plus the windows-exporter ServiceMonitor in the monitoring namespace. All exported as minimal JSON.
Restore: Applies all files, then performs rollout restarts of the metrics-server Deployment and windows-exporter DaemonSet.
monitoring
Backup: Exports user-created (non-Helm-managed) Grafana dashboard and datasource ConfigMaps (labeled grafana_dashboard=1 / grafana_datasource=1; default kube-prometheus-stack-* ConfigMaps are also excluded), all Ingress/HTTPRoute/IngressRoute/Middleware resources, and non-Helm-managed Prometheus Operator CRs (Prometheus, Alertmanager, PrometheusRule, ServiceMonitor, PodMonitor, AlertmanagerConfig).
ℹ️ Note: Secrets and PersistentVolume data are not backed up. Helm-managed resources are skipped — they are recreated when the addon is re-enabled.
Restore: Skips ingress resources that do not match the currently active ingress controller. Uses server-side apply with sanitized fields (removes resourceVersion, uid, managedFields). Performs best-effort rollout status checks for all monitoring workloads.
registry
Backup: Creates a tar.gz archive of /registry/repository on the control-plane VM via SSH, copies it to the staging directory. Also exports the registry-config ConfigMap.
⚠️ Warning: Restore overwrites any existing registry data. The StatefulSet is scaled to zero during restore.
Restore: Scales the StatefulSet to 0, waits for pod termination, copies the archive to the VM via SSH, deletes existing data, extracts the archive, optionally restores the ConfigMap, then scales back to 1.
rollout argocd
Backup: Uses argocd admin export to capture the full ArgoCD state (applications, projects, repositories, clusters). Also exports ingress resources (nginx Ingress, traefik Ingress, nginx-gw HTTPRoutes) and the Traefik oauth2-proxy-auth Middleware. The export is run via the host argocd.exe binary if available, otherwise via kubectl exec into the argocd-server pod.
⚠️ Warning: The ArgoCD export contains credentials (repository secrets). Handle the backup zip with care.
Restore: Waits for ArgoCD deployments and StatefulSets. Applies ingress resources matching the active controller only. Uses argocd admin import with sanitized YAML. Runs Update.ps1. Cleans up export files to prevent credential lingering.
rollout fluxcd
Backup: Exports all Flux custom resources in the rollout namespace (GitRepository, Kustomization, HelmRelease, HelmRepository, OCIRepository, Bucket, ImageRepository, ImagePolicy, ImageUpdateAutomation, Provider, Alert, Receiver), plus referenced Secrets (discovered via recursive secretRef scanning), plus webhook ingress resources. Secrets are written first in the manifest's file list.
Restore: Waits for Flux controller deployments. Applies resources with ingress-aware filtering. Runs Update.ps1.
security
Backup: Exports the CA root Secret (ca-issuer-root-secret from cert-manager namespace), a PostgreSQL dump of the Keycloak database (via pg_dump exec into the pod), and the enhanced-security marker file. Detects and records the current enable flags (--type, --ingress, --omitKeycloak, --omitHydra, --omitOAuth2Proxy).
Restore: Uses EnableForRestore.ps1 which reads backup.json to reconstruct the original enable flags and delegates to Enable.ps1. Restores the CA Secret with --force and restarts cert-manager. For Keycloak: scales down the Keycloak pod, drops and recreates the database, imports the dump via psql exec, then scales back up. Restores the enhanced-security marker file.
storage smb
Backup: Copies the SmbStorage.json configuration file, an addon config snapshot from setup.json, and the SMB share data from the Windows mount path. Works even when the cluster is not running (local data only).
Restore: Restores the config snapshot, determines the SMB host type from addon configuration, performs a disable/enable cycle with the -Keep flag, then restores the share data.
viewer
Backup: Exports the config-json ConfigMap, the viewerwebapp Service, and ingress resources for all three ingress types, plus the Traefik oauth2-proxy-auth Middleware.
Restore: Detects the active ingress controller, waits for the viewer deployment, applies resources with ingress-aware filtering (skips non-matching), handles missing CRDs gracefully. Runs Update.ps1.
Backup Manifest Format
Each backup zip contains a backup.json file at the root with the following structure:
{
"k2sVersion": "1.5.0",
"files": ["configmap.yaml", "ingress.json"],
"addon": "registry",
"implementation": "registry",
"createdAt": "2026-02-19T14:30:12Z"
}
| Field | Description |
|---|---|
k2sVersion |
The K2s version that created the backup |
files |
List of files in the zip (may be empty for metadata-only backups) |
addon |
Addon name |
implementation |
Implementation name (omitted when addon has a single implementation) |
createdAt |
Timestamp of backup creation |
Some addons add extra fields (e.g. ingress, enableParams, scope, storageUsage) that their Restore.ps1 / EnableForRestore.ps1 scripts use to customize the restore flow.
Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
addon '<name>' must be disabled before restore |
The addon is still enabled | Run k2s addons disable <name> first |
no backup zip found |
No matching zip in C:\Temp\Addons |
Provide an explicit path with -f |
| Manifest addon/implementation mismatch | The zip was created for a different addon | Use the correct zip file for the target addon |
No Backup.ps1 found |
Addon does not support backup | Nothing to back up — the addon is fully recreated on enable |
| Restore fails during re-enable | Cluster resources unavailable | Check cluster health with k2s system status and retry |
| Registry restore overwrites data | By design — restore replaces existing repository contents | Back up the current state first if needed |
| ArgoCD credentials in backup | argocd admin export includes repo secrets |
Store the backup zip securely; delete after restore |