A server should run only what it needs. Every extra package is something to patch, every extra service uses memory, and every listening port is something to attack. Ubuntu Server images are already fairly lean, but there’s usually more you can trim, especially on a small VPS. Here’s a careful approach.

Why minimal is better

  • Security: fewer packages means fewer vulnerabilities, and fewer open ports.
  • Resources: more free RAM and CPU for your applications on small plans.
  • Simplicity: fewer moving parts to understand, update and debug.
  • Faster updates and backups.

1. See what’s running and listening

systemctl list-units --type=service --state=running
ss -tulpn                        # listening ports and their programs
systemd-analyze blame | head     # services slowing down boot

See ss and netstat and systemctl commands.

Every listening service should be one you intend to run. Typical expected ones: sshd, your web server, your database (bound to localhost), and systemd-resolved on 127.0.0.53.

2. See what’s installed

apt list --installed | wc -l
apt-mark showmanual                           # packages explicitly installed
dpkg-query -Wf '${Installed-Size}\t${Package}\n' | sort -n | tail -20   # biggest packages

3. Common candidates to remove on a VPS

Review each one before removing it. What’s safe depends on your setup.

Package / service Why you might remove it
snapd If you don’t use snaps (it runs a daemon and mounts loop devices). See snap packages
ModemManager, wpasupplicant, bluez No modems, Wi-Fi or Bluetooth on a VPS
multipath-tools Only for SAN multipath storage
cups, avahi-daemon Printing and mDNS, not needed on servers
apport, whoopsie Crash reporting to Canonical
lxd-agent-loader, open-iscsi Only for specific environments
Old kernels apt autoremove keeps the current and one previous
sudo apt purge snapd ModemManager
sudo apt autoremove --purge

Don’t remove cloud-init without understanding your provider’s setup, nor openssh-server, systemd-*, networking packages (netplan.io), or ubuntu-minimal / ubuntu-server metapackages, without checking what they’d take with them. apt shows the list before removing: read it.

Stop a service without uninstalling: sudo systemctl disable --now avahi-daemon.

4. Install less in the future

APT installs recommended packages by default, which often pulls in extras. Skip them per command:

sudo apt install --no-install-recommends nginx

Or globally (more aggressive; some packages then lack optional features):

# /etc/apt/apt.conf.d/99norecommends
APT::Install-Recommends "false";

Prefer packages over tools that install entire stacks unless you need them, and use containers for apps with many dependencies. See Docker on a VPS.

5. Clean up

sudo apt autoremove --purge
sudo apt clean
sudo journalctl --vacuum-size=200M
dpkg -l | awk '/^rc/{print $2}' | xargs -r sudo dpkg --purge    # leftover configs of removed packages

See disk full troubleshooting.

6. Keep it minimal

  • Document what you install, and why (a README, or an Ansible playbook). See Ansible playbooks.
  • Review ss -tulpn and apt-mark showmanual every few months.
  • Keep automatic security updates for what remains. See automatic security updates.

Before and after

Measure the effect: note free -h, the number of running services, and ss -tulpn output before you start, and compare afterwards. On a small 1–2 GB VPS, removing unneeded daemons often frees 100–300 MB of RAM, and the list of listening ports usually shrinks to exactly the services you meant to expose.

Quick reference

Task Command
Running services systemctl list-units --type=service --state=running
Listening ports ss -tulpn
Manually installed apt-mark showmanual
Remove + config apt purge <pkg> && apt autoremove --purge
No recommends apt install --no-install-recommends …
Disable a service systemctl disable --now <svc>

Related: Ubuntu 24.04 initial server setup and Linux server hardening checklist.

  • Ubuntu
  • Security
  • Performance