NewHalo Edge 3 is here: HTTP/3 everywhere and 42 edge locations.Learn more
Docs / Tools and troubleshooting

Create and manage systemd services

Tools and troubleshooting8 min readUbuntu 24.04 LTS

A service is a program that runs in the background, such as a web app or a worker. systemd is the tool Ubuntu uses to start, stop, and restart services, and to bring them back after a reboot or a crash. In this guide you will write a small service unit file, start it, and manage it with systemctl.

Before you begin

  • A VPS running Ubuntu 24.04 LTS with SSH access as a user with sudo rights, such as alex.
  • A program you want to run as a service. This guide uses a tiny Python web app at /opt/hello/app.py as a stand-in.
  • Python 3, which Ubuntu installs by default.

Step 1: Create a sample app and a service user

Good practice is to run services under their own unprivileged account, not as root. The --system flag creates a system account, --no-create-home skips a home folder, and nologin stops anyone from logging in as it.

sudo useradd --system --no-create-home --shell /usr/sbin/nologin hello
sudo mkdir -p /opt/hello
sudo nano /opt/hello/app.py

Paste this small app, which answers on port 8080 and logs each request:

from http.server import HTTPServer, BaseHTTPRequestHandler

class Hello(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-Type", "text/plain")
        self.end_headers()
        self.wfile.write(b"Hello from my service\n")

HTTPServer(("127.0.0.1", 8080), Hello).serve_forever()

Hand the folder to the service user, so the app can read its files:

sudo chown -R hello:hello /opt/hello

Step 2: Write the unit file

A unit file describes the service. It lives in /etc/systemd/system/, and the name ends in .service. Create it with nano:

sudo nano /etc/systemd/system/hello.service
[Unit]
Description=Hello example web app
After=network.target

[Service]
User=hello
WorkingDirectory=/opt/hello
ExecStart=/usr/bin/python3 /opt/hello/app.py
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Here is what the sections mean. [Unit] describes the service and its ordering. [Service] says who runs it, where, and with which command. Restart=on-failure brings it back if it crashes, after waiting five seconds. [Install] says the service should start in normal multi-user boot.

Step 3: Load, enable, and start the service

Tell systemd to re-read its unit files. Then enable the service so it starts at boot, and start it now. --now does both start and enable steps at once.

sudo systemctl daemon-reload
sudo systemctl enable --now hello.service

Check that it is running:

systemctl status hello.service --no-pager
● hello.service - Hello example web app
     Loaded: loaded (/etc/systemd/system/hello.service; enabled; preset: enabled)
     Active: active (running) since Sat 2026-10-31 09:30:12 UTC; 4s ago
   Main PID: 2210 (python3)

Test it with curl. The app listens only on 127.0.0.1, so the request must come from the server itself:

curl http://127.0.0.1:8080/
Hello from my service

Step 4: Read the logs

Everything the service prints goes to the systemd journal. The -u flag selects one unit, and -f follows new lines as they arrive, like tail -f. Press Ctrl+C to stop following.

journalctl -u hello.service -f

Step 5: Restart, stop, and disable

Use these commands for day-to-day control:

sudo systemctl restart hello.service   # stop and start again
sudo systemctl stop hello.service      # stop until started again
sudo systemctl start hello.service     # start a stopped service
sudo systemctl disable hello.service   # do not start at boot
systemctl is-active hello.service      # print "active" or "inactive"

Whenever you edit a unit file, run sudo systemctl daemon-reload before restarting, so systemd picks up the change.

Tip: Use systemd-analyze verify /etc/systemd/system/hello.service after editing a unit file. It warns about typos and bad settings before you restart.
Careful: A service that restarts forever hides a broken program. If systemctl status keeps showing "activating (auto-restart)", read the journal first. Restart loops can use lots of CPU and fill your logs.

Troubleshooting

  • "Unit hello.service not found". The file is in the wrong folder or has the wrong name. It must be in /etc/systemd/system/ and end in .service. Run daemon-reload after creating it.
  • Status says "failed" with exit code 1 or 203/EXEC. systemd cannot run the command. Check that the path in ExecStart exists, that /usr/bin/python3 is correct, and that the hello user can read /opt/hello.
  • "Address already in use". Another program already uses port 8080. Find it with sudo ss -tlnp and stop it, or change the port in the app.
  • Changes do not take effect. You probably forgot sudo systemctl daemon-reload after editing the unit file, or you did not restart the service.

Next steps

Now you can run any program as a managed service. The next step is usually getting your code onto the server automatically, which is covered in the guide on deploying a site with a git push. Keep the same pattern: a dedicated service user, a unit file, and the journal for logs.

Something not working? Chat or email our support team and we will help you get unstuck.

Contact support