42.5 Disabling Unnecessary Services and Removing Unused Packages
Alright, let’s get our hands dirty. Think of your freshly installed Linux server not as a pristine, minimalist work of art, but as a cluttered garage. The previous owner (the distribution maintainer) left all sorts of stuff in there “just in case.” A service for serving Gopher pages? A package for dial-up modem configuration? It’s in there, collecting dust and, more importantly, presenting a lovely attack surface for anyone who fancies a poke around.
Our job is to be the ruthless organizer. We’re going to turn this garage into a well-lit, concrete-floored space with nothing in it but the tools we actually need. Every unnecessary service is an open window; every unused package is a forgotten key under the mat. We’re going to board up the windows and change the locks.
First, See What You’re Working With
You can’t disable what you don’t know exists. Our first stop is to get a lay of the land. Most modern systems use systemd, so we’ll start there. The following command is your new best friend. It lists all currently running services.
systemctl list-units --type=service --state=running
The output can be verbose. To see which services are set to start automatically at boot—a crucial list—use this:
systemctl list-unit-files --type=service --state=enabled
This shows you the culprits that will happily resurrect themselves after a reboot. For a more traditional SysVinit perspective or just a different view, service --status-all can also be useful, but systemd is the king now.
On the package side, you need to know what’s actually installed. Different distributions use different package managers, but the concept is identical.
On Debian/Ubuntu systems:
dpkg -l
On RHEL/CentOS/Fedora systems:
rpm -qa
Or, better yet, use the higher-level tools that manage dependencies: apt list --installed for Debian/Ubuntu or dnf list installed for newer Fedora/RHEL.
The Art of the Purge: Removing Packages
Simply stopping a service is a temporary fix. A package update or a reboot could bring it right back. The permanent solution is to remove the software entirely. This is where we separate the cautious from the reckless.
The key is to understand dependencies. Your package manager won’t let you remove a package that another installed package explicitly depends on. This is good; it keeps you from accidentally nuking your entire desktop environment by removing a font package. The real danger lies in suggested or recommended packages—often installed by default but not strictly required.
Let’s say you found telnetd, the Telnet server daemon. Using Telnet for anything in the 21st century is like sending your password on a postcard, so let’s get rid of it.
On Debian/Ubuntu, we use apt purge. The purge command is brilliant—it removes the package and its configuration files. A normal remove leaves config files lying around like ghosts of bad decisions past.
sudo apt purge telnetd
But what if you try to remove a bigger, more integrated package? apt will show you a list of other packages that will be removed alongside it. READ THIS LIST. Every. Single. Time. It might want to remove half your system because you’re trying to purge a library something else uses. If the list looks insane, hit ’n’ for no and abort.
For RHEL-based systems, the equivalent is dnf remove or yum remove. They’re equally effective but don’t automatically purge config files from /etc; you might have to hunt those down manually later, which is a bit of a design flaw, honestly.
Disabling Services Without Uninstalling
Sometimes, you can’t remove the package. Maybe another critical package depends on it (a common and frustratingly circular situation), or you might need the client component but not the server. For example, you likely need openssh-client to connect to other machines, but you may not need openssh-server running on your laptop.
First, stop the service immediately:
sudo systemctl stop sshd
This slams the door shut right now. But to prevent it from starting on the next boot, you need to disable it:
sudo systemctl disable sshd
Crucially, disable and stop are two separate steps. I can’t tell you how many times I’ve seen someone do one but not the other. Do both.
A pro tip: use mask for the truly heinous stuff you never, ever want to start, even manually. Masking creates a symbolic link to /dev/null that prevents the service from being started by anything.
sudo systemctl mask sshd
Use this power wisely. Masking a service that a critical system component tries to start can cause boot failures. It’s the tactical nuke of service management.
A Practical Walkthrough: Debian Web Server
Let’s say you’re hardening a Debian server destined to be a web host running Nginx. What don’t you need?
- Exim4 or Sendmail? Probably not. You’re not sending mail from this box.
sudo apt purge exim4* - RPCbind? A relic from the Sun NFS days with a history of vulnerabilities. Unless you’re mounting NFS shares, nuke it.
sudo apt purge rpcbind - Cups? A print server on a web head? Absurd.
sudo apt purge cups* - Avahi-daemon? The mDNS service that shouts your server’s name to the local network. Great for a laptop, terrible for a server.
sudo apt purge avahi-daemon
After each purge, your apt will show you the damage plan. Approve it if it makes sense. After a round of purges, do a sudo apt autoremove to clean up any orphaned dependencies that are now just taking up space. It’s like taking out the trash after your purge-fest.
The goal is simple: fewer things running, fewer things installed, fewer things that can go wrong. It’s the most fundamental and effective step in security hardening. Now, let’s go lock some other doors.