One clean update & cleanup script for Kali Linux.
Version: See the VERSION file in this repo (or run ./kali-update.sh --version)
kali-update.sh — The complete update and cleanup script.
Update:
- Refreshes the Kali keyring only when the download matches the pinned archive keyring (SHA-256 and key fingerprints)
- Fixes interrupted installs and broken packages
apt update- Package cache check (
apt-get check) apt upgradeapt full-upgrade
Cleanup:
apt --purge autoremoveapt autoclean+apt clean- Purge residual config files (
apt purge '~c') - Remove old kernels (keeps running kernel +
KERNEL_KEEPothers; default 2), including Kalilinux-binary-*packages - Prefer an HTTPS Kali mirror (
https://http.kali.org/kali, thenhttps://kali.download/kali). An HTTP mirror is used only for that run and is not saved. A third-party repo failure does not change the Kali line - Hold essential packages only during autoremove (a lasting hold blocks their upgrades)
- Remove old snap revisions
- Update + remove unused Flatpaks
- Firmware updates (fwupdmgr)
- Vacuum journal logs (last 30 days)
- Remove regenerable pip / go-build / uv caches (
CLEAN_DEV_CACHES, default on) - Clean partial apt lists
- Update locate database (if present)
- Rebuild man database
- Update GRUB after kernel changes
Other:
- Tracks disk usage before/after (across /, /var, /boot)
- Keeps only the last 3 log files (and their apt-warnings sidecars)
- Counts a failed package update or upgrade as a failed run
- Skips
apt cleanwhen the upgrade did not finish, so downloaded packages can be reused - Color output + clear logging
- Records last run details in /var/lib/kali-update/last-run
- Safety checks (root, internet, disk space, APT lock)
sudo ./kali-update.shOr with options:
sudo ./kali-update.sh --dry-run
sudo ./kali-update.sh --no-kernel
sudo ./kali-update.sh --last # Show last execution details
sudo ./kali-update.sh --check # Run pre-flight checks only
sudo ./kali-update.sh --versionRun periodically (recommended weekly).
Optional KEY=value files (not shell scripts). Unknown keys and shell syntax are ignored.
/etc/kali-update.conf— regular file, root-owned, mode0644or stricter, not a symlink;/etcmust be root-owned and not group/world writable/root/.config/kali-update.confand/root/.kali-update.conf— same rules- When started with
sudo, the invoking account's~/.config/kali-update.confand~/.kali-update.conf, using that account's passwd home (not$HOME). The file must be owned by that user or root and must not be group/world writable.
PATH inside the script is /usr/sbin:/usr/bin:/sbin:/bin.
Variables:
| Variable | Default | Description |
|---|---|---|
LOG_RETENTION |
3 | Number of log files to keep |
KERNEL_KEEP |
2 | Extra kernels to keep besides running |
CLEAN_DEV_CACHES |
true | Remove /root (and sudo user) .cache/{pip,go-build,uv}. Next pip/go/uv job is slower until the cache rebuilds. Set false to skip. |
- Detailed logs:
/var/log/kali-update/ - Only the most recent 3 logs are kept automatically.
- Last run record:
/var/lib/kali-update/last-run
- Must run as root.
- The archive keyring path and
sources.listpath are fixed. The environment cannot redirect them. - A run with no pinned Kali archive keyring skips package updates. The
kali-archive-keyringpackage's same-directory.gpg→.pgpsymlink is accepted; other symlinks at that path are not. - Requires at least 2GB free disk space.
- Keeps running kernel plus
KERNEL_KEEPadditional kernels (default: 2). --dry-runskips state-changing steps (keyring, apt update, holds, purges).- Non-critical steps won't stop the script.
Cron example (weekly):
0 4 * * 0 /path/to/kali-update.shOr use a systemd timer for more control.
- Version is in the
VERSIONfile. - Script also supports
--version. - See
CHANGELOG.mdfor history.
| Command | Description |
|---|---|
./kali-update.sh |
Full update + cleanup |
./kali-update.sh --dry-run |
Show what would happen (no changes) |
./kali-update.sh --no-kernel |
Skip kernel removal |
./kali-update.sh --last |
Show details from last execution |
./kali-update.sh --check |
Run all pre-flight checks only |
./kali-update.sh --version |
Show version + last run info |
This script is designed to be safe for weekly unattended/cron use.
Copyright (C) 2026 wbharris
This project is licensed under the GNU General Public License v3.0 or later (GPL-3.0-or-later).
You may redistribute and/or modify it under the terms of the GPL as published by the Free Software Foundation. See the LICENSE file for the full text.