Featherweight Linux VNC services
July 2, 2014 Leave a comment
This article describes how to set up a very lightweight VNC service under CentOS/Red Hat.
In Red Hat Enterprise Linux (and derivates, I use CentOS) you can run a VNC service to allow graphical connections to a linux system. I was looking for a very lightweight VNC service (no fancy desktop with all the bells and whistles, just something that lets me do some stuff that requires an X session and run an Xterm – such as installing Oracle or running Swingbench, without using another host with an X client). In other words, a typical service for virtual machines that run as servers (such as database servers, web servers, etc).
CentOS standard method
I tried the standard documented way to do this in CentOS: CentOS Virtual Network Computing using the standard tigervnc-server method, but found a few issues with the way they set it up:
- For every user requiring VNC services, you need to customize the configuration
- If one user deletes or corrupts his VNC password file, the whole service stops working (fix via normal SSH login but requires skilled user)
- If a user messes up his xstartup file he is locked out (fix via normal SSH login but requires skilled user)
- Users need 2 passwords: for their (own) VNC service, and the usual one for Linux
- Their X window and VNC processes are always running and thus eating resources even if not used
- If their X session hangs (i.e. window manager killed, or simple logout) it’s hard or even impossible to clean up and restart (see section 4 in the mentioned article: Recovery from a logout) without resetting the whole VNC service
- Every user requires a separate, unique TCP port
All by all, nice and easy for a small test server with a few users, but no good for larger environments. The good thing is that the desktops are persistent, i.e. you may disconnect and reconnect later and the VNC session will be as you left it. And you can install lighter desktop environments (twm or openmotif) instead of the huge and heavy Gnome desktop.
But I was looking for something better.
CentOS LTSP method
The other option is to use the non-persistent method described in the CentOS article under “5. Remote login with vnc-ltsp-config”. Instead of using a VNC password, it offers a desktop login screen if you connect to the VNC service. It also does not require any per-user setup, so that’s good!
So I tried that method as well, and also found it still less-than-ideal:
- It requires to install the entire Gnome desktop. I think that’s enormous overkill for the need to run an Xterm in a VNC session.
- It requires to run in Linux runlevel 5 with a graphical login on the VM’s admin console open at all times. More resources wasted as usually no-one will ever login via the VM’s console.
- No way to have persistent desktops any more. If you log out, session is killed.
- It’s only available via the EPEL repository for CentOS / Red Hat 5.x. 6.x does not provide the package (however if you install the 5.x package on 6.x it works fine).
Dirty Cache method
As my blog is all about doing more with less, I took up the gauntlet and started to figure out how I could have the best of all worlds. My service is called “lightvnc” and is available as an RPM package via my repository (see Software tab on this blog). If you don’t care how it works but just want to use it, just install the rpm and off you go. I recommend reading the man page for configuration details.
- Login manager XDM
- Window manager Openmotif (spartan, simple but very lightweight)
- Based on xinetd and xdm, no other daemons or services required until a connection is made
- VNC service on default port 5900, non-persistent, Multiple simultaneous users
- VNC service on port 5901, persistent (static), one user at a time, password protected
- Near-zero mem/cpu resources after the last user logs out
- Both the persistent and nonpersistent VNC service can be easily enabled/disabled
- Screen resolution adjustable
- On a CentOS minimal install, it requires 77 MB in 30 additional packages (mostly the X libraries, fonts, and the tigervnc-server itself and the majority of packages are dependencies for tigervnc). Not too bad ey?
How does it work? I needed to sort out a lot of nasty details to get it going. First of all, the standard “gdm” X display manager only seems to support Gnome. I tried using Openmotif with gdm but couldn’t get it to work properly. Decided to ditch gdm and go for XDM instead. However, using XDM resulted in pitch black VNC windows that would not respond to anything. Hard troubleshooting teached me the following:
# cat /etc/X11/xdm/xdm-config ... ! SECURITY: do not listen for XDMCP or Chooser requests ! Comment out this line if you want to manage X terminals with xdm DisplayManager.requestPort: 0
The port setting of 0 somehow results in XDM trying to listen on IPv6 (which is not configured on my system). The Xvnc server seems to get an X login on an IPv4 port. Setting it hardcoded to 177 (the standard XDMCP port anyway) did the trick.
Other things that I needed to make it work (all in the RPM package):
- /etc/X11/xdm/Xservers is only used for local attached screens, removing the only entry prevents from X trying to start an X desktop on the system console.
- /etc/X11/xdm/Xaccess: should listen on 0.0.0.0 (forcing it to listen on IPv4 any network) and allow any access.
- /etc/init/prefdm.conf is configured to start on runlevel 5 only, changed to start at levels 3 and 5 so we don’t need to change runlevels. I guess runlevel 5 is only for systems serving desktops on directly attached screens. Using an override file (/etc/init/prefdm.override) to avoid RPM updates to “initscripts” breaking this setting or breaking other packages.
- Added /etc/sysconfig/desktop with an entry to change the default display manager to XDM
- Added a line to /etc/services for port 5901 (5900 already there). Needed for xinetd.
- Added entries to support openmotif in /etc/X11/xdm/Xsession pointing to xclient-mwm that starts an openmotif / mwm session if users login.
- Wrote a script /usr/bin/vncwrapper that is called by xinetd and parses /etc/sysconfig/vncservers configuration before executing Xvnc in turn
- Wrote a script /usr/bin/vnc-setpass that needs to be run (as root) to create a system-wide /etc/vncpass file before connections to the static service can be allowed
- Created /etc/xinetd.d/vnc and ./vnc-static configuration files for xinetd.
- Wrote a SPEC file to build an RPM package (lightvnc-*.rpm) with the above items.
Some CLI stuff and screenshots
# ps aux|grep -iE "xdm|vnc"|grep -v grep root 1509 0.0 0.0 48452 1784 ? Ss 19:47 0:00 /usr/bin/xdm -nodaemon
No services are running except xdm. Memory usage is very low.
# netstat -apt|grep vnc tcp 0 0 *:vnc-server *:* LISTEN 1230/xinetd tcp 0 0 *:vnc-static *:* LISTEN 1230/xinetd
inetd listens on both ports.
For the sake of this blogpost I changed the resolution on the VNC service to 300×200 to allow smaller pictures. The default resolution is 1024×768.
Let’s take a look at the resources consumed by all this eye candy:
nobody 1766 0.1 0.6 87232 11836 ? Ss 20:27 0:00 /usr/bin/Xvnc -inetd -query localhost -SecurityTypes None -desktop centosvm -geometry 400x300 root 1783 0.0 0.1 92452 3248 ? Ss 20:27 0:00 -centosvm:0 bart 1798 0.0 0.0 106060 1340 ? Ss 20:31 0:00 /bin/sh /etc/X11/xdm/xclient-mwm bart 1817 0.0 0.0 57700 740 ? Ss 20:31 0:00 /usr/bin/ssh-agent /etc/X11/xdm/xclient-mwm bart 1820 0.0 0.2 163100 5004 ? S 20:31 0:00 mwm bart 1837 0.4 0.3 160944 7080 ? S 20:36 0:00 xterm
The first 5 processes is what every logged-in user needs. Xterm is something we started as an extra.
Let’s login to the static VNC desktop:
(from another Linux machine)
vncviewer centosvm:1 VNC Viewer Free Edition 4.1.1 for X - built Feb 5 2012 20:01:21 Copyright (C) 2002-2005 RealVNC Ltd. See http://www.realvnc.com for information on VNC. Wed Jul 2 20:44:45 2014 CConn: connected to host centosvm port 5901 CConnection: Server supports RFB protocol version 3.8 CConnection: Using RFB protocol version 3.8 Password: Wed Jul 2 20:44:55 2014 main: No password configured for VNC Auth
No password = no connections allowed. Create a (system-wide) password first!
# vnc-setpass Usage: vnc-setpass Sets the password for static VNC services on port 5901 (vnc :1) # vnc-setpass dirtycache # ls -al /etc/vncpass -r-------- 1 nobody root 8 Jul 2 20:46 /etc/vncpass
Now you can connect to screen 1 as usual. If you disconnect, the session will stay active (no timeout). Re-connect to <host>:1 and you can continue where you left. That’s why there is a system-wide password; otherwise you could login as “foo”, and disconnect, and “bar” could pick up your session without passwords…
You can enable/disable both services with chkconfig:
# chkconfig xinetd based services: ... ... time-dgram: off time-stream: off vnc: on vnc-static: on # chkconfig vnc off # chkconfig ... ... time-dgram: off time-stream: off vnc: off vnc-static: on otherhost $ vncviewer centosvm ... main: unable to connect to host: Connection refused (111)
Note that I logged out from the VNC-static service by ending the MWM session. The VNC desktop shows the login screen again. For the static session, the login screen will wait until a VNC session reconnects:
# ps aux | grep nobody nobody 1996 0.1 0.8 90648 15476 ? Ss 20:44 0:00 /usr/bin/Xvnc -inetd -query localhost -PasswordFile /etc/vncpass -desktop centosvm
You may kill this session without problems. It will restart as soon as you connect on 5901. Note that a “chkconfig vnc-static off” will also result in ending this process (through xinetd).
Want to change resolution or other Xvnc options? Edit /etc/sysconfig/vncservers:
# VNCSERVERS="2:myusername" # VNCSERVERARGS="-geometry 800x600 -nolisten tcp -localhost" VNCSERVERARGS="-geometry 400x300 -nolisten tcp -localhost"
TigerVNC uses this config file anyway (for the standard CentOS method) and I decided to just re-use this file for the same purpose. Here you can see how I changed the geometry for VNC session 0 to create smaller screenshots for the blog. Note that nolisten, tcp, localhost are ignored by lightvnc as they are handled by xinetd. Other options are passed on to Xvnc. If for example you want to change the resolution for vnc-static, make an entry for VNCSERVERARGS.
Running VNC services this way, even with passwords, transfers data over the network UNENCRYPTED! Only use it on trusted networks, or wrap the traffic in some sort of encrypted tunnel. You have been warned.
If you know Linux, VNC and xinetd a bit, you probably will figure out how to have a 1024×768 screen on default port 5900, a 1280×1024 on vnc-static port 5901, and an additional non-persistent service on port 5902 with 1600×1200 resolution. Shouldn’t be that hard anymore.
– Some people seem to end up with a black window (moving X cursor only, no login screen). Seems to be network related – for sure xdm is sensitive for correct DNS forward/reverse solving etc. But haven’t catched the root cause yet. If you have this issue, let me know so we can resolve it.
– Only works on RHEL/CentOS/OEL v6 (version 7 seems to be missing the XDM package).