Setting up multimachine multiscreen with Xdmx

I do most of my work on a small laptop, which is small enough that I can use while commuting, but which has uselessly low 1280x768 screen resolution. In addition, I have a desktop with a 1680x1050 display, and an older laptop with a 1920x1200 display. I wanted to be able to use all three displays in multihead mode from my small laptop.

Xdmx is a way of setting up a multihead machine when the monitors are connected to multiple machines. Xdmx has several issues which I had to overcome:

In addition, Xdmx is quite slow. This, I could not overcome, but I was able to bring it up to a useable speed when used with a minimal window manager.

The steps to setting up Xdmx are:

  1. Find and install a working version of Xdmx. Newer ones don't work.
  2. Test Xdmx
  3. Set up X tunneling over ssh
  4. Fix Xdmx issues
  5. Automate the process

If you find problems with this tutorial, please e-mail me. I did the setup first, and then wrote this, so it is possible that I made typos or omitted steps.

Find and install a working version of Xdmx

The version of Xdmx included with Ubuntu and Debian is broken. It has at least two bugs that prevent it from working at all. I'm not entirely sure how Debian and Ubuntu could ship with a package that was, apparently, never tested, but they did. The first bug causes Xdmx to segmentation fault on startup. This one has a patch. Once patched, however, Xdmx spews out a stream of errors when the mouse is moved, and doesn't allow any keyboard or mouse input. I did not try to patch the next set of errors, since this was clearly not a working program.

The trick, then, is to install the last working version of Xdmx. In this case, it was the older Debian package xdmx version 2:1.1.1-21etch5. Fortunately, this package just works when installed from binary (you don't need to rebuild it from source).

Note that it is necessary to lock the package so that Ubuntu doesn't automatically upgrade it on the next system updated. This can be done from the package manager GUI.

Test Xdmx

The easiest way to have a minimal Xdmx setup is to use X TCP forwarding. Sadly, X TCP forwarding appears broken in my install of Ubuntu 8.10 (this is most likely a bug in Ubuntu, but it may be something related to the configuration of the specific machine). To discover that X TCP forwarding is broken in Ubuntu, the first step is to make sure that X forwarding is enabled. See your running processes with:

   ps aux |less
Make sure X is started without the -nolisten tcp option. On my system, to do this, I had to modify two files (this may be different on your system):
  /etc/X11/xinit/xserverrc (this is where the option belongs)
  /etc/gdm/gdm.conf (this is where Ubuntu placed it, because it is
    broken)
And then restart X. At this point, run:
  nmap localhost
You should see port 6000 open. If you do (I did on my Debian boxes, but not on my Ubuntu box), you can test Xdmx easily. If not, you'll need to test with ssh X forwarding, which is slightly more difficult.

Test Xdmx the easy way

This section assumes:

If either of these isn't the case, skip forward to the next section.

Assume you have three machines. host-machine is the machine you want to use. client-machine1 and client-machine2 are the machines you want to display on. On client-machine1 and client-machine2, run:

  xhost +host-machine
On host-machine, run:
  Xdmx :1 +xinerama -display client-machine1:0  -display client-machine1:0
You should now see X shared among the the two client machines (I omitted host-machine so that if something goes wrong, you still have a working terminal). At this stage, the important thing is that something recognizable pops up, and that you can use the mouse and keyboard. You may have screen relics or other ugliness

If this works, the next step is to test Xdmx with ssh port forwarding.

Test Xdmx with ssh port forwarding

Again, assume you have three machines. host-machine is the machine you want to use. client-machine1 and client-machine2 are the machines you want to display on. On client-machine1 and client-machine2, run:

  ssh -X username@host-machine
  export |grep DISP
You should see a string to the effect of:
  declare -x DISPLAY="host-machine:10.0"
and on the other client,
  declare -x DISPLAY="host-machine:11.0"
Take those strings, and on host-machine, run this command, with the appropriate strings substitute in:
  Xdmx :1 +xinerama -display host-machine:10.0  -display host-machine:11.0
You should now see X shared among the the two client machines (I omitted host-machine so that if something goes wrong, you still have a working terminal). At this stage, the important thing is that something recognizable pops up, and that you can use the mouse and keyboard. You may have screen relics or other ugliness.

Fix Xdmx issues

At this stage, Xdmx should work, but there may be issues. On my machine, Xdmx was too slow to be useable and had screen relics. To improve Xdmx speed, I changed the cipher used by ssh to Blowfish. To do this, when you ssh, add the option:
  -c blowfish-cbc 
Or on older systems,
  -c blowfish 

The next issue I had were screen relics, and Firefox didn't work. I fixed this by adding the options:

  -norender -noglxproxy 
To the xdmx command line. Read the xdmx man page, and try different options, until everything works.

Automate Xdmx

The next step is to automate Xdmx so that you don't have to type so much on each log-in. To do this, we will create a dummy account on host-machine that, when we ssh to, will record the appropriate display information from both clients. We will automate ssh by using authorized_keys. Finally, we will automate xdmx startup. If you don't already have one, on both client machines, use ssh-keygen to create an RSA private key (you can use DSA if you prefer), and copy it (~/.ssh/id_rsa.pub) to the host machine. On the host machine, run:

  adduser multiscreen
But do not set a password. Create directory:
  /home/multiscreen/.ssh
With permissions 600, multiscreen:multiscreen. Create a file:
  /home/multiscreen/.ssh/authorized_keys
With permissions 640, root:multiscreen. This file should contain:
command="/home/multiscreen/setup-xdmx lag" ssh-rsa jkhdsjkhskhsakhkhhsdhsd3829789e2y8dcgh7832y978fdghuk378tdc pmitros@client-machine1
command="/home/multiscreen/setup-xdmx rura" ssh-rsa 43890uhh498uyhuihg487yhfvh4897yhc87h489ch83h8ovfh984h87fh pmitros@client-machine2
But with the appropriate strings from id_rsa.pub from both clients instead of the above gibberish. If you want to be more secure, you can add fancy options to the command string to prevent other uses of ssh, but Xdmx already lets any of the three machines do anything on the other two that this is probably not too important. Create a file:
  /home/multiscreen/setup-xdmx
With permissions a+rx, which contains:
#! /bin/bash
echo Setting up XDMX as $DISPLAY
echo Press any key to exit
echo $DISPLAY > $1
echo $1 is: 
cat $1
xauth list > $1.mc
cat $1.mc
echo $XAUTHORITY
echo Authorized as $1
read -n 1 s
You should be able to ssh to the machine from either of the other two with the command:
  ssh -X -c blowfish-cbc multiuser@host-machine
And see some text. This should create two new files in /home/multiuser, one with your DISPLAY, and one with your MIT magic cookie for giving access to X. ssh from both clients to host-machine, and stay logged in. This sets up an ssh X tunnel. Now, in your normal account, create an Xdmx outline configuration file, with a dummy string for both machines. This file should be called ~/xdmx.conf.raw. In my case, it is:
virtual example3 { wall 3x1 :0 RURA LAG;
  option -input RURA +xinerama;
 }
Create a script, which will transform this file into a valid Xdmx config file, set up X permissions, and start xdmx. In my case, this was ~/xm:
cat xdmx.conf.raw |sed -e s/RURA/`cat ~multiscreen/rura`/g |sed -e s/LAG/`cat ~multiscreen/lag`/g > xdmx.conf
xauth add `tail -1 ~multiscreen/lag.mc`
xauth add `tail -1 ~multiscreen/rura.mc`
startx ./xinit -- /usr/X11R6/bin/Xdmx :1 -configfile xdmx.conf -config example3 -norender -noglxproxy
Now, to start Xdmx, all you need to do is: Voila! Multihead with multiple machines.
Mar 1, 2009 Last modified: Sun Mar 1 11:55:11 EST 2009