Set a Reliable Per-User X Session with Xsession
You log in graphically and get the wrong desktop, or none at all, because nobody told you Xsession decides that on your behalf. This guide gets your own .xsession starting a chosen desktop or window manager from your home directory, with a clean way back if it goes wrong. It matches x11-common 1:7.7+23ubuntu3, installed on the machine used for these examples.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about 15 minutes. You need an existing X installation, a session command that is already installed, and a shell account with write access to your home directory. The examples do not need root. Do not run /etc/X11/Xsession directly: it expects the environment created by startx, xinit or a display manager.
1. Identify the session command
Find the program you intend to start: the command name supplied by your desktop environment or window manager. The check below is harmless; replace the placeholder with a real command such as xfce4-session or i3 only if that command is installed on your system.
$ SESSION_COMMAND='your-session-command'
$ command -v "$SESSION_COMMAND"
/usr/bin/your-session-command
If command -v prints nothing, stop and choose an installed session program instead. Xsession searches the session command in $PATH when it is passed as an argument, but a missing command falls back to the normal selection process rather than failing outright.
Checkpoint
You have a command path and know whether it needs arguments. Keep the command simple for the first test; add options only once the session starts correctly.
2. Back up any existing user session file
With the default options on this installation, Xsession accepts $HOME/.xsession and then $HOME/.Xsession, using whichever it finds first. A non-executable file runs through the shell; an executable file starts directly. Check both names before touching anything.
$ ls -l "$HOME/.xsession" "$HOME/.Xsession" 2>/dev/null || true
If either file exists and holds settings you need, make a dated backup. This only touches your home directory and is fully reversible.
$ BACKUP="$HOME/.xsession.backup-$(date +%Y%m%d-%H%M%S)"
$ if [ -e "$HOME/.xsession" ]; then cp -a "$HOME/.xsession" "$BACKUP"; fi
$ if [ -e "$HOME/.Xsession" ]; then cp -a "$HOME/.Xsession" "$BACKUP-uppercase"; fi
$ ls -l "$BACKUP"* 2>/dev/null
To undo the change later, remove or rename the new .xsession and restore the right backup. Do this from a text console or another login, not from inside the graphical session you are fixing.
3. Create the smallest useful .xsession
Write one command as the final line of $HOME/.xsession. Xsession eventually uses exec on the selected startup program, so the session command needs to stay in the foreground. Do not append an ampersand: a backgrounded command can exit immediately and leave X with no controlling process at all.
$ printf '%s\n' '#!/bin/sh' 'exec your-session-command' > "$HOME/.xsession"
$ chmod 700 "$HOME/.xsession"
$ sed -n '1,5p' "$HOME/.xsession"
#!/bin/sh
exec your-session-command
Replace your-session-command before starting X. A shell script does not strictly need the executable bit, but setting it makes the intended behaviour explicit and avoids surprises if a different launcher later picks the file up.
Security boundary
This file is shell code. It runs commands with your user privileges at every graphical login. Keep it owned by you and writable only by you.
$ stat -c '%U:%G %a %n' "$HOME/.xsession"
your-user:your-group 700 /home/your-user/.xsession
4. Check the file before logging in
Run the shell parser against the file. This checks syntax without launching the session command.
$ sh -n "$HOME/.xsession"
$ printf 'syntax check: ok\n'
syntax check: ok
Also confirm the named command is actually executable. This grabs the second field from the deliberately simple example above; if your file is more complex, check it by eye instead of trusting the shortcut.
$ SESSION_COMMAND='your-session-command'
$ command -v "$SESSION_COMMAND" && test -x "$(command -v "$SESSION_COMMAND")"
/usr/bin/your-session-command
Checkpoint
The parser exits successfully, the command exists, and the permissions do not grant group or other write access.
5. Start the session through its normal launcher
Log out and log back in through your display manager, or use startx from a text console if that is how your system starts X. Do not test by invoking Xsession itself: the display manager or xinit supplies the display, authorisation and other state the script depends on.
Knowing the default startup order helps when a login fails. Xsession first sources every valid file in /etc/X11/Xsession.d in run-parts order. It merges system X resources and, when allowed, $HOME/.Xresources. Only then does it consider a requested session, .xsession, .Xsession, and finally the first executable of /usr/bin/x-session-manager, /usr/bin/x-window-manager and /usr/bin/x-terminal-emulator.
6. Inspect the right log after a failure
Xsession sends its standard output and standard error to $HOME/.xsession-errors by default. Read the end of that file after dropping back to a text console or another login.
$ tail -n 80 "$HOME/.xsession-errors"
Xsession: X session started for ...
The exact lines depend on your desktop and installed packages, so look for the first command-not-found, permission or X connection error rather than the final message alone. On this installation the script caps the log at its latest 500,000 bytes, so copy anything useful before you repeat a noisy test.
If the home-directory log cannot be opened, the script tries a securely created temporary file instead and may link it as $TMPDIR/xsession-$USER, falling back to /tmp when TMPDIR is unset. A failure to create any log at all aborts the session, so check both locations when .xsession-errors is missing.
$ ls -l "$HOME/.xsession-errors" "${TMPDIR:-/tmp}/xsession-$USER" 2>/dev/null || true
7. Recover without guessing
If the graphical login loops, switch to a text console and move the user file out of the way. This is reversible and does not touch system configuration.
$ mv "$HOME/.xsession" "$HOME/.xsession.disabled"
$ chmod 600 "$HOME/.xsession.disabled"
$ printf 'custom session disabled; original saved at %s\n' "$HOME/.xsession.disabled"
Log in again. Xsession should now fall back to the system default, assuming a session manager, window manager or terminal emulator is installed. To restore the custom session once it is fixed, move the file back and run sh -n once more before trusting it.
An administrator can also change the policy in /etc/X11/Xsession.options, including allow-user-xsession, allow-user-resources and allow-failsafe. Those files need elevated privileges and affect every user, so do not edit them just to repair one account. If a policy change is needed, remember that later no- entries in /etc/X11/Xsession.options.d/*.conf override earlier ones.
Done means
- Command found.
command -vfinds the intended session program. - Syntax clean.
sh -n "$HOME/.xsession"exits with status 0. - Ownership correct. The file is owned by your account and is not group- or world-writable.
- Login works. The graphical login starts the intended session through the display manager or
startx. - Logs cover you. When something fails,
$HOME/.xsession-errorsor the temporary fallback log contains a useful diagnostic.