Linux and open source

Diagnose a failed Linux service with systemd

nginx won't start on a fresh server. Find the real cause with systemctl, journalctl and ss, then fix it so it survives a reboot.

  • Beginner
  • About 20 minutes (plus 15 for the real VM)
  • Command line
  • Simulation + real-world
  • Published 26 October 2026

The scenario

You installed nginx, but the site won't load and the service shows as failed. The configuration test passes, so something else is in the way. The same four commands solve most service failures.

At a glance

Before you start

  • Able to type commands in a Linux terminal
  • For the real-world part, an Ubuntu or Debian virtual machine you can break (not a production server)

Tools

  • systemctl
  • journalctl
  • ss
  • nginx -t
  • curl

You'll be able to

You can go from "the service failed" to the exact cause using status, logs and listening ports, and make a fix that persists after a reboot.

Try it

Browser simulation. Runs entirely in your browser. Nothing connects to real systems.

This simulation needs JavaScript. Here is a short sample of how a session goes:

$ systemctl status nginx
× nginx.service - A high performance web server and a reverse proxy server
     Active: failed (Result: exit-code)

$ journalctl -u nginx -n 20 --no-pager
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)

$ sudo ss -tlnp
LISTEN 0 511 *:80 *:* users:(("apache2",pid=812,fd=4),...)

$ sudo systemctl disable --now apache2
Removed "/etc/systemd/system/multi-user.target.wants/apache2.service".

$ sudo systemctl restart nginx && curl -I http://localhost
HTTP/1.1 200 OK
Server: nginx/1.24.0 (Ubuntu)

The four commands that solve most service failures

Question Command
What state is the service in? systemctl status nginx
What did it say when it failed? journalctl -u nginx -n 20 --no-pager
Is the configuration valid? sudo nginx -t
Who is using the port? sudo ss -tlnp

Work through them in that order in the simulation above. The goal tracker at the top turns green when nginx is serving on port 80 and the fix will survive a reboot.

What’s actually going on

The journal tells you bind() to 0.0.0.0:80 failed (98: Address already in use). Only one program can listen on a given port, and ss shows that apache2 already holds port 80. Installing both web servers is an easy accident: they both default to port 80, and whichever starts first wins.

Two clues worth noticing:

  • curl -I http://localhost still returns 200 OK, but the Server: header says Apache. “The site responds” and “the right service responds” are different things.
  • Without sudo, ss hides process names. Plenty of troubleshooting dead ends come from running a command without the privileges it needs.

Fixing it properly

You have two reasonable choices:

  1. You don’t need Apache: stop it now and stop it starting at boot.

    sudo systemctl disable --now apache2
    sudo systemctl restart nginx
  2. You need both: move one of them to another port. For nginx, change the listen 80 lines in /etc/nginx/sites-enabled/default (for example to listen 8080), then run sudo nginx -t and sudo systemctl reload nginx.

systemctl stop alone only fixes things until the next reboot. That’s why the simulation’s goal needs Apache disabled, not just stopped.

Reproduce it on a real VM

On a disposable Ubuntu or Debian VM:

sudo apt update
sudo apt install -y apache2     # starts and takes port 80
sudo apt install -y nginx       # installs, then fails to start
systemctl status nginx
journalctl -u nginx -n 20 --no-pager
sudo ss -tlnp

apt may report that it couldn’t configure the nginx package, because its install script tries to start the service. That’s expected here. After you fix the port clash, run sudo dpkg --configure -a so apt can finish the job.

Fix it with either option above, then confirm:

systemctl status nginx
curl -I http://localhost        # look for "Server: nginx"

To clean up afterwards: sudo apt purge -y apache2 nginx && sudo apt autoremove -y.

Expected result

nginx shows active (running), curl -I http://localhost returns a Server: nginx header, and systemctl is-enabled apache2 says disabled, so the fix survives a reboot.

Further reading

Key lessons

  • Status, logs, a configuration test and the list of listening ports answer most service failures.
  • Only one program can listen on a port. "Address already in use" means: find out who owns it.
  • Stopping a service fixes things until the next reboot. Disabling it makes the fix stick.

Keep going