clean¶
Prune old image tags according to lifecycle rules and garbage collect unreferenced blobs.
Both s3:// and local:// references are supported.
Flags¶
| Flag | Description |
|---|---|
--confirm |
Apply deletions. Without this flag, the command is a dry run (safe, no changes). |
--tags |
Only prune old tags, skip blob GC. |
--blobs |
Only GC unreferenced blobs, skip tag pruning. |
--config <file> |
Use a local config YAML file instead of the bucket's s3lo.yaml. |
How it works¶
clean does two things by default, both controlled by lifecycle rules in s3lo.yaml:
1. Tag pruning
Reads lifecycle rules from s3lo.yaml. For each image, evaluates all tags against:
lifecycle.keep_last— keep the N most recently pushed tagslifecycle.max_age— delete tags older than this durationlifecycle.keep_tags— tags that are never deleted regardless of other rules
Tags violating any rule are candidates for deletion.
2. Blob garbage collection
Reads all manifests in the bucket, builds a set of referenced blob digests, then deletes any blob in blobs/sha256/ that:
- Is not referenced by any manifest, and
- Was uploaded more than 1 hour ago (grace period to protect in-progress pushes)
Examples¶
# Dry run — see what would be deleted (no changes made)
s3lo clean s3://my-bucket/
# Full cleanup: prune tags + GC blobs
s3lo clean s3://my-bucket/ --confirm
# Only prune old tags (keep blobs for now)
s3lo clean s3://my-bucket/ --tags --confirm
# Only GC unreferenced blobs (e.g. after manual deletes)
s3lo clean s3://my-bucket/ --blobs --confirm
Output¶
Setting up lifecycle rules¶
Before running clean, configure lifecycle rules with s3lo config set:
# Keep last 10 tags, delete anything older than 90 days
s3lo config set s3://my-bucket/ lifecycle.keep_last=10 lifecycle.max_age=90d
# Override for a specific image: keep last 5 and protect stable/latest tags
s3lo config set s3://my-bucket/myapp lifecycle.keep_last=5 lifecycle.keep_tags=stable,latest
# Aggressive cleanup for dev/* images: keep only last 3 tags, max 7 days
s3lo config set "s3://my-bucket/dev/*" lifecycle.keep_last=3 lifecycle.max_age=7d
Schedule with GitHub Actions
clean doesn't run automatically. Add a scheduled workflow to run it nightly:
Safety
- Default is always dry run. Nothing is deleted without
--confirm. - Blobs uploaded in the last hour are never deleted, protecting in-progress pushes.
keep_tagsare never deleted regardless of age or count.