Users & Groups
User accounts on Shani OS follow standard Linux conventions — accounts are stored in /etc/passwd, /etc/shadow, and /etc/group, which live in the /etc overlay and persist across all OS updates and rollbacks.
The key difference from a traditional distro is that you should use adduser (not useradd) for interactive accounts. The adduser wrapper on Shani OS reads /etc/shani-extra-groups and automatically adds new users to all the groups they need (wheel, video, input, kvm, etc.) in one step. See User Provisioning for the full group reference.
---
On Shani OS: adduser vs useradd
| Command | Use when | |---------|----------| | sudo adduser <name> | Creating a human user — reads /etc/shani-extra-groups, sets Zsh shell, prompts for password | | sudo useradd | Scripted/service account creation where you need fine-grained control |
# Preferred: creates account, sets groups, prompts for password interactively
sudo adduser alice
# After adding, trigger shani-user-setup to provision Flatpak/Nix/subuid ranges
sudo touch /data/user-setup-needed
---
Creating Users
Interactive user (preferred)
sudo adduser alice
# Prompts for password and GECOS info
# Automatically adds to groups from /etc/shani-extra-groups
Scripted user creation
# Create account with home directory, set shell explicitly
sudo useradd -m -s /bin/zsh -c "Alice Smith" alice
# Set password
sudo passwd alice
# Add to all required groups
sudo usermod -aG wheel,video,input,audio,kvm,storage,network,realtime alice
# Trigger shani-user-setup for Flatpak/Nix/subuid provisioning
sudo touch /data/user-setup-needed
Service/system account (no login)
# System account: UID < 1000, no home, no shell, no password
sudo useradd --system --no-create-home --shell /usr/sbin/nologin myservice
# With a dedicated home directory (for service data)
sudo useradd --system --create-home --home-dir /var/lib/myservice \
--shell /usr/sbin/nologin myservice
---
Modifying Users
# Change display name (GECOS)
sudo usermod -c "Alice Smith" alice
# Change login shell
sudo usermod -s /bin/bash alice
# or interactively:
chsh -s /bin/bash alice
# Change home directory (use -m to move contents)
sudo usermod -m -d /home/newhome alice
# Lock an account (prepends ! to the password hash — SSH keys still work)
sudo usermod -L alice
# Unlock
sudo usermod -U alice
# Rename a user (also rename the home directory manually)
sudo usermod -l newname alice
sudo mv /home/alice /home/newname
sudo usermod -d /home/newname newname
# Expire an account on a specific date (format: YYYY-MM-DD)
sudo usermod -e 2026-12-31 alice
# Remove expiry
sudo usermod -e "" alice
---
Deleting Users
# Remove account but keep home directory (recommended — avoids accidental data loss)
sudo userdel alice
# Remove account AND home directory
sudo userdel -r alice
# Also remove the user's mail spool
sudo userdel -r -f alice
⚠️ On Shani OS,
/homeis a separate Btrfs subvolume (@home). Evenuserdel -ronly removes the directory — the subvolume itself remains. If you want to fully remove a user's data, delete the subvolume manually:
> sudo btrfs subvolume delete /home/alice >
---
Passwords
# Set or change your own password
passwd
# Set another user's password (root/wheel only)
sudo passwd alice
# Force password change on next login
sudo passwd -e alice
# Lock password login (SSH key auth still works)
sudo passwd -l alice
# Unlock
sudo passwd -u alice
# Check password status
sudo passwd -S alice
# Output: alice PS 2026-01-15 0 99999 7 -1
# Fields: username status last-change min-days max-days warn-days inactive-days
# status: PS=password set, LK=locked, NP=no password
Password aging with chage
# View aging settings
sudo chage -l alice
# Set maximum password age (days)
sudo chage -M 90 alice
# Force change on next login
sudo chage -d 0 alice
# Set account expiry
sudo chage -E 2026-12-31 alice
See ch* Commands for the full chage reference.
---
Groups
Creating and modifying groups
# Create a new group
sudo groupadd developers
# Create with a specific GID
sudo groupadd -g 2000 developers
# Rename a group
sudo groupmod -n devs developers
# Delete a group (does not affect users who were members)
sudo groupdel developers
Managing group membership
# Add a user to one or more groups (append — does not remove from existing groups)
sudo usermod -aG developers,docker alice
# Remove a user from a group
sudo gpasswd -d alice developers
# Set exact group list (replaces existing supplementary groups — use with care)
sudo usermod -G wheel,video,input alice
# Make a user the group administrator
sudo gpasswd -A alice developers
Inspecting group membership
# Show all groups the current user belongs to
groups
# Show groups for a specific user
groups alice
id alice
# List all members of a group
getent group wheel
# List all groups
getent group
# Check if a user is in a specific group
id alice | grep -w wheel
---
sudo & Privileges
On Shani OS, wheel group members have full sudo access. The configuration lives in /etc/sudoers (managed by the OS) and /etc/sudoers.d/ (your custom rules, captured by the overlay).
# Edit sudoers safely (validates syntax before saving — never edit /etc/sudoers directly)
sudo visudo
# Add a drop-in rule (preferred — less risk of locking yourself out)
sudo nano /etc/sudoers.d/my-rules
Common sudoers patterns
# Full sudo without password (convenient for a personal machine)
alice ALL=(ALL) NOPASSWD: ALL
# Allow a specific command without password
alice ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart caddy
# Allow a group to run a command without password
%developers ALL=(ALL) NOPASSWD: /usr/bin/podman
# Run commands as a specific user (not root)
alice ALL=(deploy) NOPASSWD: /usr/local/bin/deploy.sh
# Restrict to specific hosts
alice workstation=(ALL) ALL
⚠️ Always use
sudo visudoorsudo visudo -f /etc/sudoers.d/myrule— it validates syntax before writing. A syntax error in sudoers locks out all sudo access. If this happens, boot to the other slot and fix the file via the/etcoverlay.
Running commands as another user
# Run as root
sudo command
# Run as a specific user
sudo -u alice command
# Open a root shell (full environment)
sudo -i
# Open a shell as another user
sudo -u alice -s
# Check what sudo permissions the current user has
sudo -l
---
Inspecting Accounts
# Current user and UID
whoami
id
# Who is logged in right now
who
w
# Login history (reads /var/log/wtmp)
last
last alice # filtered by user
last -n 20 # last 20 entries
last reboot # reboot history
# Failed login attempts (reads /var/log/btmp)
sudo lastb
sudo lastb -n 20
# Last login time per user
lastlog
lastlog -u alice
# List all user accounts (UID >= 1000 = human users)
getent passwd | awk -F: '$3 >= 1000 {print $1, $3, $6, $7}'
# Currently active login sessions
loginctl list-sessions
loginctl show-session 1
loginctl show-user alice
---
Linger (User Services Without Login)
By default, user systemd services stop when the last session for that user ends. Enable linger to keep user services running at all times — required for user-level backup timers, containers, and any service that should run without an active login:
# Enable linger for a user
sudo loginctl enable-linger alice
# Disable
sudo loginctl disable-linger alice
# Check linger status
loginctl show-user alice | grep Linger
This is required for the backup.timer and any other systemctl --user timer that should fire even when the user is not logged in. See Backup & Recovery for the full example.
---
/etc/passwd and /etc/shadow
These files live in the /etc overlay and are preserved across every OS update. You rarely need to edit them directly — use the commands above. For reference:
/etc/passwd — username:x:UID:GID:GECOS:home:shell
/etc/shadow — username:hashed-password:last-change:min:max:warn:inactive:expire
/etc/group — groupname:x:GID:member1,member2
/etc/subuid — username:start:count (rootless container UID ranges)
/etc/subgid — username:start:count (rootless container GID ranges)
# Read entries for a specific user (uses NSS — works with LDAP too)
getent passwd alice
getent shadow alice # requires root
getent group developers
---
Troubleshooting
| Issue | Solution | |-------|----------| | New user missing groups (kvm, video, etc.) | Run sudo touch /data/user-setup-needed to trigger shani-user-setup; or sudo FORCE_SETUP=1 shani-user-setup | | sudo: alice is not in the sudoers file | Add alice to the wheel group: sudo usermod -aG wheel alice; log out and back in | | Group membership not taking effect | Log out and back in — supplementary groups are read at login. To apply immediately: newgrp developers (opens a subshell in that group) | | userdel: user alice is currently used by process | Kill active sessions first: sudo loginctl kill-user alice; then retry | | User can't run rootless Podman | Check cat /etc/subuid — if alice has no entry, run sudo touch /data/user-setup-needed | | Locked out of sudo (syntax error in sudoers) | Boot into the other slot from systemd-boot; mount the /etc overlay and remove the broken file from /data/overlay/etc/upper/sudoers.d/ | | Account exists but home directory is missing | sudo mkhomedir_helper alice or sudo cp -a /etc/skel /home/alice && sudo chown -R alice:alice /home/alice |
---
See Also
- User Provisioning —
shani-user-setup,/etc/shani-extra-groups, subuid allocation - ch* Commands —
chmod,chown,chage,chsh,chpasswd - System Config — how
/etcoverlay preserves account changes across updates - Factory Reset — what happens to user accounts after a reset
- Shell & Environment — Zsh, Starship, and per-user shell config