TL;DR: Linode Object Storage has no recursive “delete folder” in the web console. The linode-s3-delete CLI solves this by listing every object under a bucket or prefix and deleting them in batches of up to 1,000 via the S3-compatible API. It supports dry-run, region auto-detection, and domain-style bucket shorthand.

Why does Linode Object Storage lack a folder delete button?

If you use Linode Object Storage (now part of Akamai’s cloud portfolio), you have probably run into the same frustration I did: there is no recursive delete in the web console. You cannot select a folder and wipe it out. You have to click through every object, one at a time, until your will to live runs out.

I built a small open-source tool to fix that. It is called linode-s3-delete, and it does one thing well: list every object under a bucket or prefix, then delete them in bulk.

The problem is not S3… it is the UI

Object storage is not a filesystem. There are no real directories. What looks like a folder in a browser is just a shared prefix on object keys (backups/2024/photo.jpg, backups/2024/photo2.jpg, and so on). Every S3-compatible API, including Linode’s, supports listing objects by prefix and deleting them in batches.

The Linode web interface simply does not expose that workflow. So clearing out an old deployment, an abandoned static site, or a bucket you created for testing means manual labor, unless you reach for the API.

I wanted something faster than clicking, lighter than installing the full AWS CLI, and specific enough to handle Linode’s regional endpoints without me having to remember URL formats at 11 PM.

What the tool does

linode-s3-delete is a ~290-line Python script with a thin Bash wrapper. It uses boto3 to talk to Linode’s S3-compatible endpoints. The wrapper always runs through a project virtualenv, so you never have to wonder whether you activated the right Python.

Core capabilities:

  • Recursive listing and deletion — paginates through all objects under a bucket or prefix, then deletes in batches of up to 1,000 per API call.
  • --list-buckets — scans known Linode regions and prints every bucket you own, with region and creation date.
  • --dry-run — shows exactly what would be deleted, without touching anything.
  • --prefix — limits scope to a “folder” path inside a bucket.
  • --yes — skips the confirmation prompt when you are sure.
  • Region auto-detection — if a bucket is not in the region you specified, the tool searches other Linode regions automatically.
  • Bucket shorthand — if you have a domain-style bucket like www.example.com, typing www expands to the full name when the match is unambiguous.

That last feature exists because I kept getting bucket names wrong. The help text now includes explicit CORRECT and WRONG examples, because https://www.example.com/photos/ is a URL, not a bucket name, and I have typed it that way more than once.

Quick start

Clone the repo and set up the environment:

git clone https://github.com/Geigle/linode-s3-delete.git
cd linode-s3-delete
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
chmod +x delete

Export your Linode Object Storage credentials (from the Linode Cloud Manager under Object Storage → Access Keys):

export LINODE_ACCESS_KEY=your_access_key
export LINODE_SECRET_KEY=your_secret_key
export LINODE_REGION=us-ord-1   # or your region

The tool also accepts standard AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY variables if you already have those set.

List your buckets

./delete --list-buckets

Example output:

Your Linode Object Storage buckets:
  my-bucket                                region=us-ord-1  created=2024-01-15 ...
  www.example.com                          region=us-ord-1  created=2023-08-12 ...

Copy the exact name from the first column. That string is the bucket name, whether it looks like a hostname or a short label.

Preview before you delete

Always dry-run first:

./delete --bucket www.example.com --dry-run
./delete --bucket my-bucket --prefix old-project/ --dry-run

Delete for real

./delete --bucket my-bucket --prefix old-project/

The tool lists all matching objects, asks for confirmation, then deletes. Add --yes to skip the prompt when you are running scripted cleanup.

How it works under the hood

The flow is straightforward:

  1. Build a boto3 S3 client pointed at the correct Linode endpoint (https://us-ord-1.linodeobjects.com, etc.).
  2. Resolve the bucket name and region; auto-detecting if needed, expanding shorthand if you typed www instead of www.example.com.
  3. Paginate list_objects_v2 to collect every key under the optional prefix.
  4. Call delete_objects in chunks of 1,000.

S3 has no concept of deleting a directory. You delete the objects, and the “folder” disappears because nothing references that prefix anymore. If you see Found 0 object(s), the bucket or prefix is already empty.

Supported Linode regions out of the box:

RegionEndpoint
us-east-1https://us-east-1.linodeobjects.com
us-ord-1https://us-ord-1.linodeobjects.com
us-southeast-1https://us-southeast-1.linodeobjects.com
eu-central-1https://eu-central-1.linodeobjects.com

Newer Akamai regions follow the same {region}.linodeobjects.com pattern and are handled automatically.

Lessons from building it

A few things surprised me during development:

Region matters more than bucket name. My buckets all live in us-ord-1, but boto3 defaults to us-east-1 unless you set the endpoint explicitly. A wrong region produces a confusing NoSuchBucket error even when the bucket name is perfect. The tool now defaults to us-ord-1 and searches all regions if the first guess fails.

Bucket names are not URLs. Domain-style bucket names like www.example.com are common on Linode because they map cleanly to static site hosting. But they are opaque strings — not hostnames you browse to, and not paths with trailing slashes.

Dry-run is not optional. Bulk delete is irreversible. The confirmation prompt and --dry-run flag are the two guardrails that keep this tool useful instead of dangerous.

Safety and responsibility

The GitHub description calls this a utility for “indiscriminately wiping out S3 buckets,” and that is not entirely wrong, but the tool is only as reckless as the person running it. Use --dry-run, read the object list, and double-check the bucket name before confirming. Object storage has no undo.

I wrote this for my own Linode account cleanup. It is MIT-licensed, has a single direct dependency (boto3, Apache 2.0), and includes third-party license notices for GitHub hygiene. It is not affiliated with Linode, Akamai, or AWS.

Key Takeaways

  • Object storage has no real directories — “folders” are just shared key prefixes.
  • The Linode web console does not expose batch delete; the S3 API does.
  • Always use --dry-run and double-check bucket names before confirming.
  • Region mismatches produce confusing NoSuchBucket errors — the tool auto-detects.
  • Domain-style buckets (e.g., www.example.com) are valid but must be typed exactly.

Get the Tool

If you have ever stared at a Linode Object Storage bucket full of orphaned files and thought “there has to be a faster way”, then fear not, for there is. Clone the repo, dry-run first, and reclaim your evening.