This site is now 100% read-only, and retired.

running a desktop with vnc over openvpn

Posted by pj on Wed 9 Jan 2013 at 21:50

I'm going to describe how you can display and control your primary desktop remotely from a secondary so that it everything works really well. To do that, we are going to bolt together several commonly used linux components. Along the way I'll pass on some personal drivel about my own experience in doing this. The idea behind this being that you get a feel of how things hang together.

Now, I said display and control your primary desktop remotely from a secondary. By primary desktop, I want you to think of, for example, your desktop at work. Normally, you run a GUI under X on it, so that it shows applications like x-terminals, menus, screensavers, wallpapers, and so on. You've usually set these up just the way you like it on your primary desktop, so that you can work super efficiently. Every other desktop you configure elsewhere is normally a way to approximate the same stuff that you do on the primary.

By display and control your primary desktop remotely I mean something like this example: One day, you want to work from home, from your home machine, in your bunny slippers. The display and control bit means that you can not only see stuff that is on display on the work machine, but also control stuff on that work machine like you would if you were actually at the desktop at work. So, ideally you want to be able to do it from the home desktop so that it feels just like you are at the work desktop.

Note that I don't mean replicating the desktop. Replicating would mean something like copying the underlying disk drive from the work machine to the machine at home and constantly keeping stuff in sync. That requires too much thinking and maintenance. The display and control bit actually says it quite precisely. What I mean is viewing what is at work (display multiplexing), but being able to work on the desktop running at work too (remote control), all without replication of the underlying filesystem data from the remote to the local.

The tools I use for this are:

  • xrandr: deals with a dual monitor set up. Xinerama is sometimes needed instead.
  • vnc: does the multiplexing display serving thing (serve the display from the work machine to the home machine).
  • xtightvncviewer: does the multiplexing display viewing (and keystrokes/mouse input) thing (lets you view/control the remote machine on the local machine)
  • openvpn:- used to connect securely from point to point as if the home and work machine are on the same LAN.

Getting Xrandr (and its ancestor, xinerama) to do X with Dual Monitors

What is xrandr?

xrandr: X Resize, Rotate and Reflect Extension (RandR). Version 1.3+ (released in 2009) works with dual head setups that use one big virtual screen across both heads.

Actually it works with more than just dual heads, but I just work with dual heads, so that's what I'll consider.

What's my hardware then?

At work the machine I have is a reasonably powerful dual core box, with a single video card ("lspci | grep VGA" shows the chipset as ATI Technologies Inc RS880 [Radeon HD 4200]). With this card is one output for DVI and one for VGA. One output is plugged into one 22" Samsung monitor each, giving me a dual head. Having two outputs from a single video card like this is quite common for current (2012) video cards. The VGA analogue output is not distinguishable in quality from the DVI output on the hardware I use, at least for these 22" monitors running at a resolution of 1920x1200.

Back at home, my desktop set up is rather more humble. Actually, forget humble, it's downright obsolete --- the home box is a P-4 single core machine, with a single built-in VGA out, to which an oldish 1280x1024 LCD monitor is plugged in. To this I added some additional junk --- and I mean junk quite literally. As in, I added a ridiculously old 8MB PCI voodoo 3dfx card from internet prehistory, together with an equally ancient 19" Ilyama CRT monitor. Both of these were junked freebies. However, in the end, I had a home box with a gigantic CRT monitor stood beside an oldish LCD monitor that the box was already using.

Aha!, you may exclaim, the power consumption of the CRT will eat up any savings from the freebieness! Aha yourself! --- I use the CRT about once a week. So it works out to about 6 years before I spend in power the amount I would on a new LCD monitor the same size, without the power consumption. With energy saving modes enabled on the CRT it'd be a few years more. So I'm okay there on green credentials. Not so okay on the exasperation-from-the-significant-other front, but like she says, I'm thick-skinned. Plus I quite like the display on the Ilyama, since it was a fantastically overengineered monitor in its heyday.

BIOS tweaks for PCI video cards

So, there I am with two monitors and two video cards. The kernel detects both cards just fine, and Debian's xserver-xorg installs a suite of drivers for X11 for the xserver. The PCI card needs to made to boot first in the BIOS, or it refuses to do X. It seems to be a common quirk for those kind of vintage machines. The voodoo and built-in video are detected just fine after the BIOS tweak.

From the gentoo wiki, the BIOS options can be tweaked like this:

  • In AWARD BIOS (v4.51PG), menu: Integrated Peripherals -> Init Display First -> [PCI Slot / AGP]
  • In AMIBIOS (v 08.00.08), menu: PCIPnP -> PCI Bus Scan Order -> [Ascent/Descent]
  • In other BIOSs it's called: Bios First Boot -> [AGP/PCI]

Getting X on the cards


LCD Monitors can run at lots of resolutions, but the optimal ones are the ones matching the hardware pixel layout (resolution figures like 1920x1200, or 1280x1024). CRT monitors that are 17" or greater can generally handle 1280x1024, while the Ilyama 19" beast I have can cope with 1600x1200, for example. A resolution of 1280x1024 with a depth of 24 is fine for work, and is something even the Voodoo card copes with.

Monitor Juggling

  • To run a single monitor on the built-in AGP card, I make sure the video card is enabled in the BIOS, and everything runs as usual, without having to configure X for it. You can generate an xorg.conf (xserver configuration) file for it, by running Xorg -configure, and copying the resulting file over to /etc/X11/xorg.conf if you like, but in most cases it isn't needed. Indeed, by default, a recent distribution (squeeze onwards, I think) with a modern X doesn't even bother with an xorg.conf.
  • Or instead of the AGP card, I can enable PCI video in the BIOS, so that the voodoo card runs instead. Again, the xorg.conf file isn't needed here either, but can be generated the same way.
  • To run both cards, ie to run it as a so-called dual head, I have to enable the PCI video card (voodoo) setting. The xorg.conf for a dual head can be generated either as before, or it can be built up a bit more manually by using the two preceding xorg.conf files as a guide to making one big xorg.conf file to cover both cards. You'll have to use some judgement, but the man page for xorg.conf can be used for some guidance. The result, if you set things up right, is that when the machine boots, the monitor connected to the PCI card starts up first, the machine marches its way towards X, and then the xserver goes through the configuration file and eventually both monitors end up displaying something. Exactly what that "something" is depends on the way X is running.

Running X

  • The xrandr way

    The recommended way of doing multihead is xrandr, especially if you have a single card with dual (or more) outputs. Only if you have multiple cards, and you can't get them all running with xrandr, should you go the older xinerama way, as described later.

    By default, on a single card with multiple outputs, x shows up on all displays the same way (a clone view). Thus, the display manager login (xdm/kdm/gdm, whatever) will show up on all the screens. Only when xrandr kicks in will the screens display separately, as in, you typically have one monitor showing the left hand side, and the other monitor showing the right hand side, of a large "logical" screen.

    Getting xrandr to run is easy. First run a query with:

      xrandr -q

    See what outputs there are, then build a command that you can run from X as a regular user. For example, you might build scripts like the following:

          peej@rotwang:~$ cat singlescreen 
          xrandr -s 1280x1024
          peej@rotwang:~$ cat dualscreen
          xrandr --output DVI-0 --primary --mode 1280x1024 --left-of VGA-0 --output VGA-0 --mode 1280x1024

    You can add the xrandr command to the xsession start up script (.xsessionrc) so that it launches after the display manager login has been carried out.

  • The xinerama way

    The older way of doing multihead is with xinerama. There, when xdm/kdm/gdm starts up you get one screen showing an xdm/kdm/gdm display manager. I found specifying depth and maybe busID was needed, eg, in /etc/X11/xdm/Xservers:

      :0 local /usr/bin/X :0 vt7 -depth 24 -nolisten tcp -isolateDevice PCI:0:9:0

    About busIDs: AGP busIDs also use that kind of format (eg: PCI:1:0:0), but start with PCI:1 instead.

    The addendum to this article shows a sample xorg.conf file that works for me across two cards and two monitors with xinerama.

  • The multiple xserver sessions way?

    A probable third way to do multihead, but which I haven't yet been able to beat into submission on my rig, is to run an xserver for each video card. The bit I haven't figured out is how to make both displays show at the same time. If I switch to one with a ctrl alt f8, the other goes dark. You'll have to live with the displays being pretty independent too---that is, not being 1 big logical display like you get with xinerama and xrandr.

    To run a different xserver for both, if you are using xdm as your display manager, have a look at the /etc/X11/xdm/Xservers file. It has examples on how to do that near the end. I found that setting -depth explicitly as an option to the xservers there let my display show up properly for some reason as standard multiple x-servers per card, as well as with xinerama over cards.

    A way with multiple xserver sessions I've used in the past has been to use a desktop machine with a single display locally and a laptop with a single display locally, to show one screen each of the remote. Not the most efficient way to do stuff, but it works. Of course, most laptops typically have a resolution of 1280x800 so it isn't going to be seamless across monitors unless you're using that per monitor remotely too (which would be pretty unusual). Also, most laptops have an external display port too, so you should be able to do the xrandr or xinerama way anyway.


VNC is awesome! I'll only be going through a part of its capabilities though, because if I go on about it in depth, you will be blinded by its extreme awesomeness. And then you won't be able to read this article properly.

What is VNC?

VNC was covered earlier on this website. Basically, if you have been living under a rock for the last 15 years, VNC can display the GUI on the remote (work desktop) to your local (home) display. Not only that, but mouse and keyboard stuff you do locally (at home) gets converted to remote equivalents at the work machine. The result is that it's like you are at the work desktop, except from home. Which is obviously getting us on the right track if we want to work from home.

Set this VNC visual display up right, and you don't have to replicate the file structure on your work machine that makes the remote desktop. This is because, well, you have the remote desktop display itself on display in front of you. So, that means, no copying of .bashrc, /home/, your customized menu, whatever. Your work desktop is just there, in front of your naked, steaming eyes! And "there" then becomes wherever you can get a connection to the work box. If you follow the current IT fashion for cloud-speak, then your workbox is your truly personal cloud!

Most VNC implementations run as a client/server setup. That is, a VNC server runs on the remote, and you use a VNC client for viewing locally. The VNC protocol has a common core standard, so that you can mix different clients and servers. The x11vnc server is designed to send the X11 display to clients, while vino/vinagre is good for gnome. I find x11vnc server works well for me with the xtightvncviewer client. The "tight" in xtightvncviewer refers to clever compression extensions to the original VNC protocol. These extensions make the exchange between client and server take fewer round trips and generally make things snappier. All modern VNC implementations have something similar --- everyone likes responsiveness after all!

The snappiness caused by the compression extensions is remarkable. Trying the same trick of viewing a desktop with standard ssh -X (as described in in, or is painfully, teeth-clenchingly, laggy --- at least over a connection to anywhere beyond a local LAN. Using a compressed VNC client makes the connection miraculously unlaggy.

Installing VNC

The VNC server

Installing the VNC server is easy:

work:~# apt-get x11vnc

Then, store a password with (as an ordinary user):

peej@work:~$ x11vnc -storepasswd secret12345

Using a password is a fairly weak precaution (let alone the pathetic password used here), considering there is no encryption during a default VNC connection. You can crank up the connection security to any level you like, including using ssl, piggybacking over ssh, or only allowing access from particular IP addresses. Read the man page if you want to know more on this, but I found my eyes glazing over when I tried reading it. So I used openvpn instead. I'm going to discuss using openvpn later on.

Having got the VNC server ready, we can start it up, as an ordinary user, with:

peej@work:~$ x11vnc -display :0 -usepw -forever

Tip: If you like screen or tmux, you may want to start it up under that at boot from, say cron:

@reboot /usr/bin/screen -d -m -S "x11vncserver-d" /usr/bin/x11vnc -display :0 -usepw -forever

The VNC client

Once the server is running, you can run the client from the home machine. I've set up a mindless shortcut that does something like this:

pkill xtightvncviewer;  echo "secret12345" | xtightvncviewer -autopass -fullscreen
  • VNC client gotchas: encryption

    One gotcha about VNC is that the default connection configuration is typically done without encryption, even though the option is available. You could say that this is simply the old unix philosophy of having one standard tool doing one special thing incredibly well, and leaving other functionality to other standard tools. So, while the pretty standard tool VNC has as its special thing the snappy replication of a display really well, we can use the functionality of another pretty standard tool for a secure connection, that tool being openvpn. Like I've said, I'll cover using OpenVPN with VNC later.

    Anyway, an important point is to be aware of the lack of default encryption, so that you do not use an unencrypted VNC over untrusted networks.

  • VNC client gotchas: escaping keystrokes

    After you run xtightvncviewer, you get a screen replicating the remote. If you've used the -fullscreen option, and your X resolution locally matches the remote, and you have the same number of monitors in both places, then you should find you have a snappy replica of the remote, that lets you interact with it like you're sitting at the remote. To break out of it, the default key is the f8 key.

    Now, I use a lot of special keystrokes---the window manager I use icewm is pretty inspiring that way. So, like a maniacal Emacs user I go about sprinkling ctrl-escs liberally, with nary a thought. Not having to think about the fact I'm doing all this remotely makes me pretty productive. The trouble is that the default xtightVNCviewer implementation hiccups over these keystrokes, and then I suddenly find I can no longer type on the remote. Which is obviously a setback to my productivity. To pass through these kind of keystrokes, you have to change a configuration in the default vncviewer settings file: /etc/X11/app-defaults/Vncviewer. In this file, you uncomment the line:


    After that, the only special key that will work is the F8 key. If by chance you need that key for something else, or maybe you've drooled over your f8 key and it doesn't work any more, then you can modify the choice of key in the settings file too.


Like I said earlier in the VNC section, we need to do VNC in a secure way. One way that works for me is to tunnel between the client and server within OpenVPN on the big bad internet.

I covered tunneling securely over OpenVPN in in detail earlier. If you aren't familiar with OpenVPN, you should find that a pretty good guide.

The way I run OpenVPN between two points is something like:

  • On the remote primary you can run:
       # openvpn --script-security 2 --proto tcp-client --remote \
       --tls-client --remote-cert-tls server --ca ca.crt --cert pjworkbox_vpn.crt \
       --key pjworkbox_vpn.key --dev tun1 --ifconfig \
       --verb 4 --port 80 --user nobody --group nogroup --persist-tun --persist-key

The client script repeats indefinitely every 5 seconds or so if it gets no connection, so it is a bit like a service anyway. The IP address specified in it is the internet address of the local machine at home. You can maybe use a dyndns service for that, for convenience. Also, like the x11vnc service, you can run it in a screen session at boot.

  • On the local machine at home, you can run:
      # openvpn --script-security 2 --proto tcp-server --tls-server --ca ca.crt \
      --dh dh2048.pem --cert serverbox_vpn.crt --key serverbox_vpn.key --dev \
      tun1 --ifconfig --verb 4 --port 80 --user nobody \
      --group nogroup --persist-tun --persist-key

I use port 80 for my tunnel to's the least likely outgoing port to be blocked by a firewall at work. As far as VNC is concerned, it will look like a private LAN connection from to

Once the tunnel is connected up from both ends, I just run that vncviewer script from earlier:

      pkill xtightvncviewer
      echo "secret12345" | xtightvncviewer -autopass -fullscreen

If all goes well, my snappy remote X session starts, and no one can snoop on the contents.

The alternatives

This way of working remotely can be done in many other ways, including:

  • nxserver/nxclient: An optimized non-free way of connecting xclients with their display servers, using the compressed NX protocol. This is one I've tried out before, and it is probably the speediest of the lot, though I've never bothered benchmarking it.
  • vino/vinagre: Another VNC client/server combination. I don't know how neatly this works. It's probably quite slick.
  • teamviewer Very user-friendly. Uses a wine layer. Works and installs well, especially for Aunt Tilly ( Free for use for private individuals, but larger organizations have to pay. Uses a MITM server, so a cryptanalyst can't trust its security from that point of view.
  • xrdp/rdesktop: RDP is the Remote Desktop Protocol from Microsoft, for doing things in a compressed VNC-like way. I don't know anything about RDP clients and servers. I'm just adding it here so that you know that they exist in Linux too, just in case the boss forces you to use RDP.
  • x11vnc -ssl/ssvnc: I said earlier in this article that the details on securing x11vnc with the built-in options made my eyes glaze over. Inspired by a comment, I've added a note in the comment section on how to get started with that.
  • xpra: (Gotta love the comments section for reminding me of this) xpra is like screen for X, which sounds totally cool. I haven't tried it yet myself but there is a debian package for it so it won't be long before I do.

My preference for the xv11vnc/xtightvncviewer way over openVPN was based on the parts being free (as in freedom and open standards), without MITM worries, familiarity, and fast enough on the cheapest broadband connection I could get. Addendum: sample xorg.conf file that handles xinerama over two video cards:

Section "ServerLayout"
        Identifier     " Configured"
        Screen      0  "Screen0" 0 0
        Screen      1  "Screen1" RightOf "Screen0"
        InputDevice    "Mouse0" "CorePointer"
        InputDevice    "Keyboard0" "CoreKeyboard"
Section "ServerFlags"
        Option  "Xinerama"      "True"
Section "Files"
        ModulePath   "/usr/lib/xorg/modules"
        FontPath     "/usr/share/fonts/X11/misc"
        FontPath     "/usr/share/fonts/X11/cyrillic"
        FontPath     "/usr/share/fonts/X11/100dpi/:unscaled"
        FontPath     "/usr/share/fonts/X11/75dpi/:unscaled"
        FontPath     "/usr/share/fonts/X11/Type1"
        FontPath     "/usr/share/fonts/X11/100dpi"
        FontPath     "/usr/share/fonts/X11/75dpi"
        FontPath     "/var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType"
        FontPath     "built-ins"
Section "Module"
        Load  "extmod"
        Load  "dri2"
        Load  "dbe"
        Load  "glx"
        Load  "dri"
        Load  "record"
Section "InputDevice"
        Identifier  "Keyboard0"
        Driver      "kbd"
Section "InputDevice"
        Identifier  "Mouse0"
        Driver      "mouse"
        Option      "Protocol" "auto"
        Option      "Device" "/dev/input/mice"
        Option      "ZAxisMapping" "4 5 6 7"
Section "Monitor"
        Identifier   "Monitor0"
        VendorName   "Monitor Vendor"
        ModelName    "Monitor Model"
Section "Monitor"
        Identifier   "Monitor1"
        VendorName   "Monitor Vendor"
        ModelName    "Monitor Model"
Section "Device"
        Identifier  "Card0"
        Driver      "tdfx"
        BusID       "PCI:0:9:0"
Section "Device"
        Identifier  "Card1"
        Driver      "nouveau"
        BusID       "PCI:1:0:0"
Section "Screen"
        Identifier "Screen0"
        Device     "Card0"
        Monitor    "Monitor0"
        SubSection "Display"
                Viewport   0 0
                Depth     24
Section "Screen"
        Identifier "Screen1"
        Device     "Card1"
        Monitor    "Monitor1"
        SubSection "Display"
                Viewport   0 0
                Depth     24



Re: running a desktop with vnc over openvpn
Posted by mcortese (85.158.xx.xx) on Fri 11 Jan 2013 at 13:34
[ View Weblogs ]
Just for confirmation: the reason why you dismissed the standard X11 remote protocol (possibly over SSH), to the extent that you didn't even list it in the alternatives section, is because you found it laggy beyond any useful limit, correct?

[ Parent ]

Re: running a desktop with vnc over openvpn
Posted by Anonymous (87.213.xx.xx) on Fri 11 Jan 2013 at 15:51
Correct. You can do the whole remote desktop experience over ssh -X, but beyond a LAN you would have to be desperate to do it because of x protocol roundtrips. Those roundtrips are what nx gets rid of, so you have something snappy again.

[ Parent ]

Re: running a desktop with vnc over openvpn
Posted by josefwells (67.52.xx.xx) on Fri 11 Jan 2013 at 17:06
You can skip both the openvpn step and setting up a x11vnc -forever server if you use ssvnc.

ssvnc does vnc (optionally over an ssh tunnel with/without ssl) and can connect to a running x11vnc/vncserver, or run a x11vnc/vncserver on the target.

It also allows proxying through another (multiple) ssh host(s).

[ Parent ]

Re: running a desktop with vnc over openvpn
Posted by pj (62.234.xx.xx) on Sun 13 Jan 2013 at 16:18
ssvnc: yup, this sounds ideal. Only, like for vnc itself, I couldn't figure it out quickly for myself what was connected how to what when you wanted security. I'll give it a try if someone can point me to a tutorial for ssvnc dummies. It's probably really easy --- it's got a helpful gui after all!

[ Parent ]

Re: running a desktop with vnc over openvpn
Posted by pj (62.234.xx.xx) on Wed 16 Jan 2013 at 06:48
I had another look at ssvnc use. Short summary (after you have done the x11vnc -storepasswd thing):

* vnc server: x11vnc -ssl SAVE-$(hostname) -display :0 -rfbauth ~/.vnc/passwd -bg
* vnc client: ssvnc IP.Address.of.vncserver:0

The GUI-goodness is handy. I'll make a mention of this in the article.

[ Parent ]

Re: running a desktop with vnc over openvpn
Posted by Anonymous (5.254.xx.xx) on Sat 12 Jan 2013 at 04:03
I use xpra, it is fast, secure and so stable. I am really pleased. I have tried vnc, rdp and what not, but didn't find it very attractive ...


[ Parent ]