Service management with systemd is one of the basic skills that every Linux server administrator should master. systemd is the default init system and service manager in almost all modern Linux distributions, including Ubuntu, Debian, CentOS, AlmaLinux, and Fedora. This tool is responsible for booting the system, running services, managing dependencies and monitoring processes. In this complete guide to Rapido Server, you'll learn how to manage services with systemd, build custom services, check logs, and troubleshoot common problems.
What is systemd and what is its role in Linux?
systemd is a set of tools and libraries that handles the boot process and services management in Linux. This system replaced the old SysV init method and brought many benefits including parallel startup of services, intelligent dependency management and continuous monitoring of processes. The first process that runs after the Linux kernel boots is systemd itself, known by the process ID (PID) of 1.
The main concept in systemd is "Unit". Each unit describes a system resource and has different types:
- service. describes a service or daemon that runs in the background.
- socket. to enable service based on network socket or IPC.
- timer. Modern alternative to cron for scheduling tasks.
- target. Grouping of several units to reach a certain state of the system.
- mount. to manage filesystem mount points.
Note: The main command line tool for service management with systemd issystemctlcommand andjournalctlis used to view logs.
Service management with systemd and systemctl commands
The most everyday thing you do with systemd is to check the status of services. All this is done with systemctl command. To start, running a service like Nginx is like this:
systemctl start nginx
To stop the service:
systemctl stop nginx
To perform a full restart or reload configuration without interrupting service:
systemctl restart nginx
systemctl reload nginx
One of the most important distinctions in systemd is the difference between start and enable. The start command starts a service now, but enable sets it to run automatically every time the server boots. These two are independent of each other:
systemctl enable nginx
systemctl disable nginx
If you want a service to run now and be activated on boot, you can combine both with one command:
systemctl enable --now nginx
Check the status of services and fix bugs
To see the exact status of a service, use the status subcommand. This command displays valuable information such as current status, process ID, memory usage, and the last few lines of the log:
systemctl status nginx
Look for two important lines in the output of this command. Line Loaded shows the unit file loaded and whether the service is enabled or not. The line Active shows the current state of the execution. The following table describes the most common situations:
| status | meaning |
|---|---|
| active (running) | The service is running continuously |
| active (exited) | The service ran and ended successfully |
| inactive (dead) | The service is not running |
| failed | The service has stopped with an error |
| activating | The service is starting up |
To see a list of all running services and check the overall health of the system:
systemctl list-units --type=service --state=running
And to view services that have gone to failed mode:
systemctl --failed
Building a custom service with systemd
One of the most powerful features of systemd is the ability to turn any application into a managed service. Suppose you have a Node.js application that you want to always run in the background and automatically restart if it crashes. For this, we create a single file in the path /etc/systemd/system/:
nano /etc/systemd/system/myapp.service
Put the following content in it:
[Unit]
Description=My Node.js Application
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/myapp
ExecStart=/usr/bin/node server.js
Restart=on-failure
RestartSec=5
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
Each part of this file has a specific role. The [Unit] section defines descriptions and dependencies; The expression After=network.target means that the service should be executed after the network is ready. The [Service] section specifies how to run: ExecStart the command to run, Restart=on-failure automatic restart in case of error, and User the user with which the service will run. The [Install] section specifies which target the service should be activated on.
After creating the file, you need to notify systemd of the changes and then enable the service:
systemctl daemon-reload
systemctl enable --now myapp.service
Warning: Be sure to run the systemctl daemon-reload command every time you edit a single file for systemd to read the changes, otherwise the old configuration will still be applied.
Manage logs with journalctl
systemd has a centralized logging system called journal that collects all messages from services. The journalctl tool is used to view and search these logs. To see the logs of a specific service:
journalctl -u myapp.service
To follow logs live (like tail):
journalctl -u myapp.service -f
To limit logs to a specific time period, such as the past hour or since the last boot:
journalctl -u nginx --since "1 hour ago"
journalctl -b
Sometimes logs take up a lot of space. You can delete old logs to manage their volume. For example, to keep only the last 500 MB:
journalctl --vacuum-size=500M
Schedule tasks with Timer instead of Cron
In addition to managing services, systemd can be a perfect replacement for cron. You can schedule tasks by using timer units, and its advantage over cron is integration with journal for logging and better management of dependencies. To make a timer, you need two files: a service file that does the work and a timer file that determines the execution time. Sample timer file for daily execution:
[Unit]
Description=Run backup daily
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
The Persistent=true option ensures that if the server is down at the time of the scheduled run, the job will run as soon as it is turned on. To view all active timers:
systemctl list-timers
If you want to expand your server administration skills, the Rapido Server Articles series has plenty of practical guides. You also need a server to run these tutorials, which you can get from the Buy Virtual Server page.
Dependencies management and service execution order
One of the important advantages of systemd compared to old systems is the intelligent management of dependencies and execution order. In the [Unit] section of the file service, there are a few key instructions for this purpose that you should understand very well:
- After and Before. determine the order of execution but do not create a hard dependency.
After=network.targetIt means that this service should be run after the network is ready. - Requires. is a hard dependency; If the required service is not executed, this service will not be executed either.
- Wants. is a soft dependency; The required service will run, but if it fails, the main service will still run.
For example, suppose you have an application that requires a database. You can write in its service file:
[Unit]
Description=My Web App
Requires=postgresql.service
After=postgresql.service network.target
With this setting, systemd ensures that the database and network are prepared first, and then your application is executed. Understanding the difference between After (which only specifies the order) and Requires (which creates the actual dependency) is critical to designing reliable services.
Limiting resources and increasing the security of services
systemd provides powerful tools for controlling resource consumption and securing services, implemented in the Linux kernel through cgroups technology. You can prevent a service from consuming all of the server's resources by adding these options to the [Service] section:
[Service]
MemoryMax=512M
CPUQuota=50%
TasksMax=100
In this example, the service consumes a maximum of 512 MB of memory and 50% of a processor core. In addition to resources, systemd has several security options to limit service access to the system. Some of the most important of them are:
| Option | Security effect |
|---|---|
| NoNewPrivileges=true | Prevent access level increase |
| PrivateTmp=true | Isolated and dedicated tmp folder for the service |
| ProtectSystem=strict | Make a large portion of the filesystem read-only |
| ProtectHome=true | Block access to users' home folders |
These options allow you to place even services running with high availability in a restricted and secure environment to minimize damage in the event of an intrusion. You can also use the following command to check the resource consumption of a service:
systemd-cgtop
Understanding the objectives and performance levels
In old systems, there was a concept called runlevel that defined different system states. In systemd, this concept is replaced by "target", which is more flexible. The most important targets are multi-user.target for multi-user text mode (common on servers) and graphical.target for graphical mode. To see the current system default target:
systemctl get-default
On a server, the default goal is usually set to multi-user so that resources are not wasted on the GUI. To change the default target:
systemctl set-default multi-user.target
Also, in case of emergency, you can take the system to special modes such as rescue or emergency, which are very useful for troubleshooting serious boot problems. Understanding these goals will help you control the behavior of the system in different situations.
Troubleshoot failed services
When a service goes into failed state, systemd provides you with good tools to find the cause. The first step is always to check the status and logs:
systemctl status myapp.service
journalctl -u myapp.service -n 50 --no-pager
Common causes of service failure are: wrong path in ExecStart, insufficient permissions for the specified user, port being occupied by another process, or a syntax error in the application itself. By carefully reading the log messages, the cause can usually be found quickly. After fixing the problem and if you edit the unit file, don't forget to run daemon-reload and then restart the service for the changes to take effect.
Sometimes the service is restarted many times and does not reach a stable state. In this case, check if the limit on the number of restart attempts is enabled. By default, systemd will stop trying to run a service if it fails multiple times in a short period of time to avoid an infinite loop. You can set this behavior with the StartLimitIntervalSec and StartLimitBurst options. Use the following command to reset the failed status of a service and allow you to try again:
systemctl reset-failed myapp.service
Finally, a very useful troubleshooting method is to manually run the ExecStart command directly in the terminal. If the application works in direct execution but fails as a service, the problem is usually due to environment variables, the executing user, or the working path. This simple comparison is often the fastest way to find the root of the problem and help you understand the difference between a personal execution environment and an isolated systemd environment.
Frequently asked questions
What is the difference between start and enable in systemd?
The start command executes a service immediately, but this execution is temporary and disappears after the server is restarted. The enable command sets the service to run automatically every time the system boots. You should do both or use enable --now to ensure permanent execution.
Why do I need to run daemon-reload after editing the service file?
systemd loads single files into memory and uses a cached version. The daemon-reload command tells systemd to re-read configuration files from disk. Without this, your new changes will not be applied and the service will run with the old settings.
Can systemd replace cron?
yes The timer units in systemd cover the capabilities of cron and have additional benefits such as integration with journal for logging, dependency management, and delayed execution of missed jobs with the Persistent option. However, cron is still popular for simple and quick tasks.
How do I know why a service is down?
First, see the general status and the last few lines of the log with systemctl status, then check the complete logs with journalctl -u service name. Error messages usually specify the exact cause, such as a wrong path, a lack of permission, or a busy port.



