# How Omarchy Uses systemd User Services for Per-User Daemon Management

> Learn how Omarchy manages per-user daemons using systemd user services. Discover their approach to unit file deployment and service enablement for efficient background process control.

- Repository: [37signals/omarchy](https://github.com/basecamp/omarchy)
- Tags: how-to-guide
- Published: 2026-08-20

---

**Omarchy runs all background components as systemd user services, shipping unit files to `/usr/lib/systemd/user/` and enabling them via [`install/enable-services.sh`](https://github.com/basecamp/omarchy/blob/main/install/enable-services.sh) during first-run setup.**

Omarchy is Basecamp's experimental Linux desktop environment built atop systemd. Rather than relying on system-wide daemons or ad-hoc background processes, Omarchy leans entirely on **systemd user services** to manage its per-user daemons. This article examines the complete lifecycle—from installation through runtime control—based on the actual source implementation in the `basecamp/omarchy` repository.

## Installation and Unit File Placement

Omarchy ships its user service definitions in `default/systemd/user/` within the source tree. During package installation, these files land in `/usr/lib/systemd/user/`, the standard location for system-provided user units.

Key unit files include:

- **`default/systemd/user/omarchy-sleep-lock.service`** – Locks the session before suspend
- **`default/systemd/user/omarchy-crash-watch.service`** – Watches for crashes and forwards them to the UI
- **`default/systemd/user/omarchy-fcitx5.service`** – Starts the Fcitx5 input method for the user session
- **`default/systemd/user/omarchy-tailscale-receive.service`** – Handles incoming Tailscale packets for per-user networking

All services use `Type=simple` and launch corresponding Omarchy helper binaries (e.g., `omarchy-system-sleep-monitor`). The `Restart=always` directive ensures automatic recovery where appropriate.

## Enabling Services at First Run

The installer handles one-time service activation via [`install/enable-services.sh`](https://github.com/basecamp/omarchy/blob/main/install/enable-services.sh). This script issues `systemctl --user enable --now` for each shipped unit:

```bash

# From install/enable-services.sh

systemctl --user enable --now omarchy-sleep-lock.service
systemctl --user enable --now omarchy-crash-watch.service

# ... and so on for each unit

```

This creates symlinks under the user's `$HOME/.config/systemd/user/`, ensuring units survive reboots and start automatically on future logins.

You can replicate this manually:

```bash

# Enable all Omarchy user services

for u in /usr/lib/systemd/user/omarchy-*.service; do
    systemctl --user enable --now "$(basename "$u")"
done

# Or disable a single service

systemctl --user disable --now omarchy-fcitx5.service

```

## Enabling Lingering for Background Operation

Some Omarchy timers and services must fire without an active login session—backups, automated updates, and similar background tasks. The installer ensures this via `loginctl enable-linger "$USER"`, which allows the user-level systemd manager (`systemd --user`) to persist after logout.

The migration script [`migrations/1785608166.sh`](https://github.com/basecamp/omarchy/blob/main/migrations/1785608166.sh) contains the logic that creates the lingering flag if needed:

```bash

# Ensure timers keep running after logout

loginctl enable-linger "$USER"

```

Verify lingering status for your user:

```bash
loginctl show-user "$USER" --property=Linger

```

## Environment Variables and Drop-In Configuration

Certain services require additional environment variables or runtime options. The same migration ([`migrations/1785608166.sh`](https://github.com/basecamp/omarchy/blob/main/migrations/1785608166.sh)) creates a drop-in at [`90-omarchy-session-environment.conf`](https://github.com/basecamp/omarchy/blob/main/90-omarchy-session-environment.conf) specifically for `omarchy-sleep-lock.service`:

```ini

# Created by migrations/1785608166.sh

[Service]
Environment=OMARCHY_PATH=/home/user/.local/share/omarchy
Environment=WAYLAND_DISPLAY=wayland-1

```

This propagates critical session variables (`OMARCHY_PATH`, `WAYLAND_DISPLAY`) into the service's execution environment without modifying the base unit file.

## Runtime Control and Monitoring

Users and Omarchy components interact with services through standard `systemctl --user` commands:

```bash

# Check status of a service

systemctl --user status omarchy-sleep-lock.service

# Restart a service after configuration changes

systemctl --user restart omarchy-crash-watch.service

# List all loaded Omarchy units

systemctl --user list-unit-files | grep omarchy

# View live logs

journalctl --user -u omarchy-sleep-lock.service -f

```

## Resource Management and OOM Protection

Omarchy services run within the user's `app.slice`, which enables fine-grained resource control. The migration [`migrations/1785424256.sh`](https://github.com/basecamp/omarchy/blob/main/migrations/1785424256.sh) configures **systemd-oomd** to target only this slice—killing runaway applications without terminating the entire session.

This architecture provides:

- **Process isolation** – Each service operates in its own cgroup
- **Clean failure domains** – A crashing daemon doesn't cascade into session termination
- **Predictable resource limits** – Standard systemd slice controls apply

## Summary

- **Unit files** ship in `default/systemd/user/` and install to `/usr/lib/systemd/user/`
- **[`install/enable-services.sh`](https://github.com/basecamp/omarchy/blob/main/install/enable-services.sh)** runs `systemctl --user enable --now` for first-run activation
- **`loginctl enable-linger`** allows background operation without active login
- **Drop-ins** in [`migrations/1785608166.sh`](https://github.com/basecamp/omarchy/blob/main/migrations/1785608166.sh) inject environment variables where needed
- **Runtime control** uses standard `systemctl --user` commands
- **OOM protection** via `app.slice` targeting, configured in [`migrations/1785424256.sh`](https://github.com/basecamp/omarchy/blob/main/migrations/1785424256.sh)

## Frequently Asked Questions

### Do I need root privileges to manage Omarchy user services?

No. All `systemctl --user` commands operate entirely within your user session without elevated privileges. Only the initial package installation (placing files in `/usr/lib/systemd/user/`) requires root. Enable, disable, start, stop, and status commands work as your regular user.

### Why does Omarchy use user services instead of system services?

User services provide better **session integration**—they automatically inherit your environment, use your UID for file permissions, and terminate cleanly on logout (unless lingering is enabled). System services would require complex privilege dropping and environment reconstruction to achieve the same desktop integration.

### How do I prevent an Omarchy service from starting automatically?

Use `systemctl --user disable servicename.service` to remove the startup symlink, or `systemctl --user mask servicename.service` to prevent manual starts as well. Masking creates a null symlink that blocks even implicit dependencies from starting the unit.

### Can I modify a unit file without losing changes on update?

Yes. Create a **drop-in override** rather than editing the base unit:

```bash
systemctl --user edit omarchy-sleep-lock.service

```

This opens an editor for a drop-in file that persists across package updates, while the base unit remains managed by Omarchy's package.