What Is Systemd
systemd is the on-call manager of your Linux server. It's the first program that starts when the machine boots, and it's responsible for starting, monitoring, and restarting all the other services. Without it, you'd have to open the terminal and start your program manually every time the server restarted. With it, you define once how the service should run, and systemd takes care of the rest, day and night.
🧠 Analogy: The On-Call Manager
Imagine an office building with a manager who never sleeps. Their job is simple: keep the lights on, the elevators running, and the reception desk open. If a piece of equipment shuts down, they turn it back on right away. If the power goes out and comes back, they reopen everything automatically. This manager is systemd, and the equipment is your services.
- •Start the services: when the server starts
- •Monitors the services: checks whether they're still running
- •Restarts the services: if any get stuck or go down
- •Write it all down: stores the records (logs) of what happened
💡 Vocabulary: unit, service, and PID 1
In the world of systemd, each thing it manages is a unit (unit). The most common type of unit is the service (service), which is a program that runs in the background. systemd itself is the PID 1: process number 1, the parent of every other process on the machine. When you hear "create a service," understand it as "teach the manager to take care of your program."
Creating Your First Service File
To have systemd manage your program, you need to write a service file. It’s a plain text file that ends in .service and is in the folder /etc/systemd/system/. This is where you explain to the manager what to run, how to run it, and when to run it.
Create the file with nano
# Requires sudo: this is a system folder
$ sudo nano /etc/systemd/system/meuapp.service
The name before the .service and what you'll call the service later. Choose something short with no spaces.
📝 The three sections: Unit, Service, and Install
Every service file has three blocks. Each answers a different question:
[Unit]
Description=My Node application
After=network.target
# ------------------------------
[Service]
ExecStart=/usr/bin/node /home/deploy/app/server.js
WorkingDirectory=/home/deploy/app
User=deploy
Restart=always
# ------------------------------
[Install]
WantedBy=multi-user.target
[Unit]
"What am I?" A description of the service and what it depends on to start.
[Service]
"How do I run it?" The command that starts the program, the folder, the user, and the restart policy.
[Install]
"When should I start it at boot?" At what point during startup the service starts.
⚠️ Common Error
Problem: "I only put node server.js no ExecStart and got an error."
Solution: systemd doesn’t know where the node. Always use the full path of the executable. Find out with which node (will show something like /usr/bin/node) and use this full path in ExecStart.
Controlling the Service: start, stop, restart, enable
After writing the file, you interact with systemd using the command systemctl. Think of it as the remote control of the manager: starts, stops, restarts, and schedules services to start at boot.
Whenever you change the file: reload
Every time you create or edit a .service, systemd needs to reload the files:
$ sudo systemctl daemon-reload
# no output = it worked
Start, Stop, and Restart
# Start the service now
$ sudo systemctl start meuapp
# Stop the service
$ sudo systemctl stop meuapp
# Restart (stop and start again)
$ sudo systemctl restart meuapp
# View the current state
$ sudo systemctl status meuapp
● meuapp.service - Minha aplicação Node
Loaded: loaded (/etc/systemd/system/meuapp.service)
Active: active (running) since Tue 2026-06-17 12:30:01
Main PID: 4821 (node)
Note: you don't need to type the .service at the end. systemd understands meuapp by itself.
👁 enable: the difference that matters
O start starts the service now, but it won't come back if the server restarts. The enable marks the service to start automatically on boot. In most cases, you want both.
# Start at boot (but not now)
$ sudo systemctl enable meuapp
# Start now AND at boot (most commonly used)
$ sudo systemctl enable --now meuapp
# Undo: stop starting at boot
$ sudo systemctl disable meuapp
✓ What TO DO
- ✓Run
daemon-reloadafter editing the file - ✓Check with
statuswhether it stayed active - ✓Use
enable --nowfor production
✗ What NOT to do
- ✗Forget the
enableand lose the service on reboot - ✗Confuse
start(now) withenable(boot) - ✗Edit the file without reloading the daemon
Reading Logs with journalctl
When a service fails, the first question is: "what did it say before it crashed?". systemd stores everything each service prints on the screen in a central journal. You read this journal with the command journalctl. It’s your problem detective.
🧠 Analogy: The Logbook
Think of journalctl as a ship's logbook. Everything that happens is recorded with a date and time: when the service started, when it restarted, what error appeared. When something goes wrong, you open the logbook to the right page and find out what happened without guessing.
The essential filters: -u, -f, and --since
# -u = filters by a service (unit)
$ journalctl -u meuapp
jun 17 12:30:01 srv node[4821]: Server on port 3000
jun 17 12:34:18 srv node[4821]: GET /api/users 200
# -f = follows live (follow), like watching
$ journalctl -u meuapp -f
(new lines appear in real time... Ctrl+C to exit)
# --since = starting from when
$ journalctl -u meuapp --since "today"
$ journalctl -u meuapp --since "10 min ago"
# Combine them: only errors from the last 30 lines
$ journalctl -u meuapp -n 30 --no-pager
💡 Tip: the trio that handles 90% of cases
When your service won’t start, run systemctl status meuapp to see the summary, then journalctl -u meuapp -n 50 to read the last lines of errors. If you want to watch it happen in real time, leave journalctl -u meuapp -f open and restart the service in another tab.
⚠️ Common Error
Problem: "journalctl opens a weird screen and won’t exit."
Solution: By default, it opens in the pager. Use the arrow keys to scroll, q to leave, or add --no-pager to send everything straight to the screen. To go to the end of the log, press Shift+G.
Dependencies: After and Requires
Services rarely run on their own. Your application may need the database already connected to start, or from the network being ready. systemd lets you declare this order with two keys: After (order) and Requires (requirement).
network.target starts
The network is ready. Almost every internet service waits for this first.
postgresql.service starts
The database starts up. Your application needs it running to connect.
meuapp.service starts last
Only now, with the network and database ready, does your application start without connection errors.
Declaring the order in the service file
[Unit]
Description=My application
# Starts AFTER the network and database
After=network.target postgresql.service
# The database is REQUIRED: if it goes down, I go down with it
Requires=postgresql.service
After=
Define only the order: "start me after this one." It doesn't require the other service to exist. If the referenced service doesn't start, yours starts anyway.
Use it to: make sure the network is ready beforehand.
Requires=
Create strong dependency: "it doesn't work without it." If the required service fails, yours stops too. It usually comes with After.
Use it for: the database the app needs to run.
💡 Tip: After and Requires are independent
Requires ensures the other service starts along with it, but doesn't guarantee the order. To have both order AND a requirement, declare both: Requires=db.service more After=db.service. This pair is the right way to say "I need the database, and it starts after it."
Automatic Restart: Systemd’s Superpower
Here’s why you use systemd: it restarts your service on its own when it crashes. Did a bug freeze it? Did it run out of memory? The manager notices and brings everything back up in seconds, without you having to wake up in the middle of the night. You configure this with two keys: Restart e RestartSec.
In the [Service] section
[Service]
ExecStart=/usr/bin/node /home/deploy/app/server.js
# Always restarts, no matter the reason
Restart=always
# Wait 5 seconds before trying again
RestartSec=5
The most commonly used Restart values
always
Always restarts, even if the program exits without an error. Most common for web apps.
on-failure
Restarts only when the program exits with an error (nonzero code).
no
Never restarts (and that's the default if you don't define anything). Avoid in production.
👁 What you’ll see in the status after a crash
● meuapp.service - Minha aplicação Node
Active: active (running) since Tue 12:40:09
Main PID: 5102 (node)
# In journalctl, systemd logs the restart:
12:40:04 systemd: myapp.service: Main process exited, code=killed
12:40:09 systemd: meuapp.service: Scheduled restart, attempt 1
12:40:09 systemd: Started My Node application.
⚠️ Common Error
Problem: "My app has a bug that makes it crash immediately, and systemd keeps restarting it in an endless loop."
Solution: Without RestartSec, it tries to restart immediately, and systemd blocks it after too many attempts (start-limit). Add RestartSec=5 to give it a breather between attempts, and fix the bug by checking the journalctl. Restarting doesn't replace fixing the error.
✓ What TO DO
- ✓Use
Restart=alwaysin web apps - ✓Define
RestartSec=5to avoid a loop - ✓Check the log to understand why it went down
✗ What NOT to do
- ✗Leave
Restart=noin production - ✗Use restart to mask bugs without fixing them
- ✗Forget
daemon-reloadafter changing the keys
📚 Module Summary
Next Module:
4.4 - Cron Jobs: Scheduled Tasks (running commands automatically at set times)