Procedure for Deleting the Minecraft Server and Its Backups

Keeping the last backup, removing the Spot recovery root, disabling deletion protection, and destroying the server

When you finish operating the server, check the final backup and real resources in the order below. Deleting the VM also deletes the auto-delete boot disk and the world inside it. Keep Terraform state until the real resource deletion is complete.

Prerequisites

You must identify the project, the server root, and the optional recovery root to be deleted exactly. Decide as well where to keep the last backup that passed the isolated restore test in part 06.

Destructive commands

The terraform apply and gcloud storage rm below delete resources or data. Run them only when you have read the variables and the saved plan yourself. The local verification did not run the deletion commands.

If Cloud Storage soft delete is on, deleted objects and buckets stay recoverable for the retention period and storage cost can remain. The moment a live object disappears from the listing and the moment the cost fully stops can differ.

Project, Backup Bucket, and State

Check the project, the backup bucket, and the current state in the server root.

Check

cd "${HOME}/minecraft-one-root"

export PROJECT_ID="$(
  terraform output -raw minecraft_project_id
)"
export BACKUP_BUCKET="$(
  terraform output -raw backup_bucket_name
)"

printf 'Project: %s\nBackup bucket: %s\n' \
  "${PROJECT_ID}" \
  "${BACKUP_BUCKET}"
gcloud config get-value project
terraform state list

Stop if the two project values differ or the output is empty. The state must show the Minecraft VM, the network, the static IP, the service account, and the backup bucket.

The Last Backup

If the server is running and automatic backup is on, create the last backup.

Run: right before deleting the server

export MINECRAFT_INSTANCE="$(
  terraform output -raw minecraft_instance_name
)"
export MINECRAFT_ZONE="$(
  terraform output -raw minecraft_zone
)"

gcloud compute ssh "${MINECRAFT_INSTANCE}" \
  --zone="${MINECRAFT_ZONE}" \
  --command="sudo systemctl start minecraft-backup.service"

Find the new archive and manifest, and run minecraft-backup-verify from part 06. Record the full name of the object that succeeded. If you are deleting the backup bucket as well, download both files to Cloud Shell first.

Put the file name in a variable once so you do not type the timestamp three times.

export LAST_BACKUP="minecraft-EXACT-TIMESTAMP.tar.gz"

gcloud storage cp \
  "gs://${BACKUP_BUCKET}/backups/${LAST_BACKUP}" \
  .
gcloud storage cp \
  "gs://${BACKUP_BUCKET}/backups/${LAST_BACKUP}.sha256" \
  .
sha256sum --check "${LAST_BACKUP}.sha256"

If you do not see OK, do not delete any resource. Do not use the Cloud Shell home directory as a long-term storage location. Choose Download in the Cloud Shell overflow menu and move the archive and the manifest to your own computer one at a time. In the path field of the dialog, enter the file name relative to the home directory. For example, minecraft-20260729T043000Z.tar.gz, exactly the file name you just downloaded. Delete the bucket objects only after you have confirmed that both files are in a local long-term storage location and that the local SHA-256 check also says OK.

Deleting the Spot Recovery Root

Skip this section if you did not apply part 09. Removing the recovery root first keeps a late preemption event from sending a start request during the server deletion.

Conditional run: when the recovery root is applied

cd "${HOME}/minecraft-spot-recovery"
terraform plan -destroy -out=destroy-recovery.tfplan
terraform show destroy-recovery.tfplan

The plan must show only the function, the source bucket, the Pub/Sub topic, the Logging sink, the runtime and trigger service accounts, and the related IAM. Do not apply it if the Minecraft VM, a disk, or the network appears.

Deletes data: removing the recovery root

terraform apply destroy-recovery.tfplan
terraform state list

The last command must print nothing. If a deletion failed, do not touch the state; check the real resources that remain with a new destroy plan.

Disabling VM deletion protection

Return to the server root and change one value in terraform.tfvars.

cd "${HOME}/minecraft-one-root"
nano terraform.tfvars
deletion_protection = false

Run: create the change plan only

terraform validate
terraform plan \
  -out=disable-deletion-protection.tfplan
terraform show disable-deletion-protection.tfplan

It must show only the deletion_protection change on the same VM. Do not apply it if a replacement or a disk deletion appears.

Run: disable deletion protection

terraform apply disable-deletion-protection.tfplan

This step changes only the protection property so the next destroy can delete the VM.

Keeping or Deleting the Backup Bucket

While backup objects remain, force_destroy = false blocks the bucket deletion. Choose only one of the two paths below.

Keep the Backup Bucket

Leave the real bucket and its objects in place, and detach only the bucket resource from the Terraform state.

Conditional run: when keeping the backups in Cloud Storage

terraform state rm google_storage_bucket.backup

This command does not delete the bucket. Terraform no longer manages the lifecycle of this bucket either. Record the bucket name, the retention deadline, and who will delete it later. Storage cost can keep accruing.

After detaching it from the state, do not run an ordinary terraform plan in this root, only plan -destroy. The bucket definition is still in the configuration files, so an ordinary plan tries to create a new bucket with the same name, and applying it fails on the name conflict. The only procedure left in this root is the deletion plan.

Delete the Backup Bucket Too

First read the bucket’s soft delete policy and its live and noncurrent objects.

Check: backup bucket protection policy and objects

gcloud storage buckets describe \
  "gs://${BACKUP_BUCKET}" \
  --format="default(soft_delete_policy)"

gcloud storage ls \
  --recursive \
  --all-versions \
  "gs://${BACKUP_BUCKET}/"

Review the listing line by line. In <exact-object-name> below, put the full path of one archive or manifest that appeared in the listing. Do not use a wildcard or **.

Deletes data: one object at a time, after verifying the local copy

gcloud storage rm \
  --all-versions \
  "gs://${BACKUP_BUCKET}/<exact-object-name>"

Read the listing again and confirm that no object remains. Do not delete a file you do not recognize; find its owner.

If soft delete was on when you deleted the objects, copies that do not appear in the ordinary listing remain. The ** below is for the listing command only; do not copy it into a deletion command.

Check: soft-deleted objects

gcloud storage ls \
  "gs://${BACKUP_BUCKET}/**" \
  --soft-deleted \
  --full

If there is output, record the deletion time and the hard delete time of each entry. These objects cannot be permanently deleted until the retention period ends. Once the live and noncurrent objects are empty, the next Terraform destroy deletes the bucket. A bucket with a soft delete policy on can remain as a soft-deleted bucket after deletion.

Destroying the Server Root

Run: create the deletion plan only

terraform plan -destroy -out=destroy-server.tfplan
terraform show destroy-server.tfplan

The VM and its auto-delete boot disk, the static IP, the firewall, the subnet, the VPC, and the server service account must be the deletion targets. If you chose the keep path, the backup bucket must not be in the plan. If you chose the delete path, the empty backup bucket is a deletion target too.

Deletes data: after reading the whole plan

terraform apply destroy-server.tfplan
terraform state list

The last command must print nothing. If Error deleting... appears, do not erase the state first. Resolve the error and check only the remaining targets with a new destroy plan.

Completion Check

  • You kept the last archive and manifest and checked the SHA-256.
  • If you applied it, you deleted the Spot recovery root first.
  • The deletion protection plan contained only a VM attribute change.
  • You ran only one path, keeping the backup bucket or deleting objects one at a time.
  • terraform state list in the server root is empty.
  • If soft-deleted objects remain, you recorded the hard delete time and the cost that can remain until then.

When terraform state list is empty in both roots, use Cleaning Up Terraform State and Remaining Google Cloud Costs to inspect backend objects and remaining resources across the project.

Comments

Comments

    Image preview