---
title: Fun with NX stuff
date: "2009-10-15"
author: Chris Hodapp
tags:
- Technobabble
---

So, I was trying out various NX servers because I'd had very good luck
with NX in the past and generally found it faster than VNC, RDP, or
X11 over SSH. My options appeared to be:

- NoMachine's server
  ([here](http://www.nomachine.com/select-package.php?os=linux&amp;id=1)),
  which is free-as-in-beer but supports only 2 simultaneous sessions.
- [FreeNX](http://freenx.berlios.de/) made from the components that
  NoMachine GPLed. It's open souce, but apparently is a total mess and
  notoriously hard to set up. However, it doesn't limit you to two
  sessions, as far as I know.
- [neatX](http://code.google.com/p/neatx/), implemented from scratch
  in Python/bash/C by Google for some internal project because
  apparently FreeNX was just too much of a mess. Like FreeNX, it lacks
  the two-session limitation; however, it doesn't handle VNC or RDP,
  only X11.

NoMachine's server was a cinch to set up (at least on Fedora). The
only thing I remember having to do is put my local hostname (idiotbox)
in `/etc/hosts`. Performance was very good (though I haven't tried
RDP or VNC over a slower link yet - only a LAN with VirtualBox's
built-in RDP server).

neatX was a bit tougher to set up, primarily because the documentation
I saw was very sparse. This
[blog post](http://people.binf.ku.dk/~hanne/b2evolution/blogs/index.php/2009/09/01/neatx-is-the-new-black)
was helpful. It advised that you should make sure you could log in
with SSH manually before checking anything else, which gave me a
starting point for my problems.

I took these notes on how I made it work:

- Install all of the dependencies it says. ALL OF THEM!
- Follow the other instructions in `INSTALL`.
- Go to `/usr/local/lib/neatx` and run `./nxserver-login`.  If it
  looks like this, you're probably good:

```bash
[hodapp@idiotbox neatx]$ ./nxserver-login
HELLO NXSERVER - Version 3.3.0 - GPL
NX> 105
```

  If not, you may need to install some dependencies or check paths of
  some things. If it complains about not being able to import
  neatx.app, add something like this to the top of `nxserver-login`
  (replacing that path with your own if needed, of course):

```python
import sys
sys.path.append("/usr/local/lib/python2.6/site-packages")
```

- Set up password-less login for user `nx` using something like
  `ssh-keygen -t rsa` and putting the private & public keys someplace
  easy to find. Check that this works properly from another host
  (i.e. put the public key in the server's `authorized_keys` file in
  `~nx/.ssh`, copy the private key to the client, and use `ssh -i
  blahblahprivatekey nx@server` there to log in. It should look
  something like this:

```bash
chris@momentum:~$ ssh -i nx.key nx@10.1.1.40
Last login: Sun Oct 11 13:11:49 2009 from 10.1.1.20
HELLO NXSERVER - Version 3.3.0 - GPL
NX> 105
```

If it asks for a password, something's wrong.

If it terminates the connection immediately, SSH is probably okay, but
something server-side with neatX is still messed up. SSH logs can
sometimes tell things.

Once I'd done all this, neatX worked properly. However, I had some
issues with it - for instance, sometimes the entire session quit
accepting mouse clicks, certain windows quit accepting keyboard input,
or things would turn very sluggish at random. But for the most part it
worked well.

After setting up SSH stuff, FreeNX server worked okay from Fedora's
packages after some minor hackery (i.e. setting user the login shell
for user `nx` to `/usr/libexec/nx/nxserver`. I haven't yet had a
chance to test it over a slow link, whether with X11 or RDP or VNC,
but it worked in a LAN just fine. Someone in the IRC channel on
FreeNode assures me that it runs flawlessly over a 256 kilobit link.

Then, for some reason I really don't remember, I decided I wanted to
run all three servers at once on the same computer. As far as I know,
all of the NX clients log in to the server initially by passing a
private key for user `nx`. The server then runs the login shell
set in `/etc/passwd` for `nx` - so I guess that shell determines
which NX server handles the session.

So, amidst a large pile of bad ideas, I finally came up with this
workable idea for making the servers coexist: I would set the login
shell to a wrapper script which would choose the NX server to then
run. The only data I could think of that the NX client could pass to
the server were the port number and the private key, and this wrapper
script would somehow have to get this data.

Utilizing the port number would probably involve hacking around with
custom firewall rules or starting multiple SSH servers, so I opted to
avoid this method. It turns out if you set `LogLevel` to `VERBOSE` in
sshd_config (at least in my version), it'll have lines like this after
every login from the NX client: ` Oct 14 18:11:33 idiotbox
sshd[15681]: Found matching DSA key:
fd:e9:5d:24:59:3c:3c:35:c5:29:74:ef:6d:92:3c:e4 ` You can get that key
fingerprint with `ssh-keygen -lf foo.pub` where foo.pub is the public
key.

So I generated 3 keys (one for neatX, NoMachine's server, and FreeNX),
added them all to **authorized_keys**, found the fingerprints, and
ended up with a script that was something like this:

```bash
#!/bin/sh
FINGERPRINT=$(grep "Found matching RSA key" /var/log/secure |
     tail -n 1 | egrep -o "(..:){15}..")
if [ $FINGERPRINT == "26:dd:67:82:c1:2d:cc:c0:c6:13:ac:d4:49:0e:79:a3" ]; then
    SERVER="/usr/local/lib/neatx/nxserver-login-wrapper"
elif [ $FINGERPRINT == "35:fb:bd:45:c5:71:91:ce:d6:d9:7f:0b:dc:84:f4:b3" ]; then
    SERVER="/usr/NX/bin/nxserver"
elif [ $FINGERPRINT == "b5:d7:a5:18:0d:c4:fa:18:19:58:20:00:1d:3b:3c:84" ]; then
    SERVER="/usr/libexec/nx/nxserver"
fi
$SERVER
```

I saved this someplace, set it executable, and set the login shell for
`nx` in `/etc/passwd` to point to it. Make sure the home directory
points someplace sensible too, as the install script for some NX
servers are liable to point it somewhere else. But as far as I can
tell, the only thing they use the home directories for is the `.ssh`
directory and all the other data they save is in locations that do not
conflict.So I copied the three public keys to the client and manually
did `ssh -i blah.key nx@whatever` on each key.

```bash
chris@momentum:~$ ssh -i freenx-key nx@10.1.1.40
HELLO NXSERVER - Version 3.2.0-74-SVN OS (GPL, using backend: 3.3.0)
NX> 105
chris@momentum:~$ ssh -i neatx-key nx@10.1.1.40
HELLO NXSERVER - Version 3.3.0 - GPL
NX> 105
chris@momentum:~$ ssh -i nomachine-key nx@10.1.1.40
HELLO NXSERVER - Version 3.4.0-8 - LFE
NX> 105
```

The different versions in each reply were a good sign, so I tried the
same keys in the client, and stuff indeed worked (at least according
to my totally non-rigorous testing). Time will tell whether or not I
completely overlooked some important details or interference.
