Skip to content

How to Create a systemd Service

Key idea:

systemd is the init system on every modern Linux. A service unit = .service file describing how to start/stop/restart a daemon. Replaces supervisord, pm2 (for Node), rc.d. Auto-start on boot, auto-restart on crash, journalctl for logs, systemctl for control. Minimal unit — 10 lines.

Below: step-by-step, working examples, common pitfalls, FAQ.

Check your site →

Step-by-Step Setup

  1. Create /etc/systemd/system/myapp.service
  2. [Unit] section: Description, After=network.target
  3. [Service] section: ExecStart, User, WorkingDirectory, Restart=on-failure
  4. [Install] WantedBy=multi-user.target
  5. systemctl daemon-reload — reload units
  6. systemctl enable myapp — auto-start on boot
  7. systemctl start myapp + systemctl status
  8. Logs: journalctl -u myapp -f (live tail)

Working Examples

ScenarioConfig
Simple Node.js service[Unit] Description=My App After=network.target [Service] Type=simple User=nodejs WorkingDirectory=/opt/myapp ExecStart=/usr/bin/node /opt/myapp/server.js Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target
Python with venv[Service] Type=simple User=app WorkingDirectory=/opt/myapp ExecStart=/opt/myapp/venv/bin/python /opt/myapp/app.py Environment="PATH=/opt/myapp/venv/bin" Restart=on-failure
Systemd hardening (sandboxing)[Service] NoNewPrivileges=true PrivateTmp=true ProtectSystem=strict ProtectHome=true ReadWritePaths=/var/log/myapp
Timer (cron-like)# /etc/systemd/system/backup.timer [Timer] OnCalendar=*-*-* 03:00:00 Persistent=true [Install] WantedBy=timers.target
Reload config without restartExecReload=/bin/kill -HUP $MAINPID # systemctl reload myapp

Common Pitfalls

  • ExecStart with relative path — "not found". Always absolute /usr/bin/node
  • Environment variables: Environment="KEY=value", not bash syntax
  • User=root — anti-pattern. Create a dedicated user: useradd -r -s /bin/false nodejs
  • Logs don't write to a file — they go to journald: journalctl -u myapp
  • Missing systemctl daemon-reload after a unit change → stale config

TL;DR: Creating a systemd Service

To create a systemd service, start by defining a service unit file in the /etc/systemd/system/ directory, using the .service extension. Specify the service's behavior with directives like Unit, Service, and Install. After saving the file, enable and start the service using systemctl enable your-service-name and systemctl start your-service-name.

Step-by-Step Guide to Creating a systemd Service

Creating a systemd service is a fundamental skill for managing system processes efficiently. Here’s a step-by-step guide to help you set up your own service.

1. Understand the Structure of a systemd Service Unit File

A systemd service unit file typically consists of three main sections:

  • [Unit]: This section contains metadata and dependencies.
  • [Service]: This is where you define the actual service behavior.
  • [Install]: This section is used for installation details.

2. Create the Service File

Start by creating a new service file in the /etc/systemd/system/ directory. Use a descriptive name for your service, following the naming convention your-service-name.service. For example:

sudo nano /etc/systemd/system/my-example.service

3. Define the [Unit] Section

In the [Unit] section, you can specify the description and any dependencies. Here’s an example:

[Unit]
Description=My Example Service
After=network.target

4. Define the [Service] Section

The [Service] section is crucial as it defines how the service behaves. Here’s an example configuration:

[Service]
Type=simple
ExecStart=/usr/bin/python3 /path/to/your_script.py
Restart=on-failure
User=nobody
Group=nogroup

In this example:

  • Type=simple: The service is considered started immediately after the ExecStart command is executed.
  • ExecStart: This is the command that starts your application.
  • Restart=on-failure: This directive ensures that the service restarts if it fails.
  • User and Group: These specify the user and group under which the service runs.

5. Define the [Install] Section

The [Install] section specifies how the service should be enabled or disabled. Here’s a simple example:

[Install]
WantedBy=multi-user.target

This indicates that the service should start during the boot process when reaching the multi-user target.

6. Save and Exit

After defining the sections, save the file and exit the text editor. In nano, you would do this by pressing CTRL + X, then Y to confirm saving, followed by Enter.

7. Reload the systemd Daemon

To recognize the new service file, reload the systemd manager configuration with the following command:

sudo systemctl daemon-reload

8. Enable the Service

To enable the service to start at boot, run:

sudo systemctl enable my-example.service

9. Start the Service

Now, start your service with the command:

sudo systemctl start my-example.service

10. Verify the Service Status

Check the status of your service to ensure it’s running correctly:

sudo systemctl status my-example.service

This command will show you if the service is active and running, along with any logs if there are issues.

11. Managing the Service

You can stop, restart, or disable the service using the following commands:

  • sudo systemctl stop my-example.service
  • sudo systemctl restart my-example.service
  • sudo systemctl disable my-example.service

12. Debugging Issues

If your service does not behave as expected, check the logs for errors. You can do this using:

journalctl -u my-example.service

By following these steps, you can create a robust systemd service tailored to your application's needs, improving your system's reliability and efficiency.

Learn more

Frequently Asked Questions

systemd vs pm2 / supervisord?

systemd — built-in Linux, zero deps. pm2 — specialized for Node.js (cluster, zero-downtime reload). For simple apps — systemd.

Which restart policy?

on-failure (restart on non-zero exit) — standard. always — restart even on normal exit (useful for daemons). no — manual only.

How to graceful shutdown?

<code>TimeoutStopSec=30s</code> — systemd waits 30 s before SIGKILL. App must handle SIGTERM and exit cleanly.

Logs get huge — rotation?

journald auto-rotates. Settings: <code>/etc/systemd/journald.conf</code> → SystemMaxUse=1G, MaxRetentionSec=30d.

Try the live tool that powered this guide

Free plan — 10 monitors, checks every 5 min, no card required. Upgrade for 1-minute interval and multi-region monitoring.