To securely delete data on Linux, match the tool to the storage. shred works on a whole hard disk or partition, but not reliably on single files or on SSDs. For SSDs, use the drive's own erase: nvme sanitize or nvme format --ses, ATA Secure Erase through hdparm, or LUKS crypto erase when the disk was encrypted from day one.
That is the short answer. The long answer is that a "deleted" file on Linux can survive in free blocks, a journal, a snapshot, swap, a hibernation image, or flash cells the operating system cannot address. This guide covers each layer using current man pages, the nvme-cli docs, kernel documentation and NIST SP 800-88 Revision 2, with a device path check before every destructive command.
Key takeaways
shredassumes in place overwrite. That fails on journaled, copy on write, snapshotting and compressed file systems, and on flash.fstrim, thediscardoption and plainblkdiscardare maintenance, not sanitization.blkdiscard --secureneeds device support and gives no completion log.- NVMe offers Format with
--ses=1(user data erase) or--ses=2(crypto erase), and Sanitize (block erase, overwrite, crypto erase). Check the result withnvme log sanitize(older releases:nvme sanitize-log). - ATA Secure Erase through
hdparmneeds a temporary password, a "not frozen" drive and a direct SATA link. The man page labels it DANGEROUS. cryptsetup eraseremoves every LUKS keyslot but leaves the data area. Any surviving header backup undoes it.- Unencrypted swap and hibernation images can hold secrets "in plaintext on disk", per the kernel docs. Btrfs and LVM thin snapshots keep deleted files.
- NIST SP 800-88 Rev. 2 says multi pass overwrites on overprovisioned SSDs give "very little confidentiality protection". Use a sanitize command or crypto erase for Purge.
Why deleting a file on Linux does not erase it
When you run rm, the kernel removes a directory entry and, once nothing else holds the inode open, marks the file's blocks as free. The bytes stay where they were until something else is written on top. That is the behaviour every recovery tool relies on.
On top of that basic fact, Linux systems add layers that copy data around:
- Journals and copy on write. ext4 in
data=journalmode writes file contents to the journal first; Btrfs and ZFS never overwrite a block in place. - Snapshots. Btrfs and LVM thin snapshots share blocks with their origin, so they keep files you deleted.
- Swap and hibernation. Memory pages, and whole hibernation images, get written to swap.
- The flash translation layer. An SSD maps logical addresses to physical pages, writes land on new pages, and spare capacity stays hidden from the host.
- Backups and mirrors. The
shredman page warns that "backups and mirrors may contain unremovable copies".
Researchers at UC San Diego measured the flash problem directly. In their FAST 2011 paper, Wei, Grupp, Spada and Swanson read raw flash chips after applying common sanitization methods. All of the single file overwrite methods they tried failed: between 4% and 75% of a file's contents remained on the SATA SSDs, and USB drives did no better, at between 0.57% and 84.9%. Their conclusion was that reliable SSD sanitization needs "built-in, verifiable sanitize operations". The rest of this guide is about using those operations correctly.
Before you run anything: check the device path twice
Every command from here on can destroy the wrong disk if the path is wrong. Names like /dev/sda and /dev/nvme0n1 are assigned at boot and can change; the crypttab man page calls them "(unstable)". Build this check into your habits.
Step 1: list disks with identifying details.
lsblk -d -o NAME,MODEL,SERIAL,SIZE,TRAN,ROTA,MOUNTPOINTS,WWN
TRAN shows the transport (sata, nvme, usb). ROTA is 1 for a spinning disk and 0 for flash. Note the model and serial number of the disk you intend to erase, and compare them with the label on the drive or the purchase record.
Step 2: map stable names to kernel names.
ls -l /dev/disk/by-id/
Each link name contains the model and serial, and points at the current kernel name. Use the by-id path in your commands where the tool accepts it.
Step 3: confirm nothing on the disk is mounted or in use.
lsblk -o NAME,FSTYPE,MOUNTPOINTS /dev/DISK
swapon --show
cat /proc/mdstat
If a partition on the target is mounted, in use as swap, or part of a RAID array, stop and fix that first. blkdiscard opens the device in exclusive mode by default since util-linux 2.36 to avoid collisions with a mounted file system; its --force option turns that protection off, so do not use it out of habit.
Step 4: put the path in a variable and echo it.
TARGET=/dev/disk/by-id/nvme-EXAMPLE_MODEL_SERIAL
readlink -f "$TARGET"
lsblk -d -o NAME,MODEL,SERIAL,SIZE "$(readlink -f "$TARGET")"
Model, serial and size should all match step 1. Only then run the destructive command, using "$TARGET" rather than retyping. The same commands are what attackers use to destroy data, which is why defenders track them; see MITRE ATT&CK T1561 disk wipe.
When does shred work, and when is it useless?
shred overwrites a file or device with patterns. The current man page (coreutils) documents the key options:
-n Nsets the number of overwrite passes. The default is 3.-zadds a final pass of zeros to hide the shredding.-udeallocates and removes the file after overwriting. Without it,shredleaves the file in place.--remove=HOWcontrols how the name is removed:unlink,wipeorwipesync(the default).-vshows progress,-xstops rounding file sizes up to a full block,-slimits how many bytes are shredded.
The man page's CAUTION is short and important: "shred assumes the file system and hardware overwrite data in place." The GNU coreutils manual lists where that fails: log structured or journaled file systems (ext3 or ext4 in data=journal mode, Btrfs, NTFS, ReiserFS, XFS, ZFS), RAID based file systems that write redundant data, file systems that make snapshots, file systems that cache in temporary locations such as NFS version 3 clients, and compressed file systems. The manual also notes that SSDs do wear levelling and most devices map out bad blocks invisibly, so shred may never touch the sensitive copy.
So, in practice:
| Target | Does shred help? | Why |
|---|---|---|
One file on ext4 (default data=ordered) on a hard disk | Partly | The manual says default ordered and writeback modes work as usual, but copies in backups, editors' temp files and swap are untouched |
One file on Btrfs, ZFS or ext4 with data=journal | No | Copy on write or data journaling writes elsewhere |
| One file on any SSD or USB stick | No | Wear levelling; the FAST 2011 study found 4% to 75% remained |
| A whole hard disk partition or whole disk | Yes, for Clear | The manual says shredding a device "bypasses file system design issues" |
| A whole SSD | Not reliably | NIST SP 800-88 Rev. 2 says overwriting cannot address spare cells on wear levelled flash |
On pass counts, the GNU manual says that on modern storage devices "a single pass should be adequate", ideally pseudo random rather than zeros because some SSDs may optimise away all zero writes. NIST SP 800-88 Rev. 2 notes that old schemes ran from one pass to as many as 39, and that the US Department of Defense removed overwriting specifications from NISPOM in 2006.
Shredding a whole hard disk
Warning: this destroys every byte on the target device. Run the four step device check above first. Do not run it against a device that holds the system you booted from.
# 1. Identify and confirm (see the device check section)
TARGET=/dev/disk/by-id/ata-EXAMPLE_HDD_SERIAL
lsblk -d -o NAME,MODEL,SERIAL,SIZE,ROTA "$(readlink -f "$TARGET")"
# ROTA must be 1 for this method to make sense
# 2. One random pass with progress, then a zero pass
sudo shred -v -n 1 -z "$TARGET"
Expect hours on a large disk. Data in reallocated sectors is out of reach for shred; use ATA Secure Erase (below) for Purge.
What fstrim, the discard option and blkdiscard do, and whether they sanitize
All three use the same idea: tell the storage device which logical blocks no longer hold useful data, so the device can erase and reuse the flash in the background.
fstrim
fstrim asks a mounted file system to discard blocks it is not using. Useful options from the util-linux man page:
-atrims every mounted file system on devices that support discard.-Atrims file systems listed in/etc/fstab, skipping those with theX-fstrim.notrimoption.-vprints how many bytes were passed down for possible discard. The man page notes that this is an upper bound, because the device may discard less.-nis a dry run.
The man page says that for most desktop and server systems "a sufficient trimming frequency is once a week", and that running fstrim frequently "or even using mount -o discard" might affect the lifetime of poor quality SSDs. If your distribution ships an fstrim.timer systemd unit, systemctl status fstrim.timer shows whether it is active.
lsblk -D # shows DISC-GRAN and DISC-MAX; zero means no discard support
sudo fstrim -av # trim all supported mounted file systems, verbose
The discard mount option
Mounting with -o discard sends a discard every time blocks are freed, instead of in a weekly batch. It does not make deletion secure. Neither the fstrim man page nor the blkdiscard man page promises what a later read of a trimmed block returns, and nothing in a discard forces the device to erase the old flash page right away.
blkdiscard
Warning: the man page says it plainly: "All data in the discarded region on the device will be lost!" Run the device check first.
blkdiscard discards a whole device or a byte range of it, without any file system involved. Options from the current man page:
-oand-lset offset and length. Offsets must be aligned to the device sector size.-s,--secureperforms a secure discard, which also erases copies of the blocks that garbage collection may have created. The man page adds: "This requires support from the device."-z,--zerooutzero fills the range instead of discarding.-f,--forcedisables the exclusive open check.
TARGET=/dev/disk/by-id/ata-EXAMPLE_SSD_SERIAL
lsblk -D -d "$(readlink -f "$TARGET")"
sudo blkdiscard --secure -v "$TARGET"
# If the device rejects a secure discard, the command fails; it does not silently fall back.
Do they sanitize?
Plain discard and fstrim do not. They improve the odds that old data gets erased eventually, but you cannot verify when or whether. blkdiscard --secure is closer, because it asks the device to erase garbage collection copies, but support is device specific and there is no completion log to check. Treat a full device discard as a fast way to empty an SSD you will reuse yourself, and use a sanitize command or crypto erase when the data matters.
What are NVMe Format and NVMe Sanitize?
NVMe drives expose two different erase mechanisms through the nvme tool from the nvme-cli project. Both are worth understanding before you pick one.
First, note the device names. /dev/nvme0 is the controller (a character device). /dev/nvme0n1 is namespace 1 on that controller (a block device). Sanitize works on the controller and the whole NVM subsystem. Format works on a namespace, or on all namespaces depending on the drive.
The nvme-cli documentation adds a warning that matters: the character device number does not indicate which namespaces belong to which controller. If you assume it does, "you may irrevocably erase data on an unintended device." Check with nvme list and lsblk before every run.
NVMe Format with Secure Erase Settings
nvme format reformats a namespace with a chosen LBA format and can erase it at the same time. The --ses option sets Secure Erase Settings:
--ses | Meaning in the nvme-cli docs |
|---|---|
| 0 | No secure erase requested (default) |
| 1 | User Data Erase. Contents afterwards are indeterminate. The controller may use a cryptographic erase if all user data is encrypted |
| 2 | Cryptographic Erase. User data is erased by deleting the encryption key |
| 3 to 7 | Reserved |
Other options: --namespace-id picks a namespace, and the broadcast value 0xffffffff (also written all or -1) targets every namespace. The docs say that if the drive's Format NVM Attributes (FNA) bit 0 is set, a format sent to the character device applies to all namespaces by default. --force skips the warning prompt, so leave it off when running by hand.
Warning:
nvme formatdestroys all data in the target namespace, and possibly in every namespace on the controller. Run the device check first, and confirm withnvme listwhich namespaces exist.
sudo nvme list
TARGET=/dev/nvme0n1 # confirm model and serial in nvme list first
sudo nvme format "$TARGET" --ses=1
# or, if the drive supports cryptographic erase:
sudo nvme format "$TARGET" --ses=2
NVMe Sanitize
Sanitize is a separate command that acts on the whole NVM subsystem rather than one namespace. NIST SP 800-88 Rev. 2 describes dedicated sanitize commands as able to address all storage areas more effectively than host overwrites, with the trade off that you must trust the vendor's implementation. The nvme-cli documentation lists these actions for --sanact (-a):
| Action | Value | Name in nvme-cli |
|---|---|---|
| Exit Failure Mode | 0x01 | exit-failure |
| Block Erase | 0x02 | start-block-erase |
| Overwrite | 0x03 | start-overwrite |
| Crypto Erase | 0x04 | start-crypto-erase |
| Exit Media Verification State | 0x05 | exit-media-verification |
Supporting options from the same page:
--no-dealloc(-d) asks the drive not to deallocate blocks after a successful sanitize.--owpass(-n) sets overwrite passes; 0 means 16.--ovrpatsets a 32 bit pattern and--oipbpinverts it between passes. These apply only to Overwrite.--ause(-u) allows unrestricted sanitize exit. Leaving it cleared means restricted completion mode.- Recent nvme-cli versions also document
--emvs(enter media verification state after success),--preq(fail if the operation would not purge user data, on controllers that support it) and--wait. Runnvme sanitize --helpto see what your installed version supports.
Before you choose an action, check which ones the controller supports. The Identify Controller data includes the sanitize capabilities; read it with nvme id-ctrl /dev/nvme0 (or nvme id ctrl /dev/nvme0 in nvme-cli 3.0 style syntax) and look for the sanicap field, then decode it against the NVMe specification published by NVM Express.
Warning: sanitize erases user data in every namespace on the controller. Run the device check, confirm the controller with
nvme list, and make sure the machine will stay powered until the sanitize log reports completion.
sudo nvme list
CTRL=/dev/nvme0 # the controller, not the namespace
sudo nvme sanitize "$CTRL" --sanact=start-crypto-erase
# or block erase:
sudo nvme sanitize "$CTRL" --sanact=start-block-erase
Crypto Erase is usually the fastest; NIST notes that cryptographic erase can sanitize much faster than other techniques because it works on the keys rather than the data. Block Erase physically erases flash blocks and takes longer. Overwrite is the slowest and puts the most wear on flash; keep it for media where the other two are not supported.
Format or Sanitize?
| Question | NVMe Format with --ses | NVMe Sanitize |
|---|---|---|
| Scope | One namespace, or all, depending on FNA and --namespace-id | Whole NVM subsystem |
| Intended to reach areas the host cannot address | Not stated in the nvme-cli docs | Yes, that is the purpose of a dedicated sanitize command |
| Can change LBA format | Yes | No |
| Progress and result log | No dedicated log | Yes, the sanitize log page |
| Typical use | Re-provisioning a namespace you keep | Retiring, returning or reselling a drive |
How does ATA Secure Erase work with hdparm, and what is a frozen drive?
SATA drives, both hard disks and SSDs, implement the ATA Security feature set. Its SECURITY ERASE UNIT command asks the drive firmware to erase all user data. On Linux you send it with hdparm.
The man page (hdparm 9.65 in Debian testing) is blunt. --security-erase and --security-erase-enhanced are both marked "(DANGEROUS)", as is --security-set-pass. The ATA Security section says the switches "are DANGEROUS to experiment with, and might not work with some kernels", and the feature description says "THIS FEATURE IS EXPERIMENTAL AND NOT WELL TESTED. USE AT YOUR OWN RISK."
The frozen state
A drive in the "frozen" state refuses security commands. The hdparm man page explains that --security-freeze freezes the drive's security settings until the next power on reset and the archived kernel.org ATA wiki explains that a frozen drive usually means the BIOS or operating system sent a SECURITY FREEZE command at boot. You check it like this:
sudo hdparm -I /dev/sdX | grep -A8 -i '^Security'
Look for not frozen. If it says frozen, the wiki lists workarounds: suspend to RAM and resume from a live system (echo -n mem > /sys/power/state), which it reports clears the frozen state on some machines; trying a different motherboard; or hot plugging the drive's SATA data cable while the system runs, which it says may crash the kernel. Never swap power cables on a running PC.
The same wiki is clear on interfaces: "Do not attempt to do this through a USB interface!" USB to SATA bridges, SAS controllers and hardware RAID controllers may reset the drive partway through a long erase. It also says not to use hdparm versions older than 9.31, which had a hard coded two hour timeout that could cut off the erase on large drives.
The procedure
Warning: this erases the whole drive, and an interrupted erase can leave the drive locked. Use a direct SATA connection, a live USB, and run the device check first. Use a throwaway password, never an empty one.
DEV=/dev/sdX # confirm model and serial first
sudo hdparm -I "$DEV" | grep -A10 -i '^Security'
# Must show: supported, not enabled, not locked, not frozen
# The output also estimates erase time, for example "2min for SECURITY ERASE UNIT"
# 1. Set a temporary user password (this enables security)
sudo hdparm --user-master u --security-set-pass Eins "$DEV"
sudo hdparm -I "$DEV" | grep -A10 -i '^Security' # should now show "enabled"
# 2. Issue the erase and wait; do not interrupt it
time sudo hdparm --user-master u --security-erase Eins "$DEV"
# or, if "supported: enhanced erase" is listed and you want it:
# time sudo hdparm --user-master u --security-erase-enhanced Eins "$DEV"
# 3. Confirm security is disabled again
sudo hdparm -I "$DEV" | grep -A10 -i '^Security' # should show "not enabled"
The wiki's example took about 40 seconds on an 80 GB SSD and warns that a 1 TB hard disk "might take 3 hours or more". If the erase fails, the wiki says to use --security-disable with the same password to return the drive to normal.
A caution from the research record: the FAST 2011 study tested 12 SSDs. Eight reported ATA Security support; one encrypted data so it could not be checked, and of the other seven only four executed ERASE UNIT reliably. One reported success while all data remained intact. That was 2011 hardware, but NIST SP 800-88 Rev. 2 makes the same point today: dedicated sanitize commands "require trust and assurance" from the vendor.
The ATA command set also defines a SANITIZE feature set. The current hdparm man pages we checked do not document sanitize options, so this guide does not give commands for it. If your drive supports it, use your drive vendor's documented procedure.
How does LUKS crypto erase work, and what about header backups?
If the disk was encrypted with LUKS from the first byte, every data block is ciphertext under a volume key that exists only in the LUKS header, wrapped by each keyslot. Destroy the keyslots and the ciphertext becomes noise. For the wider limits of this idea, see key destruction and the limits of cryptographic erasure. The cryptsetup man page says LUKS is "designed for fast and secure wiping by just overwriting the header and keyslot area", and that keyslots can be scrubbed thanks to "anti-forensic stripes". NIST SP 800-88 Rev. 2 calls this approach cryptographic erase and classes it as a Purge technique, subject to conditions on the strength of the encryption and on the keys.
The relevant actions:
cryptsetup luksDump DEVICEshows the header and which keyslots are in use.cryptsetup luksKillSlot DEVICE Nwipes keyslot N.cryptsetup luksRemoveKey DEVICEremoves the keyslot that matches the passphrase you supply.cryptsetup erase DEVICE(aliasluksErase) erases all keyslots and makes the container "permanently inaccessible".cryptsetup luksHeaderBackupandluksHeaderRestoresave and restore the header and keyslot area.
The cryptsetup-erase man page spells out the limits. The operation is irreversible without a header backup, and it does not wipe or overwrite the data area; it only removes the keyslots. So the key rule is: a header backup undoes it. If anyone ever ran luksHeaderBackup, that file plus an old passphrase brings the data back. Find and destroy every header backup, escrowed passphrase and key file before you rely on crypto erase.
Warning:
cryptsetup erasemakes all data in the LUKS container unrecoverable unless a header backup exists. Run the device check first and confirm withluksDumpthat you have the right container.
PART=/dev/disk/by-id/nvme-EXAMPLE_SERIAL-part3
sudo cryptsetup luksDump "$PART" | head -20 # confirm it is the expected LUKS container
sudo cryptsetup close cryptroot 2>/dev/null # make sure it is not open
sudo cryptsetup erase "$PART"
sudo cryptsetup luksDump "$PART" | grep -i keyslot # should show no active keyslots
For self encrypting drives managed through LUKS2 OPAL support, the man page describes a separate --hw-opal-factory-reset option that erases all data on the OPAL drive using the drive's PSID. It warns that a header backup cannot recover data from OPAL drives, because the keys are removed from the hardware, and that the PSID should be treated as sensitive because anyone holding it can destroy data on the drive.
When LUKS crypto erase is not enough
Crypto erase only protects data that was encrypted. Check these before you rely on it:
- Was the partition encrypted from first use? If you installed in plaintext and encrypted later, old plaintext may sit in places the encryption never overwrote.
- Is
/bootor the EFI system partition outside LUKS? Usually yes. Those hold kernels and initramfs images, which can include key files or configuration you would not want shared. - Was swap encrypted? If swap lived on a plaintext partition, it needs its own treatment (next section).
- Is the disk an SSD where plaintext was ever written? Flash may hold old plaintext pages in spare area. Combine crypto erase with a device sanitize for Purge.
How do you handle swap, zram and hibernation images?
Swap
Anything in memory can be paged out to swap: decrypted file contents, typed passwords, tokens held by a running program. A plaintext swap partition or swap file is therefore a leak, a storage cousin of the hardware problem in CWE-1330 remanent data after memory erase.
The cleanest fix is to make swap ephemeral. The crypttab man page documents a swap option that formats the device as swap on every boot, and says /dev/urandom "may be used as key file, resulting in a randomized key". Its example line is swap /dev/sda7 /dev/urandom swap. With that setup, each boot uses a fresh random key and the previous boot's swap becomes unreadable. The man page warns that the swap option "will destroy the contents of the named partition during every boot", which is why it recommends stable names such as /dev/disk/by-uuid/ over /dev/sdX.
To wipe an existing plaintext swap partition on a hard disk:
Warning: this destroys the swap partition's contents and its UUID. Confirm the partition with
swapon --showandlsblkfirst.
swapon --show
SWAP=/dev/disk/by-id/ata-EXAMPLE_HDD_SERIAL-part2
sudo swapoff "$SWAP"
sudo shred -v -n 1 "$SWAP" # hard disk only; on SSD use blkdiscard --secure or a sanitize
sudo mkswap "$SWAP" # creates a new UUID; update /etc/fstab or crypttab to match
sudo swapon "$SWAP"
Hibernation images
The kernel's swsusp documentation says hibernation "saves the state of the machine into active swaps". You point it at the image with resume= on the kernel command line, plus resume_offset= when you use a swap file. It also says that without suspend image encryption, "your sensitive data are then stored in plaintext on disk", and that if swap is not reused after resume the data "can remain on disk virtually forever". Its own advice for clearing leftovers after an aborted suspend is to run mkswap on the suspend swap partition early in boot.
An image in swap that uses a fresh random key every boot cannot be resumed. If you need hibernation, keep swap inside your LUKS container; if not, use random key swap and disable hibernation.
zram
zram is different. The kernel documentation describes it as RAM based block devices where pages "are compressed and stored in memory itself". Plain zram swap therefore never touches the disk. The exception is writeback: with CONFIG_ZRAM_WRITEBACK, you can set backing_dev to a partition and write idle or incompressible pages to it. If you configured a backing device, treat that partition like swap. To tear a zram device down cleanly:
sudo swapoff /dev/zram0
echo 1 | sudo tee /sys/block/zram0/reset # frees its memory and sets disksize to zero
How do you verify a sanitize completed?
NIST SP 800-88 Rev. 2 dropped most of the old "verification" language and now talks about validation: checking for errors and anomalies, and for non destructive methods, "checking the completion status of the tools". On Linux, that means reading what the device reports.
NVMe: the sanitize log
sudo nvme log sanitize /dev/nvme0 # nvme-cli 3.0 and later
sudo nvme sanitize-log /dev/nvme0 # older nvme-cli releases; a deprecated alias in 3.0
The nvme-cli documentation lists these status values:
| Status | Meaning |
|---|---|
| 0x0000 | The NVM subsystem has never been sanitized |
| 0x0001 | The most recent sanitize completed successfully |
| 0x0002 | A sanitize is in progress |
| 0x0003 | The most recent sanitize failed |
It also documents a Global Data Erased bit (set if nothing has been written since manufacture or the last successful sanitize) and a Purged bit, which is set when the last sanitize purged user data because Purge Required was set. Run the log once while the sanitize is running to see progress, and again afterwards. Save the output with the drive's model and serial as your record.
If the log shows a failure, the controller may be in a failure state that blocks normal I/O; --sanact=exit-failure is the documented way out, after which you should run the sanitize again.
SATA: hdparm security status
After ATA Secure Erase, hdparm -I should show security not enabled and not locked. That shows the command completed, not that every cell is clean. The FAST 2011 drive that reported success with all data intact is the reason to treat any single status line with some caution.
A sampling check you can do yourself
For any method, read a few regions of the device and look at what comes back. This does not prove sanitization, but it catches the worst failure: a command that did nothing.
DEV=/dev/nvme0n1
sudo dd if="$DEV" bs=1M count=16 status=none | hexdump -C | head
sudo dd if="$DEV" bs=1M skip=100000 count=16 status=none | hexdump -C | head
sudo blkid -p "$DEV" # should find no file system or partition signature
What about LVM thin snapshots and Btrfs snapshots?
Snapshots are the most common reason a "deleted" file survives on a Linux server.
LVM thin provisioning
The lvmthin man page says snapshots are efficient because "the data blocks common to a thin LV and any of its snapshots are shared". Deleting a file inside the origin LV does not free blocks the snapshot still references. The page also says that removing a thin LV and its snapshots returns their blocks to the pool, but warns that this is not always effective because blocks may be shared and free space may be fragmented.
Discards matter here too. A thin pool has a discards mode: ignore, nopassdown or passdown, with passdown the default. In passdown mode, fstrim inside a thin LV can return whole unused chunks to the pool and pass the discard to the physical device. In ignore mode, fstrim has no effect. Check with:
sudo lvs -o lv_name,pool_lv,origin,discards,zero
The zero property controls whether newly provisioned chunks are zeroed; the man page notes that switching it on later does not zero chunks already provisioned.
Btrfs subvolumes and snapshots
The Btrfs documentation says a snapshot initially shares all of its data blocks with the source through copy on write, and that file modifications in a snapshot do not affect the original. The reverse also holds: deleting a file in the live subvolume leaves the snapshot's copy in place. Subvolume deletion happens in two phases, with the actual data removed later by a cleaning step that can take time depending on shared blocks and the queue length.
sudo btrfs subvolume list -s / # list snapshots
sudo btrfs subvolume delete /.snapshots/123/snapshot
sudo btrfs subvolume sync / # wait for the cleaner to finish
sudo fstrim -v /
Automatic pre and post update snapshots can hold weeks of history, so list them before assuming a file is gone.
How do you run these safely from a live USB?
You cannot safely erase the disk you booted from, so boot a live image and work on an idle disk.
- Use a current live image so nvme-cli, hdparm, cryptsetup and util-linux are recent.
- Unplug every disk you are not erasing, including backup drives. This is the single best safety step.
- Identify the target with
lsblkand/dev/disk/by-id/. The live USB shows up as ausbdisk, and kernel names may differ from your installed system. - Check nothing is mounted or used as swap with
lsblk -o NAME,MOUNTPOINTSandswapon --show; a live session may activate swap it finds on disk. - Stay on mains power. An erase that loses power can leave a drive locked or in a failure state.
- Run one destructive command at a time, each after the variable and echo check, then verify and label the drive with what you did and when.
How does each command map to Clear and Purge?
NIST SP 800-88 Rev. 2 defines three methods. Clear applies logical techniques to all user addressable locations, protecting against "simple, non-invasive data recovery techniques" through the normal interface. Purge makes recovery infeasible "using state-of-the-art laboratory techniques" while keeping the media potentially reusable. Destroy does the same but leaves the media unusable. Rev. 2 removed the old media specific tables and points readers to IEEE 2883 for technique details, so the mapping below is our reading of the definitions applied to Linux tools, not a NIST table.
| Linux command | Media | Method it can support | Conditions |
|---|---|---|---|
rm | Any | None | Removes a name only |
shred on a file | Any | None reliable | Fails on journals, CoW, snapshots, flash |
shred or dd over whole device | Hard disk | Clear | Remapped sectors are missed |
shred over whole device | SSD | Not recommended | Spare cells and wear levelling |
fstrim, discard | SSD | None | Maintenance hint only |
blkdiscard --secure | SSD | Clear at best | Device support; no completion log |
nvme format --ses=1 | NVMe | Clear or Purge | Scope and assurance depend on drive |
nvme format --ses=2 | NVMe | Purge (crypto erase) | Drive must encrypt all user data |
nvme sanitize block erase or crypto erase | NVMe | Purge | Check sanitize log for success |
hdparm --security-erase | SATA | Clear or Purge | Firmware quality varies; test |
cryptsetup erase | Any | Purge (crypto erase) | Encrypted from first use; no header backups; no plaintext swap |
| Shredding, disintegration, incineration | Any | Destroy | Use a qualified service |
NIST adds one more warning that applies to every row: degaussing should not be used on flash, and it is no longer considered an approved Destroy technique on its own.
Which method for which situation?
| Situation | Recommended Linux approach |
|---|---|
| Delete one sensitive file you will keep using the machine | Rotate or revoke the secret it held; delete snapshots; rely on full disk encryption |
| Reuse an SSD yourself | blkdiscard of the whole device, or nvme format --ses=1 |
| Sell, return or recycle an NVMe drive | nvme sanitize crypto erase or block erase, then nvme log sanitize |
| Sell or recycle a SATA SSD | ATA Secure Erase over direct SATA, then sampling check |
| Retire a hard disk | ATA Secure Erase, or one random pass of shred over the whole disk |
| Retire a LUKS encrypted laptop fast | cryptsetup erase, destroy header backups, then a device sanitize if time allows |
| Drive is dead or will not accept commands | Physical destruction |
| Cloud volume | Delete volumes and snapshots; crypto erase through the provider's key management |
A complete walkthrough: retiring a Linux laptop with an NVMe drive
This is the sequence for a developer laptop that is being returned or resold.
1. Capture what you need to rebuild. Push work, export installed packages (apt list --installed, dnf list --installed or pacman -Qqe), and keep lockfiles and project SBOMs.
2. Revoke what the machine could use. Revoke SSH keys, cloud and registry tokens and Git credentials at the service. A sanitized drive does not stop a token copied earlier.
3. Find LUKS header backups and escrowed keys for this disk, to delete after the wipe.
4. Boot a live USB and unplug other drives.
5. Identify the controller.
sudo nvme list
lsblk -d -o NAME,MODEL,SERIAL,SIZE,TRAN
ls -l /dev/disk/by-id/ | grep nvme
6. Crypto erase the LUKS container (optional but fast).
Warning: irreversible without a header backup. Confirm the partition with
luksDumpfirst.
sudo cryptsetup luksDump /dev/nvme0n1p3 | head
sudo cryptsetup erase /dev/nvme0n1p3
7. Sanitize the drive.
Warning: erases every namespace on the controller. Confirm model and serial in
nvme list.
sudo nvme id-ctrl /dev/nvme0 | grep -i sanicap
sudo nvme sanitize /dev/nvme0 --sanact=start-crypto-erase
If crypto erase is not supported, use --sanact=start-block-erase.
8. Wait and verify.
sudo nvme log sanitize /dev/nvme0 # or: nvme sanitize-log /dev/nvme0
sudo blkid -p /dev/nvme0n1 # expect nothing
9. Record it. Save the sanitize log, drive model and serial, date, method and who ran it; NIST SP 800-88 Rev. 2 lists the verification method and the people involved among record fields.
10. Delete the header backups and escrowed keys you found in step 3.
11. Rebuild the replacement machine from lockfiles, not from memory, so the new environment starts from known dependency versions.
Where Safeguard fits, honestly
Safeguard does not erase disks, scan firmware, manage devices or detect malware, and nothing in this guide depends on it. The link is the step after the wipe: a rebuilt developer machine pulls every project's dependencies again, and that is when a version you had moved away from can quietly return. Safeguard scans repositories, container images and SBOM files for known vulnerabilities (safeguard scan --dir .), shows which projects contain a given component and version, and can open fix pull requests when autonomous remediation is turned on. The local runner and offline mode, described in how the local runner and offline mode work, keep those checks running on a rebuilt or air gapped Linux box without moving code elsewhere.
Common mistakes
- Running
shred -uon a file on Btrfs, ZFS or an SSD and calling it done. The GNU manual lists these as cases where shred is not effective, and research measured large remnants on SSDs. - Trusting
fstrimordiscardas secure deletion. They are hints for performance and wear, with no completion guarantee. - Targeting
/dev/sdXnames copied from an old note. Names change between boots and between installed and live systems. Use/dev/disk/by-id/and check model and serial. - Confusing
/dev/nvme0and/dev/nvme0n1. Sanitize goes to the controller and affects all namespaces. Format goes to a namespace, but may hit all of them depending on FNA. - Attempting ATA Secure Erase through a USB enclosure. The kernel ATA wiki warns against it and reports a bricked drive.
- Leaving LUKS header backups lying around after a crypto erase. A header backup reverses the erase.
- Forgetting swap, hibernation and snapshots. Each keeps copies of data you thought was gone.
- Not keeping a record of the sanitize log and drive serial.
FAQ
How do I securely delete a file on Linux?
For one file on an SSD or a copy on write file system, you cannot do it reliably with shred. The practical approach is to keep the disk encrypted, delete the file and any snapshots that hold it, run fstrim, and rotate any secret the file contained. On a hard disk with ext4 in default mode, shred -u -n 1 -z file overwrites the file in place, but copies elsewhere remain.
Does shred work on SSDs?
Not reliably. The GNU coreutils manual says SSDs do wear levelling and that shred assumes in place overwrite. The FAST 2011 study found 4% to 75% of a file remained on SATA SSDs after single file overwrite methods. Use nvme sanitize, ATA Secure Erase or LUKS crypto erase for SSDs.
Is blkdiscard a secure erase?
Plain blkdiscard is not. blkdiscard --secure asks the device to also erase copies made by garbage collection, and the man page says this requires device support. There is no completion log, so for drives leaving your control, prefer NVMe Sanitize or ATA Secure Erase.
What is the difference between nvme format and nvme sanitize?
Format with --ses erases a namespace (or all namespaces) and can change the LBA format; --ses=1 is a user data erase and --ses=2 is a cryptographic erase. Sanitize works on the whole NVM subsystem, offers block erase, overwrite and crypto erase, and reports progress and results in the sanitize log.
How do I check if an NVMe sanitize finished?
Run nvme log sanitize /dev/nvme0 on nvme-cli 3.0 or later, or nvme sanitize-log /dev/nvme0 on older releases. A status of 0x0001 means the most recent sanitize completed successfully; 0x0002 means it is still in progress and 0x0003 means it failed.
Why does hdparm say my drive is frozen?
The BIOS or firmware usually sends a security freeze at boot so nothing can set a drive password. A frozen drive refuses security commands until the next power on reset. The archived kernel ATA wiki suggests suspending to RAM and resuming from a live system, which clears the state on some machines.
Is cryptsetup erase enough before selling a laptop?
It is a fast cryptographic erase if the disk was encrypted from first use, swap was inside LUKS or used a random key, and no header backups or escrowed keys survive. Because flash may still hold plaintext written before encryption, add an NVMe sanitize or ATA Secure Erase when the drive leaves your control.
How do I wipe swap on Linux?
Turn it off with swapoff, overwrite or discard the partition depending on the media, and recreate it with mkswap, then update the UUID in /etc/fstab. Going forward, use encrypted swap, either inside LUKS or with a random key per boot through crypttab.
Fix it without waiting for upstream
Wiping a Linux machine is the easy part; rebuilding it means every project pulls its open source dependencies, container images and toolchains again, and the same is true of disk utilities like nvme-cli, util-linux and cryptsetup, which are themselves open source packages inside your images. Safeguard does not touch the disk, so the fit here is indirect, but the rebuild is exactly when old vulnerable versions slip back in, and that part is worth closing.
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.
3. Gold Registry: start from components that are already fixed
registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | The Gold scan GitHub Action in CI, plus Safeguard policies and gates |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch (early access) |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
See how Safeguard would help
None of these demos erase a drive. They show the software side once a sanitized Linux machine has been rebuilt and is back in use. You can download the CLI from https://safeguard.sh/download and read the setup guide at https://docs.safeguard.sh/docs/cli .
The first demo sets up the Safeguard runner on your own machine, approves it with its device code, and then scans from the terminal. On a freshly installed Linux workstation or homelab server, this is how you get dependency inventory and vulnerability checks working again without sending project code anywhere else.
Click through it at your own pace, or open it full screen.
The second demo is a real CLI session. After install, safeguard opens the interactive terminal, you ask it to fix the lodash CVE in a repo, and it reads the finding and advisory, asks before each command, edits package.json to lodash 4.17.21, runs npm install and npm test with your approval, prints a summary and pushes nothing. After a rebuild, the same flow catches a vulnerable version that came back with the first npm install, and the approval step means nothing runs on the new machine without your say.
Click through it at your own pace, or open it full screen.
Quick check
Why is shred not a reliable way to delete one file on an SSD or Btrfs?
Because shred assumes data is overwritten in place. SSDs remap writes for wear levelling and Btrfs writes new copies elsewhere, so the original blocks survive. Research on SATA SSDs found 4% to 75% of a file remained after single file overwrite methods.
What can undo a cryptsetup erase?
A LUKS header backup. The erase only removes the keyslots and leaves the encrypted data area in place, so restoring an old header with a known passphrase brings the data back. Destroy every header backup and escrowed key before relying on crypto erase.
Sources
- man7.org: shred(1)
- GNU coreutils manual: shred invocation
- man7.org: fstrim(8)
- man7.org: blkdiscard(8)
- man7.org: lsblk(8)
- nvme-cli documentation: nvme-format
- nvme-cli documentation: nvme-sanitize
- nvme-cli documentation: nvme-log-sanitize
- nvme-cli documentation: nvme-sanitize-log (deprecated alias)
- nvme-cli documentation: nvme-id-ctrl
- NVM Express: specifications
- man7.org: hdparm(8)
- Debian manpages: hdparm(8), version 9.65
- kernel.org archived ATA wiki: ATA Secure Erase
- man7.org: cryptsetup(8)
- man7.org: cryptsetup-erase(8)
- man7.org: crypttab(5)
- Linux kernel documentation: zram
- Linux kernel documentation: swsusp
- man7.org: lvmthin(7)
- Btrfs documentation: Subvolumes
- NIST SP 800-88 Rev. 2, Guidelines for Media Sanitization (CSRC page)
- NIST SP 800-88 Rev. 2 (PDF)
- Wei, Grupp, Spada, Swanson: Reliably Erasing Data From Flash-Based Solid State Drives (FAST 2011)
Last reviewed: 23 October 2026. Tool options change between releases; check man and --help on your installed versions before running any command here.