Skip to content

Systemd

A service (commonly called daemon in the Unix world) is a program, that runs in the background, typically detached from a terminal. You can use your own Systemd user instance, to manage and monitor services.

We provide two ways to create new services:

  1. Use uberspace service to create a service with common options by running a single command.
  2. Manually create .service files, giving you flexibility and the full power of system.

It's recommended to start out with uberspace service and switch over to writing .service files yourself, if you encounter the command's limits. However, it's always a good idea to look at the generated files and read the full documentation below the Quickstart.

Quickstart

To quickly create and delete services, use uberspace service.

Add a Service

[isabell@moondust ~]$ uberspace service

 Usage: uberspace service [OPTIONS] COMMAND [ARGS]...

 Manage systemd user services

╭─ Options ────────────────────────────────────────────────────────────────────╮
│ --help  -h        Show this message and exit.                                │
╰──────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ───────────────────────────────────────────────────────────────────╮
│ add    Create and start a systemd user service.                              │
│ del    Stop and delete a systemd user service.                               │
│ list   List all user services in ~/.config/systemd/user/                     │
╰──────────────────────────────────────────────────────────────────────────────╯

For example, use uberspace service add to create a new service. This command will:

  1. Create a service file in ~/.config/systemd/user/
  2. Reload systemd to load the new configuration
  3. Start the service and run it automatically on reboot
  4. Show the service status, so you can check the result

It comes with several options:

  • Service name (e.g. hello): Unique name of the service, used to create files and to refer to the service in systemctl commands. Use a combination of lower case letters, dashes, underscores, numbers, etc., for example: django, backend, rail-test, svc2, ...
  • Command (e.g. caddy respond --listen ...): Executable and parameters to run, refer to the documentation of your software on what to put here.
  • Environment Variables (e.g. --env SOME_CONFIG=1): Variables to put into the environment of the process. Refer to the documentation of your software on what to put here. This is commonly used to specify configuration options or point the software to a config file. You can pass this option multiple times to specify multiple variables.
  • Working Directory (e.g. --workdir /tmp): Path to change to before the command starts. Use this if your sofware is looking for data, config or code files relative to some directory.
[isabell@moondust ~]$ uberspace service add hello "caddy respond --listen 0.0.0.0:12345 --body 'Ohai!'" --env SOME_CONFIG=1 --workdir /tmp
OK: Created service file: /home/isabell/.config/systemd/user/hello.service
OK: systemctl --user daemon-reload
OK: systemctl --user start hello
OK: systemctl --user enable hello
OK: systemctl --user status hello

● hello.service
     Loaded: loaded (/home/isabell/.config/systemd/user/hello.service; enabled; preset: enabled)
     Active: active (running) since Wed 2025-11-05 21:27:48 CET; 168ms ago
 Invocation: 884da81d0a7547e0b9155039e18a82a1
   Main PID: 11633 (sleep)
      Tasks: 1 (limit: 19134)
     Memory: 624K (peak: 2M)
        CPU: 11ms
     CGroup: /user.slice/user-1005.slice/user@1005.service/app.slice/hello.service
             └─11633 caddy respond --listen 0.0.0.0:12345 --body 'Ohai!'

Nov 05 21:27:48 lutodev.uberspace.de systemd[546]: Started hello.service.

Show Services

Your service will now show up in uberspace service list:

[isabell@moondust ~]$ uberspace service list

  Service       Status   Enabled
 ────────────────────────────────
  hello         active   enabled

Remove a Service

To get rid of the service use uberspace service del hello. This command will:

  1. Stop the service, if it's running
  2. Disable the service, if it's enabled
  3. Delete the service file
  4. Run systemctl --user daemon-reload
[isabell@moondust ~]$ uberspace service del hello
OK: systemctl --user stop hello
OK: systemctl --user disable hello
OK: Deleted service file: /home/isabell/.config/systemd/user/hello.service
OK: systemctl --user daemon-reload

Types of Units

In this article we give you a quick overview on how to run you own processes reliably in the background. We focus on service, timer, socket, and path units:

  • A service unit encapsulates settings needed to start and manage your process.
  • A timer unit can start a service at wall clock times or given intervals.
  • A socket unit can start a service on incoming network connections.
  • A path unit can start a service on file changes.
  • There are also common configuration options and rules for every unit.

Systemd User Instance

We start a user instance for your Asteroid at system boot. When your systemd user instance starts, it brings up the per user target default.target. Other units can be controlled manually with systemctl --user … (see below for details).

You can check the status of your instance like this systemctl status --user:

[isabell@moondust ~]$ systemctl status --user
● moondust.uberspace.de
    State: running
    Units: 93 loaded (incl. loaded aliases)
     Jobs: 0 queued
   Failed: 0 units
    Since: Tue 2025-06-24 12:13:42 CEST; 6 days ago
  systemd: 257.6-1-arch
   CGroup: /user.slice/user-1001.slice/user@1001.service
           └─init.scope
             └─6757 /usr/lib/systemd/systemd --user

Service

A service unit encapsulates settings needed to start and manage your process.

How to get more Details?

We try to show you all the settings usually needed, and at least mention the more common ones, to give you enough to start comfortably. For all the details, we refer you to the manual pages.

If we mention a setting here, e.g. ExecStart=, you can search for it in the service unit manual to get detailed information (unless we explixitly mention another man page as source).

Create

To create a new service, place a .service file named after your service in ~/.config/systemd/user/.

Refresh Service Info

You need to run systemctl --user daemon-reload, otherwise Systemd won't pick up your new service.

This is also needed, antytime after you change unit files on disk.

So if you want to add a service called hello that runs the caddy executable to serve greetings, you can create a file like this ~/.config/systemd/user/hello.service:

[Install]
WantedBy=default.target

[Service]
ExecStart=caddy respond --listen 0.0.0.0:12345 --body 'Ohai!'

WantedBy setting

Always use WantedBy=default.target. There is a limited selected of targets available and using one that does not exist like multi-user.target will lead to your service not starting.

  • Since no Type= is specified, the default Type=simple will be assumed.
  • Since no ExecStop= was specified, systemd will send SIGTERM to all processes started from this service, and after a timeout also SIGKILL.

Settings

At the very least you need to set a command that should be run, e.g. with ExecStart=. And a type with Type=, unless you want the default of Type=simple.

  • For details on how to format your commands for the various Exec… settings, you can see the section on command line format in the manual.

  • For supported placeholder variables, see the list of specifiers in the manual page for common options for all units.

Service Type

We give you a quick overview of the types simple (the default), forking and oneshot. You can read up all the details and on the remaining types in the manual.

simple

This is the default if no Type is set. Systemd will assume the unit to be started immediately, and that the process will continue running until the service terminates. If the program daemonizes itself (i.e. forks), please use Type=forking instead.

forking

Use this, if the process you want to start forks itself, which is a common pattern for Unix services (for details on what this means you can see this Wikipedia article on forking).

Systemd will consider the service to be in the process of initialization while the original program is still running. Once it exits successfully and at least a process remains (and RemainAfterExit=no), the service is considered started.

oneshot

Units of this type will wait until the process started terminates and then fall back to being inactive. That means another request to start the unit will perform the action(s) again. This can be useful, if you want to do stuff without keeping active processes, e.g. download a feed, or start a backup. For this type (only) you can define ExecStart= multiple times.

Start

These settings define what is to be done, whenever your service gets started:

ExecCondition=, ExecStartPre=, ExecStart=, ExecStartPost=, SuccessExitStatus=, TimeoutStartSec=

If ExecCondition= succeeds, the lines from ExecStartPre= are run first, then ExecStart=, followed by ExecStartPost=. See the man page on how success and failure is handled for each step. You can use SuccessExitStatus= and TimeoutStartSec= to further define success and failure for your service (this might be especially useful, if you plan to have your unit restarted automatically).

Stop

These settings define what is to be done, whenever your service gets started:

ExecStop=, ExecStopPost=, TimeoutStopSec=

What happens as default (i.e. if you do not set these) depends on the given Type=, you can read up on it in the man page.

Restart

RestartSec=, RestartSteps=, RestartMaxDelaySec=

Reload

ExecReload=

Start / Stop

Use start to start your service:

[isabell@moondust ~]$ systemctl --user start hello.service

And stop to end it:

[isabell@moondust ~]$ systemctl --user stop hello.service

Restart

Stop and start you service at once:

[isabell@moondust ~]$ systemctl --user restart hello.service

See the settings above on how to tweak this process.

Reload

To trigger a configuration reload, use reload:

[isabell@moondust ~]$ systemctl --user reload hello.service

For this to work, the service needs to be configured with ExecReload=; if it is not defined, reloading is not supported.

If you are not sure, if a service supports reloading, you can use reload-or-restart: it will try to reload if possible, and if not, will restart.

[isabell@moondust ~]$ systemctl --user reload-or-restart hello.service

Enable / Disable

By default a service will not be started alongside your session (i.e. when your host starts, e.g. after a reboot, your service will not start automatically). For that you need to enable it first, using systemctl --user enable …:

[isabell@moondust ~]$ systemctl --user enable hello.service

After enabling it, the service will be started with your session (e.g. after the host was rebooted). If you want to revert this behavior, you can disable your service, using systemctl --user disable …:

[isabell@moondust ~]$ systemctl --user disable hello.service

After disabling, the service will no longer be started along with your session.

Enabling / disabling does not start / stop your service!

Enabling a service does not automatically start it, disabling does not stop it. You can use the --now flag to combine both actions, e.g.:

[isabell@moondust ~]$ systemctl --user enable --now hello.service

The command above will enable the service and also start it (given it is not already stated).

Automatic Restarts

Restart=, SuccessExitStatus=, RestartPreventExitStatus=, RestartForceExitStatus=

TODO

Add note on self DOS by restarting broken Services. And add some tips for mitigation. Mention RestartPreventExitStatus=, Restart=, and RestartSec=.

Important

For Type=oneshot, Restart=always and Restart=on-success are not allowed.

Delete

If you stop and disable a service (e.g. systemctl disable --now {{SERVICENAME}}.service), it will no longer run, nor will be started automatically with you session.

Remove

To completely remove a service, you need to…

  1. Stop and disable the service first (systemctl disable --now {{SERVICENAME}}.service).
  2. Then remove the service file (rm ~/.config/systemd/user/{{SERVICENAME}}.service). If your have created overrides for the service, you need to remove those too (rm -r ~/.config/systemd/user/{{SERVICENAME}}.service.d/).
  3. Afterward you should reload you service manager instance, so it drops the unit from memory (systemctl --user daemon-reload).
[isabell@moondust ~]$ # stop and disable service
[isabell@moondust ~]$ systemctl --user disable --now hello.service

[isabell@moondust ~]$ # remove service file
[isabell@moondust ~]$ rm ~/.config/systemd/user/hello.service

[isabell@moondust ~]$ # reload systemd user instance
[isabell@moondust ~]$ systemctl --user daemon-reload

Timer

A timer unit can start a service at wall clock times or given intervals.

TODO

Compare to cron. Write about problems with cron and common intervals and best practices against it.

Socket

A socket unit can start a service on incoming network connections.

Path

A path unit can start a service on file changes.

Troubleshooting

  • If your Service listens on a port, and you want to use it for a Web Backend: The application needs to listen on interface :: or 0.0.0.0 (using 127.0.0.1, localhost, or ::1 does not work!) at any port between 1024 and 65535.

  • If you can still not reach the port, check if your service runs in the correct network namespace. For that you need to…

    1. Get the PID of the process (e.g. systemctl --user show --property MainPID --value {{SERVICENAME}}.service ).
    2. Check if the PID is in your network namespace: ip netns pids {{ASTEROIDNAME}}_ns.

    You can read more about the network stack.

Further Reading

  • For more detailed information you can read the man pages linked above and the Systemd manual, it's quiet good.

  • The Arch wiki has a page on user services, it contains more information on your service manager.

  • The Arch wiki also has a page on writing services, it contains some more detailed information on writing you own service files.