Homectl peculiarities

Why `homectl`-managed home directories behave differently from traditional ones

Posted by Navisence on Fri, Dec 12, 2025

TL;DR

This post explains why homectl-managed home directories behave differently from traditional ones, why environment variables may be missing when a user logs in remotely, and how lingerd and PAM interact. It provides a stable configuration that allows SSH logins without requiring a local login first, while keeping environment initialization consistent.

Introduction

After using homectl on Linux for a while, I noticed thumbnails were no longer working. It was also impossible to change or keep some of the user system settings, like the sound settings. Investigating this led me into multiple rabbit-holes and dead ends. Eventually I made the suggestion of homectl being involded to an LLM and it then was able to point me in the right direction of where to look and how to solve this.

Once my system seemed stable and showing thumbnails again, I asked the LLM to help writing up on its findings.

Using homectl With SSH: Understanding Linger, PAM, and Environment Setup

Systemd’s homectl can provide encrypted, automatically mounted home directories with clean integration into user sessions. However, when using homectl on a workstation that also accepts SSH logins, you may run into surprising behavior:

  • Environment variables like XDG_DATA_DIRS fail to load over SSH.
  • The home directory doesn’t mount until a graphical login happens.
  • Enabling linger solves one problem but introduces others.

This post explains why these issues occur and presents a configuration that works reliably.

Why homectl Behaves Differently

When using systemd-homed, your home directory is not simply a static filesystem entry. Instead, systemd:

  1. Authenticates the user via systemd-homed (using JSON metadata).
  2. Mounts the home directory via a systemd-generated home-* mount unit.
  3. Applies user-side identity mapping (idmap + fs encryption).
  4. Starts a systemd user manager when a login session opens.

This means your home directory only exists after systemd-homed is invoked, and that depends on how you log in.

The Role of Linger

loginctl enable-linger USER keeps the user’s systemd instance running even when no sessions are active. This guarantees:

  • The home directory auto-mounts early in the boot process.
  • Systemd user services start without needing a login.
  • SSH sessions have access to the home directory.

However, lingering also means:

  • The system starts the user manager at boot.
  • PAM environment logic may not run for the first session, leading to missing variables.
  • Some XDG initialization that assumes an interactive login may not trigger.

In short: linger trades “always available” for “environment not completely initialized unless handled manually”.

Why Your Environment Variables Were Missing

When logging in via SSH with lingering enabled, the user manager may already be running before PAM sets up the environment. This means:

  • systemd --user starts with a minimal environment.
  • Later SSH sessions inherit environment variables from PAM only, but systemd user services do not.
  • Graphical sessions add another layer of environment configuration, which can mask the issue.

This is why disabling linger can make your environment correct — PAM initializes everything before the user manager starts — but then the home directory would not be available via SSH.

A Reliable Configuration

The working compromise is:

  1. Keep Linger Enabled so that SSH works and the home directory mounts.
  2. Explicitly set needed environment variables in:
    • /etc/environment for system-wide values, or
    • $HOME/.config/environment.d/*.conf for homed-specific, user-level environment.

This ensures both:

  • systemd user manager gets the correct environment at boot, and
  • all login methods (SSH, TTY, Wayland) behave consistently.

Example: create

1~/.config/environment.d/xdg.conf

with:

1XDG_DATA_DIRS=$/home/$USER/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share

Systemd will import this into the user manager before it starts, solving the mismatch.

Verifying the Result

1systemctl --user show-environment | grep XDG

should show the same values as:

1env | grep XDG

Regardless of:

  • graphical login
  • SSH login
  • lingering

Caveat: Don’t use static mount units with systemd-homed

When using systemd-homed, the home directory must not be mounted using:

  • /etc/fstab
  • a persistent /etc/systemd/system/home-$USER.mount unit
  • systemctl enable home-$USER.mount

systemd-homed creates its own transient home-USER.mount unit under /run/systemd/transient/ and manages the ordering internally.

If a static mount unit exists, systemd tries to mount the home directory during early boot, before systemd-homed is ready. This leads to:

  • long boot delays (typically ~90 seconds)
  • XDG directories being mis-set (//.cache, //.local/share)
  • services like xfconfd failing

If you previously experimented with manual mounting or fstab, ensure that /etc/systemd/system/home-USER.mount does not exist.

If it does:

1sudo rm /etc/systemd/system/home-USER.mount
2sudo systemctl daemon-reload

This restores proper homed behavior and eliminates the boot timeout.

Conclusion

systemd-homed is powerful, but it deviates from traditional UNIX assumptions. Understanding how user sessions, PAM, and the user manager interact makes it much easier to create predictable behavior.

By enabling lingering for availability and defining environment variables using environment.d, you get the best of both worlds:

  • SSH works before graphical login
  • home directory auto-mounts
  • environment is correct and consistent

More work than /etc/passwd, but also more flexibility.

Appendix

Check if linger is enabled

1loginctl show-user $USER | grep Linger

Check home mount status

1systemctl status home-$USER.mount

Inspect user manager environment

1systemctl --user show-environment