How to Pin a Deployment in rpm-ostree to Prevent It from Being Garbage Collected

To pin a specific deployment in rpm-ostree and prevent it from being garbage collected, use the `rpm-ostree pin` command on the deployment's ID or index.

When an update breaks your workflow

You just ran rpm-ostree upgrade on your Silverblue or Kinoite system. The reboot finishes, but the new kernel panics on your specific GPU, or a desktop environment update breaks your tiling window manager. You drop to a TTY, check the logs, and realize you need to boot back into the previous version immediately. You run rpm-ostree cleanup to clear out old layers, or you let the automatic maintenance run, and suddenly the previous deployment vanishes. The system only has the broken version left. You need a way to lock a specific commit in place until you are ready to let it go.

How rpm-ostree manages deployments

rpm-ostree treats your root filesystem as an immutable tree. Every time you run upgrade or rebase, it downloads a new commit, merges it with your local layers, and writes it to a new boot entry. The old deployment stays around for a short window so you can roll back. That window is controlled by the garbage collector. The collector runs automatically during rpm-ostree cleanup and during certain upgrade paths. It deletes deployments that are no longer active and have not been explicitly protected.

Think of it like a version control system that automatically prunes old branches unless you tag them. Pinning is that tag. It tells the package manager to ignore the deployment during cleanup, regardless of boot order or age. The rpm-ostreed daemon handles the actual deletion in the background. It checks the pin database before removing any commit from the BTRFS or overlay filesystem. If a deployment is pinned, the daemon skips it and moves to the next candidate.

Run journalctl -xeu rpm-ostreed after a cleanup cycle to see exactly which commits the daemon evaluated and which it skipped. The daemon logs every decision, so you never have to guess why a deployment disappeared.

Pinning a deployment to keep it safe

You need the exact commit hash to pin a deployment reliably. The index number shown in the deployment list shifts every time you reboot or add a new version. Scripts and manual workflows break when indices change. Always grab the full hash string.

Here is how to list your current deployments and extract the hash you need.

# Show all deployments with their commit hashes and boot order
rpm-ostree status
# Look for the line starting with "Deployment:" followed by the hash
# Copy the full 40-character hash from the version you want to preserve

Once you have the hash, apply the pin. The command requires root privileges because it modifies the internal deployment database.

# Mark the specific commit as protected from garbage collection
sudo rpm-ostree pin <commit-hash>
# The daemon writes the hash to the pin database immediately
# No reboot is required for the pin to take effect

You can also pin by index if you are working interactively and do not mind the shifting numbers. The index refers to the position in the current boot order.

# Pin the deployment at index 1 (usually the previous version)
sudo rpm-ostree pin 1
# The command resolves the index to a hash before saving
# This method is fine for quick manual rollbacks

Pinning does not change your current boot target. It only changes what the cleanup process is allowed to delete. Your system continues running the active deployment exactly as before.

Apply the pin before you run any cleanup commands. The garbage collector does not retroactively protect deployments you pin after the fact.

Verify the pin is active

The deployment list updates immediately to show the protection status. A P marker appears next to the pinned commit. This marker tells you the daemon will skip this entry during any future maintenance.

Here is how to confirm the pin is registered and active.

# Refresh the deployment list to show pin markers
rpm-ostree status
# Look for the "P" flag on the line containing your commit hash
# The flag confirms the database entry is recognized

If you see the P marker, the deployment is safe. You can now run rpm-ostree cleanup or let the automatic timer fire without losing that version. The daemon reads the pin database before touching the filesystem.

Check the marker after every reboot. Boot order changes can sometimes obscure the visual layout, but the P flag stays attached to the correct hash.

Common pitfalls and disk space reality

Pinning is a safety net, not a storage strategy. Each rpm-ostree commit contains a full snapshot of the root filesystem. A single deployment typically consumes between one and two gigabytes. If you pin five versions, you reserve ten gigabytes of disk space permanently. The garbage collector will not reclaim that space until you remove the pin.

Monitor your root partition regularly. Fedora systems with small root partitions fill up quickly when multiple deployments accumulate.

Here is how to check your actual disk usage and identify space hogs.

# Show filesystem usage in human-readable format
df -h /
# Look at the "Use%" column to gauge remaining headroom
# Aim to keep usage below 85% to avoid daemon failures

When the root partition crosses 90 percent, rpm-ostreed may refuse to download new updates. The daemon requires free space to stage the new commit before merging it. You will see a transaction error if you try to upgrade on a full disk.

Error: Transaction test error: insufficient disk space for staging new deployment

The error is intentional. Forcing an upgrade on a full partition corrupts the overlay mount. Unpin old versions or run sudo rpm-ostree cleanup to free space before attempting another update.

SELinux does not interfere with pinning operations. The rpm-ostreed daemon runs with the correct context by default. If you encounter permission denied errors, verify your user is in the wheel group or that you are using sudo correctly. Manual edits to /etc/rpm-ostreed/ are rarely needed. Trust the package manager. Manual file edits drift, snapshots stay.

When to pin versus other recovery strategies

Use rpm-ostree pin when you need a guaranteed fallback commit that survives automatic maintenance and manual cleanup. Use rpm-ostree rollback when you want to immediately boot into the previous deployment without modifying the deployment list. Use rpm-ostree cleanup when you are running low on disk space and want to reclaim storage from old, unpinned commits. Use rpm-ostree rebase when you are switching between different Fedora editions or testing a specific stable branch. Stay on the default upgrade cycle if your hardware is standard and you only need temporary rollbacks during the first 24 hours after an update.

Where to go next