Uninstall
Admin guide
Greenlight runs entirely in your own cloud, so you remove it there, as a cloud owner — never from the dashboard. Settings → Danger zone says the same and removes nothing. Shift cannot uninstall Greenlight for you: it has no access to your cloud.
Uninstalling is a by-hand sequence, run once. Your databases, storage, DNS zone, and cluster carry delete protection so that no automatic update can ever destroy them (Upgrades). Uninstalling is the one time you lift that protection, on purpose.
Before you start
Section titled “Before you start”-
Keep what you need. Export the audit log, and snapshot or back up any database or storage you may want later, using your cloud’s own tools. Once the step that deletes them has run, they cannot be recovered.
-
Delete your apps in Greenlight first. Use each app’s lifecycle menu (Kill switch & restore). That removes the identities, images, secrets, and DNS records each app was given, the way the platform expects, so fewer leftovers need finding by hand.
-
Stop automatic updates, so no scheduled update runs halfway through the teardown:
Terminal window kubectl -n greenlight-updater patch cronjob greenlight-updater -p '{"spec":{"suspend":true}}' -
Remove the DNS delegation for your Greenlight host (for example
greenlight.example.com) at whoever hosts your parent domain. Greenlight never had access to that record. Until it is gone, public resolvers keep answering for the host after the zone itself is deleted.
Installed from the Azure portal (Marketplace)
Section titled “Installed from the Azure portal (Marketplace)”Delete the managed application in the Azure portal. Azure removes its managed resource group, and everything Greenlight created, with it. If the delete is refused, contact Shift support before trying anything else: the managed resource group’s deny assignment stops you changing it directly.
Installed with install.sh
Section titled “Installed with install.sh”Everything Greenlight creates sits in the one resource group you installed into, so deleting that group removes the install. Delete locks guard the cluster, both PostgreSQL servers, the storage account, and the Key Vault, so remove those first.
-
Remove the delete locks in the install’s resource group:
Terminal window az lock list --resource-group <resource-group> --output tableaz lock delete --ids $(az lock list --resource-group <resource-group> --query '[].id' --output tsv) -
Delete the resource group. This removes the cluster (and the node resource group Azure manages for it), the databases, storage, Key Vault, DNS zone, network, and identities:
Terminal window az group delete --name <resource-group> -
Purge the Key Vault, if you want its name back. A deleted vault stays recoverable for 90 days and holds its name for that time. Greenlight’s vault does not use purge protection, so you can purge it straight away:
Terminal window az keyvault list-deleted --query "[].{name:name, location:properties.location}" --output tableaz keyvault purge --name <vault-name> --location <region>
Google Cloud
Section titled “Google Cloud”The project holds only Greenlight
Section titled “The project holds only Greenlight”Delete the project. This is the simplest complete removal. It also takes the Terraform state bucket (greenlight-tfstate-<project>), which nothing else uses once the install is gone:
gcloud projects delete <project>Google keeps a deleted project recoverable for 30 days before removing it for good. Billing for its resources stops when the delete is requested.
The project holds other things too
Section titled “The project holds other things too”Destroy only what Greenlight created, with the Terraform files from the release package you last installed or updated with. Run the steps in order. Each one clears something that would otherwise stop the destroy.
-
Remove the cluster workloads while the cluster still exists, so the load balancers and firewall rules they own are deleted cleanly:
Terminal window helm uninstall greenlight -n greenlight-systemhelm uninstall traefik -n traefik -
Empty the Cloud DNS zone of every record except
NSandSOA. Greenlight writes the host’sArecords and the certificate’s_acme-challengeTXTrecords itself, and Google refuses to delete a zone that still has them. -
Delete the Cloud SQL instances directly (
gcloud sql instances delete <instance>) instead of letting Terraform drop their database users first. The users own objects inside the database, so dropping them fails. -
Delete what Greenlight created while running, which Terraform does not track: the Secret Manager secrets that hold integration credentials, app secrets, the Slack webhook URL, and Greenlight’s own signing and encryption keys, and the service account made for each app. List them, check each list, then delete what it shows. The secret filter leaves out the four
greenlight-cloudsql-*secrets, which the destroy in step 6 removes:Terminal window gcloud secrets list --project <project> --filter="name ~ /secrets/(integrations|apps|notifications|greenlight)- AND NOT name ~ /secrets/greenlight-cloudsql-" --format="value(name)"gcloud iam service-accounts list --project <project> --filter="displayName:'Greenlight app'" --format="value(email)"Delete each secret with
gcloud secrets delete <name> --project <project>and each account withgcloud iam service-accounts delete <email> --project <project>. -
Lift the delete protection on a copy of the package’s
deployment/gcp/directory. In every.tffile, changeprevent_destroy = truetofalse. Never edit the package you install from. -
Destroy from that copy against the install’s state:
Terminal window terraform init -backend-config="bucket=greenlight-tfstate-<project>" -backend-config="prefix=install"terraform destroy \-var "projectId=<project>" -var "region=<region>" -var "controlPlaneHost=<host>" \-var "sourceRegistryUrl=" -var "sourceRegistryUsername=" -var "sourceRegistryPassword="If it stops, fix the cause and run it again:
- A resource you already deleted is still in the state (for example a Cloud SQL user after step 3):
terraform state rm <address>, then rerun. - The private services connection says producer services are still using it: wait a few minutes after Cloud SQL is gone and rerun. If it persists, delete the VPC peering named
servicenetworking-googleapis-com, then rerun. - The network cannot be deleted because firewall rules use it: delete the leftover
k8s-…rules GKE created on that network (gcloud compute firewall-rules list --filter="network:<network>"), then rerun.
- A resource you already deleted is still in the state (for example a Cloud SQL user after step 3):
-
Decide the state bucket. Keep
gs://greenlight-tfstate-<project>as the record of what was destroyed, or delete it, including every object version.
Greenlight expects its own AWS account. The databases, buckets, DNS zone, EKS cluster, and the GitHub App secrets carry delete protection, so a plain terraform destroy is refused until you lift it.
-
Remove the cluster workloads, then wait for the ingress load balancer to go before removing the controller that deletes it. On a private install that publishes through PrivateLink, first rerun
./install.sh --private-link-consumers none: AWS will not delete a load balancer an endpoint service still publishes, and that run rejects the connected endpoints and removes the service.Terminal window helm uninstall greenlight -n greenlight-systemhelm uninstall traefik -n traefikContinue once the Network Load Balancer tagged
elbv2.k8s.aws/cluster=<cluster-name>is gone and, on a public install, the ingress Elastic IP shows no association. Then:Terminal window helm uninstall cert-manager -n cert-managerhelm uninstall aws-load-balancer-controller -n kube-systemhelm uninstall cluster-autoscaler -n kube-system -
Empty the Route 53 zone for your host of every record set except
NSandSOA. Check that the zone’s name is exactly your host before you delete anything. -
Delete what Greenlight created while running, which Terraform does not track: IAM roles under the
/gl-app/path,gl-app-*ECR repositories, and Secrets Manager secrets undergreenlight/,integrations/,apps/, andnotifications/. -
Lift the delete protection on a copy of the package’s
deployment/aws/directory. In every.tffile, changeprevent_destroy = truetofalse. Never edit the package you install from. -
Destroy from that copy against the install’s state:
Terminal window terraform init -backend-config="bucket=greenlight-tfstate-<account-id>" \-backend-config="key=install/terraform.tfstate" -backend-config="region=<region>"terraform plan -destroy \-var "region=<region>" -var "controlPlaneHost=<host>" \-var "sourceRegistryUrl=" -var "sourceRegistryUsername=" -var "sourceRegistryPassword="terraform destroy \-var "region=<region>" -var "controlPlaneHost=<host>" \-var "sourceRegistryUrl=" -var "sourceRegistryUsername=" -var "sourceRegistryPassword="Read the plan first: it should contain only deletions. The databases take longest, so run the destroy where a dropped session cannot interrupt it; a partial failure is safe to rerun. The databases are deleted without a final snapshot, every bucket is emptied with all its versions, and secrets are deleted without a recovery window.
-
Decide the state bucket. Keep
greenlight-tfstate-<account-id>as the record of what was destroyed, or delete every object version and the lock file, then the bucket.
Outside your cloud
Section titled “Outside your cloud”Whichever cloud you used, a few things live elsewhere:
- The DNS delegation at your parent domain, if you have not already removed it.
- The GitHub App. Uninstall it from your GitHub organization, and archive or delete the app and plugin marketplace repositories it managed, if you no longer want them.
- The sign-in client you registered with your identity provider for Greenlight.
- Your Shift subscription. Tell Shift the install is gone, so the subscription can be closed and the install stops appearing as one that has missed its reports.