Archives / Search ›

TextDrive moved; OpenVPN script revised

gilford.textdrive.com, the server hosting this weblog, is now in San Diego. I’m looking forward to less downtime now TextDrive has physical access to their servers; I couldn’t really have asked for a much smoother transition.

I revised my OpenVPN DNS script and the associated weblog entry earlier today; it’s now generic and should work unmodified as long as you’ve set up your server to send the right DHCP options. I’ve been getting a steady stream of requests for it, so I hope it helps some people…

Automatically setting $DISPLAY with NX

I do most of my research work on Linux, primarily with lots of X11 Emacs and OS X Terminal windows. I sit at my iBook, which doesn’t stay put network-wise or physically in any given day. Setting up my environment from scratch every time I need to start work in a new location is a huge time sink (in perception if not reality), so I’ve been doing some work to reduce this setup delay.

I can detach from my terminal sessions with screen as I’ve been doing for many years, but X11 is harder. In the past, I either used a local Emacs with TRAMP (for slow setup, slow synchronous file I/O, poor tolerance of network failure, and inability to do things like M-x compile), waited a long time for a remote Emacs to come up over SSH-forwarded X11 (for slow setup), or settled for Emacs running in a Terminal window (making, among other things, copy and pasting between OmniOutliner and Emacs very painful). VNC was out because it took over the entire screen, used lots of CPU, and was too slow over my home Internet connection; besides, I like being able to overlap X11 and Mac windows.

Thankfully, there is finally a good alternative: NX. It’s a primarily-GPL-but-with-commercial-pieces client/server X proxy system which massively speeds up X11, VNC and RDC traffic and reduces latency to the point that remote windowing is usable over a slow connection. As of version 1.5, it also provides detachable multiwindowed (rootless) sessions.

I’ve been using NX full-time for the past month or so, first with 1.4 which gave me “fast, detachable” (and windowed) or “slow, rootless” but not the best of both worlds, and finally this week with 1.5. The initial Mac 1.5 client was a bit broken, but the problems were in the open-source part of it, so Gian Filippo Pinzari from NoMachine was able to provide a patch in a mailing list post. I rebuilt the corresponding components, and everything works now! (Update, August 17: The official client as of version 1.5.0-106 now works without patching.) I even tried detaching my NX session from OS X, resuming on Windows, detaching from there, and resuming on Linux. Did I mention how fast everything is? I can hardly tell the difference between working at home and school now.

There’s also FreeNX, which is comprised primarily of shell scripts wrapping the GPL NX components. I used it before 1.5 came out. FreeNX has some advantages: more configurability, like being able to move my cache directory out of my home directory, since AFS tokens expiring can be a bit of a problem (I work around this with commercial NX using symlinks), and the ability to install as a non-root user. It also has some disadvantages: failures are difficult to troubleshoot, and I can’t get it to work with the NX 1.5 components. Commercial NX is downright cheap for a single user license, and the company is being incredibly generous with their support and code, so I plan to pay for it.

And finally, this brings us to some hopefully-unique information I have to add: a short zsh fragment I wrote so my display gets set automatically based on an already-open NX session. Since I don’t want any fancy desktop environments to start under NX—I already have OS X for that—the session is set to start a small terminal window which immediately goes into the Dock (rxvt -fn fixed -geometry 80x3 -iconic). After that’s set up, I head back to Terminal and ssh into the machine where my NX session runs, and this piece of my ~/.zshrc sets $DISPLAY for me:

  # use NX display if possible
  if [[ -z $DISPLAY ]] {
    nx_cache_dir=(~/.nx/C-$HOST-*(N:t))
    case ${#nx_cache_dir} in
      0) ;;
      1) export DISPLAY=unix:${${(s:-:)nx_cache_dir[1]}[3]}.0
         ;;
      *) echo '*** Potentially stale NX cache directories:'
         for i in ${(f)"$(cd ~/.nx; ls -ldt $nx_cache_dir)"}; do
           echo '***' ${${=i}[-4,-1]}
         done
    esac
  }

Then I start my screen session, and I’m ready to go.

In case you accidentally have some old session caches around, the script warns you it doesn’t know which one to pick; mostly, this was left over from when I was debugging NX problems (rant about GNU ls and cut‘s inflexibility deleted). Of course, you might have some legitimate reason for having multiple simultaneous sessions, too…

In other news, I’m using WordPress 1.5.2 now. The upgrade was pretty simple, though I had to be careful what I was doing (mv -i is your friend). I haven’t tested everything, so let me know if you have any difficulties with this site after the upgrade.

Overriding DNS for domains in OS X Tiger

ACM@UIUC has a bunch of machines behind NAT, which are all in the non-publicly-served domain internal.acm.uiuc.edu, and as I started to need these machines more for my research, I got annoyed at having to do a nested ssh every time I wanted to access them.

The obvious solution was a VPN. I set up OpenVPN on our OpenBSD router box. I’ve done enough OpenVPN evangelism here, so I won’t do more than say it’s worth checking out.

Next came the client side. OpenVPN, at least on Unix platforms, doesn’t automatically modify your nameserver configuration (it used to not modify your routing table either), so I wrote a Python script which automatically edits resolv.conf to add the appropriate nameserver address for internal.acm when you connect, and remove it when you disconnect.

This worked wonderfully until I upgraded to Tiger. OS X 10.4, except for a few tools like host, no longer directly reads /etc/resolv.conf to determine nameservers and search domains. Instead, Tiger has a much more flexible (but rather poorly documented) DNS interface as part of the System Configuration framework. Not to worry, it does keep resolv.conf up to date with the current state of things, but if you change that file, don’t expect Safari, Mail, or even ssh or ping to recognize your changes.

After some poking around and help from a mailing list, I developed a solution. Try running scutil --dns, where you’ll see multiple resolvers, each resolver with its own set of (search) domains and nameservers—it’s like a routing table for DNS. This architecture solves my problem much more elegantly than editing resolv.conf. You can even be connected to multiple VPNs simultaneously, with a private nameserver and associated domains for each VPN, and everything just works™.

I rewrote the script to use this new mechanism, and had been using it a month or so without problems, when I found this article posted at macosxhints.com, which proposes a much more primitive method of altering the nameserver configuration. So I posted a comment saying anyone could email me and I’d send them my script—a sure-fire procrastination tactic, since I was sure nobody would email me immediately, and I planned on cleaning the script up for more general use, just not then because I had several deadlines.

I’ve now had a chance to clean up the script so it is more generically useful. Here is the script with its associated OpenVPN config file.

In order to get the script to work, you’ll need to install PyObjC (has an installer), then the SystemConfiguration wrapper.

If you’re not familiar with using Python’s distutils, to install the wrapper, cd into the SystemConfiguration-0.3 directory, then run python setup.py install. If you get permissions errors (which you shouldn’t on a default OS X install, but…) you might need to sudo python setup.py install instead.

When the VPN is up, OS X Tiger will use the OpenVPN DHCP option-provided nameserver(s) for the corresponding search domains, but will use your existing nameserver(s) for everything else. Use scutil --dns to see one or more resolvers appear after you’re connected, and disappear when you disconnect.

Version 3.0a2 of Tunnelblick, an OS X OpenVPN GUI, now seems to work with this script, as long as you change the cd command in the OpenVPN config file to use an absolute path. It’d be great if it or similar software could adopt this approach automatically, so I didn’t have to write a script at all.

Configuring Trac with FastCGI and lighttpd

I initially tried getting tracd to work, but couldn’t get it to generate URLs that made sense. So, I decided to investigate all the fuss about using lighttpd and FastCGI. It works, better than tracd likely, and is certainly more flexible.

Here’s my lighttpd.conf for dev.sabi.net. It essentially implements the “Global authentication” example from the TracMultipleProjects page on the Trac wiki. You need a trunk version of Trac for this to work; 0.8.x don’t have FastCGI support.

server.port         = 9013
server.document-root= "/home/nriley/web/public/"
server.indexfiles   = ( "index.html" )
server.pid-file     = "/home/nriley/var/run/lighttpd.pid"
server.errorlog     = "/home/nriley/logs/lighttpd.error.log"
accesslog.filename  = "/home/nriley/logs/lighttpd.access.log"
url.access-deny     = ( "~", ".inc" )
compress.cache-dir  = "/home/nriley/var/cache/lighttpd/compress/"
compress.filetype   = ( "text/plain", "text/html" )
fastcgi.server      = ( "/trac" =>
                       ( "trac" =>
                        ( "socket" => "/home/nriley/var/run/trac-fastcgi.sock",
                          "bin-path" => "/home/nriley/cgi-bin/trac.fcgi",
                          "bin-environment" =>
                           ( "TRAC_ENV_PARENT_DIR" => "/home/nriley/trac" )
                        )
                       )
                      )
alias.url           = ( "/media/" => "/home/nriley/share/trac/htdocs/" )
auth.backend        = "htdigest"
auth.backend.htdigest.userfile= "/home/nriley/etc/trac.digest.passwd"
$HTTP["url"] =~ "^/trac/[^/]+/login" {
    auth.require    = ( "/" =>
                       ( "method" => "digest",
                         "realm" => "sabi.net Subversion repository",
                         "require" => "user=nicholas"
                       )
                      )
}

In order for the above FastCGI association to work, I must create a file named trac in the server’s document root, so lighttpd has something to pass along to the FastCGI script. (I got this tidbit from this article on using Django with lighttpd).

I needed to use /media instead of /trac or something like /trac-common or /trac/common because I couldn’t get lighttpd to give up the FastCGI assocation with /trac.

It appears there’s nothing equivalent to “Require valid-user” in lighttpd, and the “require” statement isn’t parsed until a request is received, so you’ll need to add a bunch of users to a group and require a group, likely. The parsing error is very poorly identified, too: (http_auth.c.345) = is missing. I had to dig through the lighttpd source to see what it was referring to.

So, everything seemingly works; the only problem I’m having is my log file getting polluted with these messages:

2005-08-01 03:08:38: (mod_fastcgi.c.2110) FastCGI-stderr:  

which I’ve filed as a bug in Trac.

I also had to do some digging to figure out how to enable anonymous access to Subversion via WebDAV. The Subversion repository’s DAV interface was created as private to begin with, a sensible precaution. However, I couldn’t use <LimitExcept> to apply permissions, so instead I have a AuthzSVNAccessFile svn-access.conf that looks like this:

[dev:/]
nicholas = rw
* = r

Then I open up Apache access with Satisfy Any. Some more discussion of this technique is here.

‹ Newer Posts