Centos – How to run Xvfb without root

centosxkbxorgxvfb

Desired result on a server without root:

1) Run Xvfb without input devices, or

2) Just get Xvfb to run

Background:

I have two machines both having nearly identical builds of CentOS. One machine has root access and internet and the other is sandboxed (no root access) with no package managers (no yum) and no Xserver. I'm trying to get Xvfb (X virtual frame buffer) running in the target machine for experimenting with headless firefox. When Xvfb is working, I can use xvfb-run.

What I've tried:

I've successfully transferred the Xvfb binary and the user shared libraries using this method (see the comment below the answer). I'm able to run Xvfb like so

Xvfb :1 -nolisten tcp -screen 0 1680x1050x16

but then I get a keymap error (Aside: I'd also like to deal with that temp dir issue as I've set export TMPDIR=~/tmp):

_XSERVTransmkdir: Owner of /tmp/.X11-unix should be set to root
XKB: Failed to compile keymap
Keyboard initialization failed. This could be a missing or incorrect setup of xkeyboard-config.
(EE)
Fatal server error:
(EE) Failed to activate core devices.(EE)

I don't need physical keyboard or mouse support at all. If someone could explain how to run Xvfb without input devices, then we can stop here. I've searched for hours with no success.


How I tried to get xkb working:

My next action was to bring over xkbcomp from the source machine along with the shared libraries. Next I exported the keymap file from the source machine like so:

xkbcomp -xkb $DISPLAY xkbmap

I tried to pass in the xkbdir and xkbmap to run the following with no success

Xvfb :1 -xkbdir ~/X11/xkb -xkbmap xkbmap -nolisten tcp -screen 0 1680x1050x16

because -xkbdir is a valid parameter, whereas -xkbmap is not despite the man page for Xvfb stating:

In addition to the normal server options described in the Xserver(1)
manual page, Xvfb accepts the following command line switches:

and the man page for Xserver stating:

−xkbdir directory
    base directory for keyboard layout files. This option is not available for setuid X servers (i.e., when the X server’s real and effective uids are different).
    ...
−xkbmap filename
    loads keyboard description in filename on server startup.

If I just pass in -xkbdir

$ export PATH=~/bin:$PATH; # all copied binaries are here, including xkbcomp
$ Xvfb :1 -xkbdir ~/X11/xkb -nolisten tcp -screen 0 1680x1050x16

then I get

_XSERVTransmkdir: Owner of /tmp/.X11-unix should be set to root
    sh: /usr/bin/xkbcomp: No such file or directory <-- WHY THIS PATH?
    sh: /usr/bin/xkbcomp: No such file or directory
    XKB: Failed to compile keymap
    Keyboard initialization failed. This could be a missing or incorrect setup of xkeyboard-config.
    (EE)
    Fatal server error:
    (EE) Failed to activate core devices.(EE)

This is where I've been stuck for hours. On a machine without root, either

1) How can I run Xvfb without input devices? or

2) How can I just get Xvfb to run?

Best Answer

Partial answer: How to run Xvfb without xkeycomp.

According to your description, your main problem doesn't seem to be to run Xvfb as non-root (that works quite well on my system), but that as non-root you cannot install auxiliary programs like xkeycomp and their associated data files in the place where Xvfb expects them.

That's difficult to simulate without knowing exactly what is and isn't installed on your sandboxed CentOS environment. But here's how to get rid of the xkeycomp dependency:

As using strings on Xvfb shows, the invocation of xkeycomp looks like "%s%sxkbcomp" -w %d %s -xkm "%s" -em1 %s -emp %s -eml %s "%s%s.xkm", and the corresponding source files are xkbInit.c and ddxLoad.c. From a cursory inspection, it looks like the path to xkbcomp is hardwired. But the string is long enough to replace it with a call to a script instead, which shows that Xvfb wants to compile the following description

xkb_keymap "default" {
    xkb_keycodes             { include "evdev+aliases(qwerty)" };
    xkb_types                { include "complete" };
    xkb_compatibility        { include "complete" };
    xkb_symbols              { include "pc+us+inet(evdev)" };
    xkb_geometry             { include "pc(pc105)" };
};

provided from stdin, into the file /tmp/server-1.xkm. So on a machine with X and tools, copy this description to a file, say default.xkb, and compile it

xkbcomp -xkm default.xkb 

to default.xkm. Now patch your copy of Xvfb on the CentOS sandbox by searching for the invocation:

$ grep -FobUa '"%s%sxkbcomp' Xvfb
1648800:"%s%sxkbcomp

and patch it with a call to cp:

echo -n '/bin/cp /home/dirk/tmp/xvfb/default.xkm /tmp/server-1.xkm          ' | dd bs=1 of=Xvfb seek=1648800 conv=notrunc

(of course with your position and your path to default.xkm).

That works fine on my machine, but on your sandboxed CentOS machine it will now probably trigger the next problem. :-)

And the X API decouples the functions to inspect the keyboard mapping from actual input devices, so even if there are no input devices, a keyboard mapping must still be present.

Related Question