first commit

This commit is contained in:
2026-09-05 12:14:36 +03:00
commit 5930fd7ab5
8 changed files with 217 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
*.sh text eol=lf
*.hook.chroot text eol=lf
Dockerfile text eol=lf
+9
View File
@@ -0,0 +1,9 @@
FROM debian:trixie
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
live-build ca-certificates debootstrap xorriso squashfs-tools dosfstools \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /work
ENTRYPOINT ["/bin/sh", "-c", "tr -d '\\r' < /work/build.sh | EP_ERASER_ROOT=/work /bin/sh"]
+36
View File
@@ -0,0 +1,36 @@
# EP Eraser
EP Eraser is a small Debian Live image for securely retiring SATA/NVMe SSDs and rotational HDDs. It boots into a text console inspired by DBAN, but uses device-specific erase methods instead of overwriting every disk indiscriminately.
## Safety model
- The tool requires an exact device name and a typed `ERASE` confirmation.
- It refuses mounted devices, the live boot device, read-only devices, and devices with mounted descendants.
- SSDs use `blkdiscard --secure` where supported, with NVMe sanitize as an option.
- HDDs use a three-pass `shred` overwrite followed by a device-state/status check.
- Every operation is logged to `/var/log/ep-eraser.log` and a summary is written to the target's parent device metadata only when supported.
No software can guarantee recovery resistance for every controller, reserved area, remapped sector, or damaged drive. For high-assurance disposal, combine this image with the drive vendor's sanitize command or physical destruction according to your organization's policy.
## Build
Build from Debian/Ubuntu, WSL, or Docker. The builder must run as root because `live-build` creates a chroot.
```sh
sudo ./build.sh
```
The output is `build/ep-eraser-amd64.hybrid.iso`. Write it to a USB drive with a tool such as Rufus or `dd`. Verify the output checksum before deployment.
To build without installing packages on the host, use Docker from Linux or WSL:
```sh
docker build -t ep-eraser-builder .
docker run --rm -v "$PWD:/work" ep-eraser-builder
```
## Use
Boot the target machine from the image, inspect the disk list, and choose the exact device path. The program detects rotational media and presents the appropriate operation. Reboot after completion; do not remove the USB device until the result is shown.
This project intentionally does not include an automatic wipe-all mode.
+31
View File
@@ -0,0 +1,31 @@
#!/bin/sh
set -eu
if [ "$(id -u)" -ne 0 ]; then
echo "Run this builder as root (or use the Dockerfile)." >&2
exit 1
fi
ROOT=${EP_ERASER_ROOT:-$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)}
cd "$ROOT"
rm -rf build
mkdir -p build
lb config \
--distribution trixie \
--architectures amd64 \
--binary-images iso-hybrid \
--debian-installer false \
--archive-areas "main contrib non-free-firmware" \
--apt-recommends false \
--bootappend-live "boot=live components username=eraser hostname=ep-eraser" \
--iso-application "EP Eraser" \
--iso-publisher "EP Eraser Project" \
--iso-volume "EP_ERASER" \
--image-name "ep-eraser" \
--source false
lb build
mv ./*.hybrid.iso build/ep-eraser-amd64.hybrid.iso
sha256sum build/ep-eraser-amd64.hybrid.iso > build/ep-eraser-amd64.hybrid.iso.sha256
echo "Built build/ep-eraser-amd64.hybrid.iso"
@@ -0,0 +1,4 @@
#!/bin/sh
set -eu
chmod 0755 /usr/local/sbin/ep-eraser
systemctl enable ep-eraser.service
@@ -0,0 +1,19 @@
[Unit]
Description=EP Eraser console
After=local-fs.target systemd-udev-settle.service
Wants=systemd-udev-settle.service
[Service]
Type=simple
ExecStart=/usr/local/sbin/ep-eraser
StandardInput=tty
StandardOutput=tty
StandardError=tty
TTYPath=/dev/tty1
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
Restart=no
[Install]
WantedBy=multi-user.target
@@ -0,0 +1,107 @@
#!/usr/bin/env bash
set -Eeuo pipefail
LOG=/var/log/ep-eraser.log
exec > >(tee -a "$LOG") 2>&1
die() { printf '\nERROR: %s\n' "$*" >&2; read -r -p 'Press Enter to return to the menu...' _; }
mounted() {
findmnt -rn -S "$1" >/dev/null 2>&1 && return 0
lsblk -nrpo NAME,MOUNTPOINTS "$1" | awk 'NF > 1 && $2 != "" { found=1 } END { exit !found }'
}
is_live_device() {
local live parent
live=$(findmnt -rn -o SOURCE /run/live/medium 2>/dev/null || true)
[ -n "$live" ] || return 1
parent=$(lsblk -dnro PKNAME "$live" 2>/dev/null || true)
[ -n "$parent" ] && [ "$1" = "/dev/$parent" ]
}
disk_info() {
lsblk -dnpo NAME,TYPE,SIZE,MODEL,SERIAL,TRAN | awk '$2 == "disk" { print }'
}
choose_disk() {
mapfile -t disks < <(lsblk -dnpo NAME,TYPE | awk '$2 == "disk" { print $1 }')
[ "${#disks[@]}" -gt 0 ] || { die 'No whole disks were detected.'; return 1; }
printf '\nDetected disks:\n\n'
printf '%-4s %-18s %-10s %-24s %-16s %s\n' '#' DEVICE SIZE MODEL SERIAL TRAN
disk_info | nl -w2 -s' '
printf '\nEnter the number shown above, or q to quit: '
read -r choice
[ "$choice" = q ] && exit 0
[[ "$choice" =~ ^[0-9]+$ ]] || { die 'Invalid selection.'; return 1; }
target=${disks[$((choice - 1))]:-}
[ -n "$target" ] || { die 'Invalid selection.'; return 1; }
}
validate_target() {
[ -b "$target" ] || { die 'Selected path is not a block device.'; return 1; }
[ "$(lsblk -dnro TYPE "$target")" = disk ] || { die 'Only whole disks may be erased.'; return 1; }
[ "$(lsblk -dnro RO "$target")" = 0 ] || { die 'The disk is read-only.'; return 1; }
mounted "$target" && { die 'The disk or one of its partitions is mounted.'; return 1; }
is_live_device "$target" && { die 'The live boot device cannot be erased.'; return 1; }
}
confirm() {
local info
info=$(lsblk -dnpo NAME,SIZE,MODEL,SERIAL "$target")
printf '\nTARGET: %s\n%s\n\nThis permanently destroys all data. Type ERASE to continue: ' "$target" "$info"
read -r answer
[ "$answer" = ERASE ] || { printf 'Cancelled.\n'; return 1; }
}
erase_ssd() {
printf '\nSSD/NVMe erase options:\n1) Secure discard (blkdiscard --secure)\n2) NVMe sanitize (NVMe only)\n3) Cancel\nChoose: '
read -r method
case "$method" in
1)
blkdiscard --secure --force "$target" || { die 'Secure discard failed; no data was overwritten.'; return 1; }
;;
2)
[[ "$target" == /dev/nvme*n* ]] || { die 'NVMe sanitize requires an NVMe namespace.'; return 1; }
nvme sanitize "$target" -a 2 || { die 'NVMe sanitize failed.'; return 1; }
nvme sanitize-log "$target" -H || true
;;
*) printf 'Cancelled.\n'; return 1 ;;
esac
}
erase_hdd() {
printf '\nHDD erase uses three random overwrite passes plus a zero pass. Continue? [yes/no]: '
read -r answer
[ "$answer" = yes ] || { printf 'Cancelled.\n'; return 1; }
shred --verbose --iterations=3 --zero --force "$target"
}
verify() {
printf '\nFinal device state:\n'
lsblk -dnpo NAME,TYPE,SIZE,MODEL,SERIAL "$target"
printf 'Erase command completed. Verification is limited to command/device status.\n'
}
main() {
[ "$(id -u)" -eq 0 ] || { echo 'This tool must run as root.' >&2; exit 1; }
printf '\nEP ERASER - destructive disk sanitization\n==========================================\n'
while true; do
choose_disk || continue
validate_target || continue
rotational=$(lsblk -dnro ROTA "$target")
if [ "$rotational" = 1 ]; then
operation=HDD
else
operation=SSD/NVMe
fi
printf '\nDetected media type: %s\n' "$operation"
confirm || continue
if [ "$operation" = HDD ]; then erase_hdd; else erase_ssd; fi
verify
printf '\nPress Enter to return to the disk menu, or type q to quit: '
read -r answer
[ "$answer" = q ] && exit 0
done
}
main "$@"
@@ -0,0 +1,8 @@
bash
coreutils
hdparm
nvme-cli
parted
smartmontools
util-linux
whiptail