Skip to content

About

Debian/Ubuntu system update and cleanup script

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

debian_ubuntu_update_clean

One update and cleanup script for Debian and Ubuntu (and other apt-based derivatives).

Version: VERSION file, or ./update-clean.sh --version. See CHANGELOG.md for history.

For Ubuntu AI / GPU compute blades, see ai_blade_ubuntu_update_clean.

What it does

Update: fix interrupted installs, then apt-get update / upgrade / full-upgrade and apt-get check. Mutating work uses apt-get, not apt(8).

Cleanup: purge autoremove, autoclean, residual configs, old kernels (running + the KERNEL_KEEP newest extras), Snap/Flatpak when present, fwupd when installed, journal vacuum (JOURNAL_VACUUM_TIME, default 30d), optional regenerable pip/go/uv caches (CLEAN_DEV_CACHES, default off), partial apt lists, man/locate DBs, GRUB after kernel changes.

Also: Debian vs Ubuntu archive host for connectivity, disk change on / /var /boot, log rotation, last-run record, root / disk / APT-lock checks.

Usage

sudo ./update-clean.sh
sudo ./update-clean.sh --dry-run
sudo ./update-clean.sh --check
sudo ./update-clean.sh --last
sudo ./update-clean.sh --no-kernel
sudo ./update-clean.sh --reboot-if-required
sudo ./update-clean.sh --offline

--dry-run skips apt-get update and logs planned apt commands. It may still use the network for read-only listings.

Kernel keep count, log retention, and similar knobs live in the config file, not as extra flags. See update-clean.conf.example.

Requires Bash 4+ (#!/usr/bin/env bash). Do not run under /bin/sh.

Install

From the latest GitHub Release (no version pin):

curl -fsSL -o debian_ubuntu_update_clean.tar.gz \
  https://github.com/wbharris/debian_ubuntu_update_clean/releases/latest/download/debian_ubuntu_update_clean.tar.gz
tar -xzf debian_ubuntu_update_clean.tar.gz
cd debian_ubuntu_update_clean
sudo install -m 755 update-clean.sh /usr/local/sbin/update-clean.sh
sudo cp systemd/update-clean.service systemd/update-clean.timer /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now update-clean.timer

From git (development):

git clone https://github.com/wbharris/debian_ubuntu_update_clean.git
cd debian_ubuntu_update_clean
sudo install -m 755 update-clean.sh /usr/local/sbin/update-clean.sh

Run weekly. Prefer a maintenance window if you use --reboot-if-required.

Exit codes

Code Meaning
0 Success
1 One or more steps failed (FAILURES in the last-run record)

Inspect modes (--check, --last, --version) do not take the instance lock.

Configuration

Sourced in order if present:

  • /etc/update-clean.conf (must be root-owned)
  • As root: /root/.config/update-clean.conf, /root/.update-clean.conf
  • Via sudo: also the invoking user's ~/.config/update-clean.conf and ~/.update-clean.conf
  • As a normal user: $HOME/.config/update-clean.conf, $HOME/.update-clean.conf
KERNEL_KEEP=2
BACKUP_MODE=false
REBOOT_IF_REQUIRED=false

/etc/update-clean.conf must be owned by root. World-writable configs are skipped. User-level configs are still only as trustworthy as the account that wrote them.

Config loads after CLI parsing; explicit flags win.

Variable Default Meaning
KERNEL_KEEP 2 Newest extra kernels besides the running one (oldest extras are purged)
BACKUP_MODE false Tar /etc before purging residual configs (excludes /etc/ssl/private)
REBOOT_IF_REQUIRED false Auto-reboot when /var/run/reboot-required is set
LOG_RETENTION 3 Runs to keep under /var/log/update-clean (log and its .apt-warnings sidecar)
JOURNAL_VACUUM_TIME 30d journalctl --vacuum-time window
CLEAN_DEV_CACHES false If true, remove /root (and sudo user) .cache/{pip,go-build,uv}. Off by default so servers do not rebuild package caches every week.

Further keys (LOG_DIR, LOCKFILE, APT_LOCK_WAIT_SECS, ADMIN_EMAIL, CRITICAL_PACKAGES, …) are in update-clean.conf.example.

Recommended packages: psmisc or lsof (APT lock holders), jq (last-run JSON and snap cleanup).

Logging

  • Logs: /var/log/update-clean/ (retention via LOG_RETENTION). A run's .apt-warnings sidecar lists apt/dpkg warnings and errors only; routine apt output stays in the main log.
  • Last run: /var/lib/update-clean/last-run
  • JSON (when jq is installed): /var/lib/update-clean/last-run.json
  • sudo ./update-clean.sh --last prints the record and the last 80 log lines
  • Disk change is df on /, /var, /boot only. If usage grew, the summary says it increased (not a negative “freed”)
  • needrestart (if installed) only lists services that need a restart; this script does not restart them

Safety

  • Root required except --check / --version / --last / --help
  • Needs at least 2 GB free on / and /var; /boot hard abort is 100 MB
  • Keeps the running kernel plus the KERNEL_KEEP newest other images. Recovery: GRUB → previous kernel
  • --reboot-if-required reboots if /var/run/reboot-required exists (including from a prior run)
  • Non-critical steps do not abort the run
  • The bundled timer does not pass --reboot-if-required

Scheduling

Weekly, Sunday 04:00:

0 4 * * 0 /usr/local/sbin/update-clean.sh

Or the bundled timer:

sudo install -m 755 update-clean.sh /usr/local/sbin/update-clean.sh
sudo cp systemd/update-clean.service systemd/update-clean.timer /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now update-clean.timer

Supported systems

Debian (stable, testing, unstable), Ubuntu (LTS and interim), and other apt-based derivatives (Kali, Mint, Pop!_OS, …). Not all derivatives are tested.

Repo Focus
update_clean Kali
debian_ubuntu_update_clean General Debian/Ubuntu
ai_blade_ubuntu_update_clean Ubuntu AI / GPU blades
update-clean.sh
VERSION / CHANGELOG.md / README.md / LICENSE
update-clean.conf.example
systemd/                 # optional weekly timer
.github/workflows/       # ShellCheck + release
scripts/package-release.sh
tests/                   # Ubuntu 22.04 / 24.04 / 26.04 / Debian 12 harness

Testing

sudo ./tests/simulate_ubuntu.sh
sudo ./tests/run_real_host.sh

simulate_ubuntu.sh bind-mounts Ubuntu 22.04, Ubuntu 24.04, Ubuntu 26.04, and Debian 12 os-release files in a private mount namespace (no Docker). It sources update-clean.sh (CLI skipped) so held-kernel tests use DPKG_STATUS_INSTALLED_RE from the script. HTML report: tests/last-results.html.

run_real_host.sh is a live root harness on this machine: --check, a 90s --dry-run (no dpkg --configure / no apt-mark hold / no unbounded sync), held-kernel listing, and EFI grub-pc skip. It isolates logs and the instance lock under $TMPDIR.

License

Copyright (C) 2026 wbharris

GNU General Public License v3.0 or later (GPL-3.0-or-later).

About

Debian/Ubuntu system update and cleanup script

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages