Modern Linux system administration and DevOps automation have transitioned rapidly towards declarative, immutable infrastructure. Traditionally, creating system user accounts and service groups on Debian and Ubuntu systems relied on imperative shell commands executed in post-installation scripts (such as useradd, adduser, or groupadd). While functional for manual setup, imperative user management introduces race conditions in container base images, creates UID/GID allocation mismatches across clustered nodes, and complicates stateless operating system provisioning.
The systemd suite provides an official declarative framework for managing system identities: systemd-sysusers. By defining service accounts, group memberships, login shells, and home directories in simple configuration files within /etc/sysusers.d/, administrators ensure that system users and groups are allocated consistently at package installation, image build time, or early system boot. Mastering systemd-sysusers streamlines automated deployment across Ubuntu servers and container environments.
Understanding systemd-sysusers Architecture
The systemd-sysusers tool reads declarative configuration files from three primary filesystem directories, prioritized in standard systemd order:
/etc/sysusers.d/*.conf: Local system administrator overrides and custom application configurations (highest priority)./run/sysusers.d/*.conf: Ephemeral configurations generated at runtime by orchestrators./usr/lib/sysusers.d/*.conf: Upstream package defaults shipped by the operating system distribution (lowest priority).
During system boot or when executed manually, systemd-sysusers parses these files, checks /etc/passwd and /etc/group, and idempotently creates missing entries without modifying existing users. System accounts created through this mechanism are automatically locked (no password) and allocated from the system UID/GID range (typically below 1000).
Configuration File Syntax and Directives
Files in sysusers.d use a whitespace-separated tabular format consisting of six fields per line:
Type Name ID GECOS HomeDirectory Shell
Field Descriptions
- Type: The entry classification:
u: Create a user and a matching group with the same name.g: Create a standalone group without a matching user.m: Add an existing user to an existing group.r: Reserve a numeric UID/GID range without creating accounts.
- Name: The account or group name (e.g.,
prometheus,nginx-worker). - ID: The requested numeric UID/GID, a specific range, a path to another file whose ownership to mirror, or
-to automatically assign the next available system ID. - GECOS: A descriptive comment or full name enclosed in quotation marks, or
-for none. - HomeDirectory: The path to the account’s home folder, or
-to default to/(or/nonexistent). - Shell: The login shell path, or
-to default to/usr/sbin/nologin.
Creating Custom System Users and Groups
To create a dedicated service account for a custom background daemon (for example, a telemetry agent named telemetryd):
1. Create a new configuration file in /etc/sysusers.d/:
sudo nano /etc/sysusers.d/telemetryd.conf
2. Define the user, an accompanying group, and supplementary group memberships:
# Type Name ID GECOS HomeDirectory Shell
u telemetryd - "Telemetry Collector Daemon" /var/lib/telemetryd /usr/sbin/nologin
m telemetryd systemd-journal
This single configuration file specifies that:
- A system user named
telemetrydand a primary group namedtelemetrydare created with auto-allocated IDs. - The account comment is set to “Telemetry Collector Daemon”.
- Its home directory is configured as
/var/lib/telemetrydwith a disabled login shell. - The user is automatically added to the
systemd-journalsupplementary group to read system logs.
Validating and Applying Configurations
You can execute systemd-sysusers safely while the server is live. To dry-run and inspect what actions the utility will perform without writing changes to /etc/passwd or /etc/group:
systemd-sysusers --dry-run
To apply the configuration changes immediately:
sudo systemd-sysusers
Verify that the user and group were created successfully:
id telemetryd
The console returns the newly provisioned UID, primary GID, and supplementary groups:
uid=994(telemetryd) gid=994(telemetryd) groups=994(telemetryd),101(systemd-journal)
Allocating Static UIDs for Clustered Applications
In distributed database clusters (such as Ceph, PostgreSQL, or Kubernetes shared storage) using NFS or distributed block storage, file permissions break if UIDs differ across nodes. Force identical numeric UIDs and GIDs by specifying the ID field explicitly:
# Type Name ID GECOS HomeDirectory Shell
u dbadmin 850 "Database Operator" /var/lib/dbadmin /bin/bash
When executed across all cluster nodes, systemd-sysusers guarantees that dbadmin is assigned UID 850 and GID 850 everywhere.
Integrating with systemd Services
Systemd units can reference users created by sysusers seamlessly inside service definitions:
[Service]
Type=simple
User=telemetryd
Group=telemetryd
ExecStart=/usr/local/bin/telemetry-collector
Adopting systemd-sysusers modernizes identity management on Ubuntu, replacing error-prone shell scripts with declarative, predictable system configurations.