Skip to content
You are reading dev: the documentation of main. The last release, 0.1.0, predates this site.

Uninstall

Three scopes, from the smallest.

Set kube.<module>.enabled = false and apply (Enable a module). Turn crossplane off last: the roles it created for other modules stay otherwise.

  1. Wait for every module’s ResourceSet to be Ready, if you just turned one on.

  2. Destroy the bootstrap module:

    Terminal window
    tofu destroy -target=module.socle.module.socle

flux-system is then left with no ResourceSet, FluxInstance or Deployment, and no module namespace remains (28 s on floci, 2026-09-30).

Under the hood

The releases go in reverse: the envelope, the Flux instance, the operator, then on aws the EKS add-ons and CoreDNS, and on aws and azure Cilium. The socle Kustomization’s deletionPolicy: WaitForTermination holds the envelope until every catalog ResourceSet is finalized, so the operator is never removed with work left (Uninstall order). The operator uninstalls from the inventory of its last completed reconcile, hence step 1. CI asserts the empty result on every run (the destroyed suite).

On GCP, the cluster carries deletion protection: set gcp.deletion_protection = false and apply first. Then, on both:

Terminal window
tofu destroy

On GCP a first destroy fails on the certificate map, the regional certificate and the proxy-only subnetwork: GKE removes the Gateways’ load balancers after the cluster. Run tofu destroy again a few minutes later (measured on a sandbox, 2026-10-07).

The releases go before the cluster, which needs the API. If the runner can no longer reach it (on AWS it left cluster_endpoint_public_access_cidrs, say), drop the releases from the state first:

Terminal window
tofu state rm module.socle.module.socle
tofu destroy

Nothing then deletes the module access Crossplane created: see the table below.

WhatWhyHow to remove it
The Gateway API CRDsdeleting a CRD deletes every Gateway and routeby hand once unused, or with the cluster
The CRDs of external_secrets, keda, velero, crossplane, argocd_image_updaterthey hold your objectsas above
Module roles (AWS), when crossplane went first or the bootstrap left the statenothing is left to delete themdelete the roles under /socle/<cluster>/ in IAM
Module bindings (GCP), when crossplane went first or the bootstrap left the statenothing is left to delete them; a socle created in the project next inherits themremove the principal://… members of the project’s IAM policy
Velero’s bucket (S3 on AWS, GCS on GCP)Crossplane may not delete a bucket of datain the cloud, once its backups are not needed
A pending Velero Restoreits finalizer holds the namespacedelete the Restore (Restore a backup)
ImageUpdater objects in argocd, once argocd_image_updater is offtheir finalizer holds them, and the argocd namespace, with no controller to release itdelete them before turning the module off, or release them: kubectl -n argocd patch imageupdater <name> --type merge -p '{"metadata":{"finalizers":[]}}'
A mirror’s pull secretflux-system outlives the operator’s releasewith the cluster
On aws, /aws/eks/<cluster>/cluster, when control-plane logs were on and the destroy was interrupted during its five-minute wait, or EKS delivered later than thatEKS recreates the group when it delivers, with no retention and no key (AWS-20); the next apply of the same cluster_name fails on ResourceAlreadyExistsExceptionaws logs delete-log-group --log-group-name /aws/eks/<cluster>/cluster, or keep it: tofu import 'module.foundations.aws_cloudwatch_log_group.cluster' /aws/eks/<cluster>/cluster
On gcp, the cluster’s flow, NAT and GKE logsthey are in the project’s _Default bucket, which the socle does not own (GCP-17)they expire with the bucket’s retention, 30 days by default