Control Debian X Sessions with Xsession.options
Xsession.options is the file that decides whether your desktop trusts your own startup script, and most people never look at it until a login breaks. This guide switches user startup files, X resources, failsafe sessions, D-Bus activation and SSH-agent wrapping on or off, without touching the Xsession shell script itself.
The route
Jump straight to the step you need, or tick off Done means at the end.
It follows the Xsession.options(5) shipped by x11-common version 1:7.7+23ubuntu4 on this machine. The file format is shared across Debian-derived systems, but the available options and package version can differ on yours. Allow about ten minutes, plus one X session restart to test the result.
You need a shell and access to the machine's X session configuration. Reading and checking files is unprivileged. Changing /etc/X11 needs an account permitted to use sudo. A configuration change affects the next X session, so save your current state first and make the change when you have a way back in.
1. Check the package and current configuration
Start with read-only checks. They show which package supplied the behaviour and which options are currently enabled:
$ dpkg-query -W -f='${Package} ${Version}\n' x11-common
x11-common 1:7.7+23ubuntu4
$ sed -n '1,120p' /etc/X11/Xsession.options
# configuration options for /etc/X11/Xsession
allow-failsafe
allow-user-resources
allow-user-xsession
use-ssh-agent
use-session-dbus
Your version and file may not match this output. The shipped defaults enable all five documented options on this host. Do not assume a line present means the feature is actually in use: use-ssh-agent, for example, only wraps the startup command when no agent process already appears to be running.
Checkpoint
Keep a copy of the output, or record the file's checksum, before you edit anything.
$ sha256sum /etc/X11/Xsession.options
HASH /etc/X11/Xsession.options
2. Understand the option format
Each non-comment line contains one hyphen-separated option. A plain name enables it; prefixing it with no- disables it. Blank lines and comments beginning with # are fine to use.
Options are read from /etc/X11/Xsession.options, then from files matching *.conf in /etc/X11/Xsession.options.d/, in sorted order. The last occurrence wins, enable or disable. That ordering is exactly what makes the drop-in directory useful: a local file can override a vendor setting without changing the main one.
For a quick, read-only view of the effective text, show both sources in the order that Xsession reads them:
$ { cat /etc/X11/Xsession.options 2>/dev/null; \
run-parts --list --regex '\\.conf$' /etc/X11/Xsession.options.d 2>/dev/null | \
xargs -r -d '\n' cat; } \
| nl -ba
This shows lines, not a parsed summary. If two lines mention the same option, the later one is authoritative. Keep filenames simple, such as 90-local.conf; a file without the expected .conf suffix is ignored on this path entirely.
3. Add a narrowly scoped policy
Say this machine must never run a user's executable ~/.xsession as the session startup program. The relevant option is allow-user-xsession. Disabling it also blocks an explicitly requested session program from being accepted through the paths described by Xsession(5).
Warning
This changes how every user's graphical session starts. Test it on a machine where you have a second access path, and do not combine it with unrelated session changes.
Create a drop-in with elevated privileges:
$ printf '%s\n' '# Local session policy' 'no-allow-user-xsession' | \
sudo tee /etc/X11/Xsession.options.d/90-local.conf
# Local session policy
no-allow-user-xsession
The tee command writes the new file as root without touching the vendor file. Check the result and the file mode:
$ sudo cat /etc/X11/Xsession.options.d/90-local.conf
# Local session policy
no-allow-user-xsession
$ sudo test -f /etc/X11/Xsession.options.d/90-local.conf && echo 'drop-in exists'
drop-in exists
Do not stack several experiments in one drop-in while diagnosing a failed login. One change per file makes the cause easy to spot.
4. Choose the other controls deliberately
The documented options have different effects:
allow-failsafepermits thefailsafesession argument, which starts only an X terminal emulator and no window manager. Without an available terminal emulator, that session just exits.allow-user-resourcespermits$HOME/.Xresourcesto be merged with the system X resources at login.allow-user-xsessionpermits a user's executable.xsessionstartup file. A present but non-executable file may still be run as a Bourne shell script.use-session-dbusactivates a session bus when thedbuspackage is installed.use-ssh-agentusesssh-agentto run the startup command only when an agent does not already appear to be running.
For example, a host policy that keeps user resources but disables both user startup scripts and automatic agent wrapping would use:
# /etc/X11/Xsession.options.d/90-local.conf
no-allow-user-xsession
no-use-ssh-agent
Use the exact option names from the installed manual. An administrator may support additional local options, but an unfamiliar name is not proof that a feature actually exists.
5. Verify precedence before restarting X
Check for every occurrence of the option you changed:
$ { cat /etc/X11/Xsession.options 2>/dev/null; \
run-parts --list --regex '\\.conf$' /etc/X11/Xsession.options.d 2>/dev/null | \
xargs -r -d '\n' cat; } | grep -nE '(^|^no-)allow-user-xsession$'
3:allow-user-xsession
1:no-allow-user-xsession
The line numbers above are illustrative because the combined input depends on your own files. In the real output, the final matching line must read no-allow-user-xsession. If a later drop-in re-enables it, rename or edit that later file rather than guessing which one wins.
Start a new X session through your normal display manager or startx path. Do not invoke /etc/X11/Xsession directly as a substitute: the manual says it needs the environment set up by an X server startup mechanism. If the session fails, inspect the user's X session log, commonly $HOME/.xsession-errors, from another login.
6. Undo the change cleanly
Because the example added one isolated file, recovery is simple. This removes the local policy and leaves the vendor file untouched:
$ sudo rm /etc/X11/Xsession.options.d/90-local.conf
$ sudo test ! -e /etc/X11/Xsession.options.d/90-local.conf && echo 'drop-in removed'
drop-in removed
Removal is irreversible for that file. If it holds local work you might need later, move it to a clearly named backup instead of deleting it. After undoing the setting, start a fresh X session and confirm the original configuration is effective again: a running session does not retroactively re-read these options.
Done means
- Version recorded. You identified the installed
x11-commonversion and saved the current configuration. - Format understood. You know that
no-optiondisables an option and that later occurrences win. - Change isolated. Your local change lives in an ordered
*.confdrop-in, not an edited vendor file. - Precedence checked. You checked the final occurrence before starting a new X session.
- Recovery ready. You have a recovery path and can remove the drop-in without touching unrelated session settings.