Log into almost any Linux server built in the last decade and there’s one program quietly running underneath everything else: systemd. It started before your shell. It launched the SSH daemon you connected through. It’s the reason your web app comes back up after a reboot without anyone touching it. And yet most people only learn its name the day a service won’t start and someone tells them to “just run systemctl restart.”
That’s a shame, because systemd isn’t hard once you see what problem it solves. At its core it answers a deceptively simple question: when this machine turns on, what should run, in what order, and what happens when something dies? Get comfortable with that idea and a big chunk of day-to-day server work stops feeling like guesswork.
What systemd actually is
When a Linux machine powers on, the kernel loads, does its low-level setup, and then hands control to a single program whose job is to bring the rest of the system to life. That first program is called the init system, and on the vast majority of modern Linux servers, that init system is systemd.
Think of it as the server’s stage manager. Nothing runs on its own. systemd decides what to start, makes sure the things each service depends on are ready first, restarts anything that crashes, and shuts everything down cleanly when you power off. It’s process number 1 — the parent of every other process on the machine, directly or indirectly.
The pieces systemd manages are called services (or, in its own vocabulary, units — more on that word in a moment). A service is just a long-running program: a web server, a database, a background worker, the SSH daemon. systemd’s whole reason for existing is to start those, keep them running, and tell you what happened when they don’t.
systemd replaced an older approach
Before systemd became standard, Linux booted using shell scripts run in sequence (a system often called “SysV init”). It worked, but starting services strictly one-after-another was slow, and there was no built-in way to automatically restart something that crashed. systemd starts independent services in parallel, tracks dependencies between them, and supervises them after launch. That’s why it took over — not because it’s trendy, but because it solved real, annoying problems. You’ll still hear old-timers grumble about it; that debate doesn’t need to be yours.
Units: the thing systemd manages
systemd doesn’t only manage running programs. It manages anything that can be started, stopped, or watched, and it calls each of those things a unit. A unit is described by a small plain-text configuration file, and the file’s extension tells you what kind of unit it is.
The kind you’ll touch most often is the service unit (.service) — that’s a long-running program like a web server. But there are others worth recognizing:
.service— a program to run and supervise (the everyday one)..socket— a network or local socket systemd listens on, starting the matching service only when a connection actually arrives..timer— a scheduled trigger, systemd’s modern alternative to a cron job..target— a named group of units, used to describe a whole state of the system (for example, “everything needed for a normal multi-user server”)..mount— a filesystem that should be mounted.
You don’t need to memorize all of these. The mental model that matters: a unit is one manageable thing, described by one file, and .service units are what you’ll live in. Almost every “start my app on the server” task comes down to writing or editing one .service file.
systemd (PID 1)
│
┌──────────┼───────────────┬─────────────┐
▼ ▼ ▼ ▼
ssh.service nginx.service db.service app.service
(running) (running) (running) (crashed → restarted)
systemctl: the one command you’ll use daily
You don’t talk to systemd directly. You talk to it through a command-line tool called systemctl. If you remember nothing else from this article, remember systemctl and a handful of verbs that follow it. They’re the same no matter which service you’re poking at, which is exactly what makes systemd pleasant once it clicks.
Here are the ones you’ll reach for constantly. Replace app with the real service name:
# Is it running right now? Shows status, recent log lines, PID.
systemctl status app
# Start it now (does nothing about future boots).
systemctl start app
# Stop it now.
systemctl stop app
# Stop then start — the classic "turn it off and on again".
systemctl restart app
# Re-read config WITHOUT a full restart, if the service supports it.
systemctl reload app
Run systemctl status app first whenever something’s wrong. It’s the most useful command in the whole toolkit: it tells you whether the service is active (running), inactive (stopped), or failed (tried to run and died), and it prints the last several log lines right there, which is usually enough to spot the problem.
Most of these need root
Starting, stopping, and changing services affects the whole machine, so systemd quite reasonably wants administrator rights. On a typical server you’ll prefix these with sudo — for example sudo systemctl restart app. Read-only commands like systemctl status usually work without it. If a command silently does nothing or complains about permission, that missing sudo is the first thing to check.
“Enabled” vs “started”: the distinction that trips everyone up
Here is the single most common point of confusion with systemd, and it’s worth slowing down for. Starting a service and enabling a service are two different things.
- Start means: run it right now, in this moment. If the server reboots, it will not come back on its own.
- Enable means: set it to start automatically on every future boot. By itself, enabling does not start it right now.
So a fresh service you want running both now and after every reboot needs both:
# Run it now AND make it come back after a reboot — in one command.
sudo systemctl enable --now app
# The equivalent of doing it in two steps:
sudo systemctl enable app # will start on next boot
sudo systemctl start app # starts it this very moment
The mirror image is disable (don’t start on future boots) versus stop (stop it now). People get burned by this constantly: they start a service, everything works, they reboot the server weeks later, and the service is mysteriously gone — because it was started but never enabled. Whenever you set up something that must survive reboots, the --now flag is your friend.
start now? auto-start on boot?
start yes no
enable no yes
enable --now yes yes
What a service unit file looks like
Eventually you’ll want to run your own program as a managed service — your app, a background worker, something you wrote. You do that by creating a small .service file. You don’t need to understand every option to read one, so here’s a realistic, minimal example for a fictional web app belonging to ACY Partner Indonesia:
[Unit]
Description=ACY Partner Indonesia web app
After=network.target
[Service]
ExecStart=/usr/bin/node /srv/app/server.js
WorkingDirectory=/srv/app
User=appuser
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Reading it top to bottom:
[Unit]describes the unit itself.Descriptionis human-readable text you’ll see instatus.After=network.targettells systemd not to launch this until the network is up.[Service]is the heart of it.ExecStartis the exact command that runs the program.WorkingDirectoryis the folder it runs in.Usersays which user it runs as (a good habit — don’t run app code as root).Restart=on-failuretells systemd to bring the service back automatically if it crashes, andRestartSec=5waits five seconds before each retry so you don’t hammer a broken service.[Install]controls what happens when youenableit.WantedBy=multi-user.targetis the usual choice for a normal server service — it ties the service into the standard “fully booted, multi-user” state.
That Restart=on-failure line is, for many people, the whole reason to bother with systemd. Your process dies at 3 a.m. and systemd quietly brings it back five seconds later, no human required. That self-healing behaviour is exactly the kind of thing a good init system gives you for free.
Edit, then reload the systemd config
After you create or change a .service file, systemd doesn’t notice automatically — it has the old version cached in memory. Run sudo systemctl daemon-reload to make it re-read the unit files, then start or restart your service. Forgetting daemon-reload after an edit is one of the most common “but I changed it and nothing happened” mistakes. Edit file → daemon-reload → restart. That order, every time.
Where do these files live? System-managed units (the ones installed by packages) sit in /usr/lib/systemd/system/ or /lib/systemd/system/. Units you create or override go in /etc/systemd/system/. The rule of thumb: leave the package directories alone and put your own files in /etc/systemd/system/, because that’s the directory meant for the administrator — you.
Reading the logs with journalctl
systemd doesn’t just run your services; it also captures everything they print. Anything a managed service writes to its output gets collected into a central system log called the journal, and you read it with a companion command, journalctl. This is hugely convenient: you don’t have to hunt around the filesystem for a log file, because systemd already grabbed the output for you.
A few patterns cover almost everything:
# Logs for one service, newest at the bottom.
journalctl -u app
# Follow it live — like tail -f — to watch as things happen.
journalctl -u app -f
# Just the most recent lines (here, the last 50).
journalctl -u app -n 50
# Everything since the last boot only.
journalctl -u app -b
The -u flag is the important one: it filters the journal down to a single unit, so instead of every message on the whole machine you see only the service you care about. When a service status says failed, the very next move is journalctl -u app -n 50 to read why. Nine times out of ten the error is right there — a typo in a path, a port already in use, a missing file.
Why this matters for running anything online
Step back and the point of systemd is simple: it’s the difference between a program you babysit and a service that takes care of itself. Without an init system, you’d start your app by hand in a terminal, and the moment that terminal closed, the server rebooted, or the program crashed, your site would go dark and stay dark until a human noticed. systemd removes the human from that loop. It starts your services when the machine boots, restarts them when they fall over, runs them under the right user, and keeps tidy logs you can read after the fact.
Just about every real deployment on a Linux server, from a tiny side project to serious production infrastructure, leans on systemd to keep things alive. You don’t need to be an expert in all of it. Knowing what a service unit is, the difference between start and enable, and how to check status and logs already covers the overwhelming majority of what you’ll actually do. If you’re still fuzzy on what a “service” or a long-running “process” even is underneath all this, it’s worth being comfortable on the command line first, since every systemd command lives there — and the broader picture of why Linux dominates servers is part of why systemd is something worth learning at all.
Wrapping up
The essentials, gathered in one place:
- systemd is the init system on most modern Linux servers — process 1, the program that boots the machine and supervises everything that runs on it.
- It manages units; the everyday kind is the
.serviceunit, a long-running program described by one plain-text file. - You drive it with
systemctl:status,start,stop,restart, andreload. Runstatusfirst whenever something breaks. enable≠start. Start runs it now; enable makes it come back after a reboot. Useenable --nowto do both.- A
.servicefile’sRestart=on-failuregives you automatic self-healing — systemd quietly brings a crashed service back up. - After editing a unit file, run
daemon-reloadbefore restarting, and read what happened withjournalctl -u <service>.
Once services start, stay alive, and survive reboots on their own, the next natural questions are about the world around the process — the variables it reads its configuration from, and how you reach the machine in the first place to manage all of this remotely.