PTENES
MODULE 4.3

⚙️ Systemd: Services That Never Stop

You deployed your application to the server, but what happens when the server restarts? Or when the program crashes? systemd is the manager that keeps your services running 24 hours a day, 7 days a week. Here you’ll learn to turn any program into a service that never stops.

6
Topics
45
Minutes
Basic
Level
Hands-on
Type
1

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.

systemd (PID 1) 24/7 on-call manager meuapp.service active (running) api.service stuck → restart nginx.service active (running)

🧠 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."

2

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.

3

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-reload after editing the file
  • ✓Check with status whether it stayed active
  • ✓Use enable --now for production

✗ What NOT to do

  • ✗Forget the enable and lose the service on reboot
  • ✗Confuse start (now) with enable (boot)
  • ✗Edit the file without reloading the daemon
4

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.

5

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).

1

network.target starts

The network is ready. Almost every internet service waits for this first.

2

postgresql.service starts

The database starts up. Your application needs it running to connect.

3

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."

6

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=always in web apps
  • ✓Define RestartSec=5 to avoid a loop
  • ✓Check the log to understand why it went down

✗ What NOT to do

  • ✗Leave Restart=no in production
  • ✗Use restart to mask bugs without fixing them
  • ✗Forget daemon-reload after changing the keys

📚 Module Summary

✓
Systemd is the on-call manager - keeps your services running 24/7
✓
The service file has [Unit], [Service], and [Install] - lives in /etc/systemd/system/
✓
systemctl start/stop/restart/enable - enable makes it start at boot
✓
journalctl -u, -f, --since - read the logs to find out what happened
✓
After/Requires and Restart=always - order between services and automatic restart

Next Module:

4.4 - Cron Jobs: Scheduled Tasks (running commands automatically at set times)