Minimal script to start the X server manually from the text console (a lot simplified annotated customization-friendly alternative to the startx).
The xx
name is convenient when it has to be typed from a misconfigured
keyboard after arbitrary boot problem. Single x
would be even simpler, but
it would be also prone to launch unintentionally. The xx
script itself does:
- Creates the session data directory
/tmp/X0
. - Starts user's dbus for the browser to work correctly.
- Starts user's pulseaudio sound server.
- Sets the xauthority authentication cookie for X.
- Moves the
Xorg.0.log
to/tmp/X0
. - Makes temporary xinitrc to start a window manager.
- Runs the X server.
- Removes all session data after the X is closed.
All X runtime files will be created or redirected into /tmp/X0
. The X0
stands for the "X display 0". The main runtime files will be:
/tmp/X0/dbus -> dbus socket file
/tmp/X0/dbus.log -> dbus log
/tmp/X0/xauthority -> authentication cookie
/tmp/X0/xinitrc -> xinitrc
/tmp/X0/xorg.log -> standard X log
/tmp/X0/xorg.stdout -> console messages from X
Unfortunately, the user's session dbus daemon is needed for the browser to obtain links from apps, or for some other bigger/container apps to interact with each other. Otherwise, it is not needed.
The environment variable $DBUS_SESSION_BUS_ADDRESS
needs to be exported to
define the path to a socket file. The standard location
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$UID/bus"
is not reliable
(might be missing), so we use our /tmp/X0/dbus
instead.
Before starting the dbus-daemon
we kill the one hanging from the previous
session. In this step, a potential stalled socket file was already removed,
when we removed a whole /tmp/X0
directory in the previous step. We log dbus
info into /tmp/X0/dbus.log
, instead of the default syslog.
Unfortunately, the DBUS_SESSION_BUS_ADDRESS
name was chosen as the
standard, instead of a simple DBUS
.
Unfortunately, a running audio server is needed for applications to be able to
play sound or just to not hang. Often, pulseaudio
is required. Pulseaudio
saves its runtime stuff to ~/.config/pulse
, to /var/run/user/ID/pulse
plus
syslog or journal. To move it to /tmp/pulse
we need to set
PULSE_RUNTIME_PATH
and XDG_CONFIG_HOME
and let pulseaudio clients know it in
the /etc/pulse/clients.conf
:
extra-arguments = --log-target=stderr
cookie-file = /tmp/pulse/cookie
Main pulseaudio runtime files will be:
/tmp/pulse/cookie -> authentication cookie
/tmp/pulse/socket -> sound server socket
/tmp/pulse/pulse.log -> sound server log file
/tmp/pulse/pid -> sound server PID
We chose /tmp/pulse
instead of /tmp/X0/pulse
, as the pulseaudio is
potentially independent from X. Also, this path has to be referenced as a
string in /etc/pulse/client.conf
and /etc/pulse/default.pa
, which further
supports the simpler path choice.
The pulseaudio --log-target=file
uses some logic to handle things, to avoid
to work around it we rather use the --daemonize=no --log-target=stderr
and
point STDERR to a file.
Similarly to step 4. we can grant a group access to the pulseaudio
by
changing the /tmp/pulse
permissions, but we also need to negotiate common
socket file location by adding this line to /etc/pulse/clients.conf
:
default-server = unix:/tmp/pulse/socket
and this line to /etc/pulse/default.pa
:
load-module module-native-protocol-unix auth-anonymous=1 socket=/tmp/pulse/socket
To use the /tmp/pulse/cookie
instead of creating a new one in
~/.config/pulse/cookie
the other users have to set the $XDG_CONFIG_HOME
in
.bashrc
or .zshrc
:
export XDG_CONFIG_HOME=/tmp
Any custom pulseaudio setup, which will otherwise go into ~/config/pulse
needs to be copied in the xx script to the /tmp/pulse
, similarly to the
xinitrc file from step 6. Alternatively, things can be set directly in
/etc/pulse
files.
On Ubuntu or other systemd based systems, the pulseaudio daemon is started on user's login, to stop it and use only the xx pulseaudio do something like:
ln -sf /dev/null /etc/systemd/user/default.target.wants/pulseaudio.service
ln -sf /dev/null /etc/systemd/user/sockets.target.wants/pulseaudio.socket
An authentication cookie file is used to secure the X access to only a single user. User-run applications can use the X only if they can read the cookie file. In this script, we can use the same cookie file for the X server and for the client (user application), because we expect the server to be run by the user too.
The location of the cookie file is revealed to clients by the XAUTHORITY
environment variable, and to the X server by the -auth
switch. Without the
touch $XAUTHORITY
the xx
will work but complain. Without the manual
xauth
setup, X will create and use the ~/.Xauthority
file. For the
host-based access the default 600
permissions set by xauth
need to be
overridden to allow other users to read the cookie too by adding: chmod 644 $XAUTHORITY
to the xx
script.
Similarly, the group based access can be granted by creating a group xorg
(for instance) and assigning users to it by echo "xorg:x:200:user1,user2" >> /etc/group
(for instance). Then, a re-login is needed to activate the xorg
group. Finally, we can grant access to the cookie for a whole group in the
xx
script by adding:
chgrp xorg $XAUTHORITY
chmod 640 $XAUTHORITY
The ssh -X/Y
from remote to this host will create its own ~/.Xauthority
cookie on this host. This cookie is different from /tmp/X0/xauthority
, it is
unique for every ssh session, and you can remove it after the ssh session.
Why have more users share a single X session? Modern trend is to force multiuser operating systems to accept only a single user, or support/suggest single-user usage scenarios. However, it gradually becomes more advantageous for a single human to use multiple user accounts concurrently. Modern applications tend to automatically store settings, profiles, states, caches, dependencies for a particular user and to modify their own functionality accordingly. But, people often work on several completely different projects requiring to use tools in different ways, to remember different coworkers, different passwords, bookmarks, folders, etc. Multiple user accounts for a single human can help! To fully use the advantage of multiple accounts you need to be able to open windows from two accounts at the same time to copy-paste, compare, etc. ...and it is easy!
The default location of the user-run X server is in the user's home directory
~/.local/share/xorg/Xorg.0.log
. This path is hardcoded in the X server
program and the -logfile
option is available only to the root user. Thus to
move the user-run X log from /home
to /tmp/X0
we must use a symlink, which
is what we do in this step.
The log file of the root-run X can be stored in the /tmp/X0
using the
-logfile
, but also by the symlink: ln -s /var/log/Xorg.0.log /tmp/X0/xorg.log
.
TODO: Hack the X server to allow to log directly to the /tmp/X0
as a user.
In this step, we just copy the ~/.xinitrc
to our runtime directory /tmp/X0
.
However, instead of this copying, the xinitrc content can be generated on the
fly in the xx
script to contain the whole X setup in a single file. Like
this:
echo "setxkbmap dvorak" > $XINITRC
echo "fvwm -f ~/.fvwmcfg" >> $XINITRC
Another mechanism to set up the X are the /usr/share/X11/xorg.conf.d
files.
However, some things have to be set by the xinitrc even if they are already set
in xorg.conf
. For instance, if a keyboard is configured only in the
xorg.conf
, then the window manager which is run from the xinitrc might not
have the keyboard correctly configured in the time it is initialized.
Here we run the X server Xorg
through the xinit
program for the display
:0
reusing the current virtual console. We also log the X server stdout
messages to the xorg.stdout
alongside its logfile xorg.log
.
In this step, we clean up everything that we created for the X to run:
- kill the dbus daemon,
- remove all runtime and log files, all of which we placed into
/tmp/X0
.
The X server also creates /tmp/.X11-unix
and /tmp/.ICE-unix
which we cannot
remove due to their root privileges. Also, if the X is run as root the log is
stored in /var/log/Xorg.0.log
and can be removed only by root.
- Edit the
xinitrc
part ofxx
, see section 5., make install
to copy thexx
to~/bin
.
Alternatively, use make install4group
or make install4host
to install the
modified xx
for group-based or host-based access. The default is single-user
access mode.
The X and pulseaudio group-based access used in steps 3 and 4 has the
primary-secondary roles: the initiating user is the primary one with the write
privileges, other users in the xorg
group are secondary with only the read
access. Instead of the xorg
, a good name for the group would be the name of
primary user.
We try to put all X and pulseaudio runtime data to the /tmp
and remove it at
the end of the session. This way we achieve:
- no waste data are stored,
- data are together, easier to inspect!
The dbusrc
and pulserc
files for the startup of daemons daemons allow the
"fire-and-forget" approach. If something in these less-important services
fails, it will not stop the X from starting, if something takes too long, it
will not slow down the main routine.
This xx
is written only for the display :0
.
https://gitlab.freedesktop.org/xorg/app/xinit ← startx & xinit sources