Turns out I got my Plan 9 installation online and set up with Git (sort of) and the Go programming language sooner than I thought I would. Shortly after that, I fulfilled my promise to run bitly/oauth2_proxy tests on Plan 9. Here are the grotty details for anyone who cares to pursue a similar path.
By the way, I was delighted to find out that VMware Fusion’s clipboard integration with Plan 9 was seamless. Would’ve been painful to recreate these commands by other means.
- Network Configuration
- Patching the SSL/TLS library
- Getting and Installing Go
- Getting Git (sort of)
- Building and Testing bitly/oauth2_proxy
- What’s next?
Network Configuration
The first order of business: getting the network connection up. Here’s what I was confronted with the first time I tried to ping this here site:
term% ip/ping mike-bland.com
ip/ping: couldn't dial icmp!mike-bland.com!1: cs: can't translate address: '/srv/dns' file does not exist
Somehow I figured out that I needed to run the ip/ipconfig
command; I think I
was looking for ifconfig
(per other UNIX-like systems) and came across the man
page for ip/ipconfig
instead. However, even though the interface was clearly
up, and the DNS was configured to use my local router, and I could ping Google’s
DNS server at 8.8.8.8
successfully, name resolution still wasn’t working.
term% cat /net/ndb
ip=127.0.0.1 ipmask=/104 ipgw=::
sys=gnot
term% ip/ipconfig
term% cat /net/ndb
ip=127.0.0.1 ipmask=/104 ipgw=::
sys=gnot
sys=gnot
dns=X.X.X.1
term% ip/ping mike-bland.com
ip/ping: couldn't dial icmp!mike-bland.com!1: cs: can't translate address: '/srv/dns' file does not exist
term% ndb/dns -r
term% ip/ping mike-bland.com
ip/ping: couldn't dial icmp!mike-bland.com!1: cs: temporary problem: dns: dns failure
term% ip/ping 8.8.8.8
sending 32 64 byte messages 1000 ms apart to icmp!8.8.8.8!1
0: rtt 22546 µs, avg rtt 22546 µs, ttl = 43
1: rtt 22226 µs, avg rtt 22386 µs, ttl = 43
2: rtt 22294 µs, avg rtt 22355 µs, ttl = 43
Through some creative web searching I discovered an article holding the key to
Plan 9 name server
configuration
(which also happened to mention the video settings I described in my previous
post). Setting the DNSSERVER
environment variable before launching ndb/dns
-r
did the trick. (By the way, all environment variables are visible within the
/env
directory; Plan 9 takes the “everything is a file” approach to an
extreme.)
term% DNSSERVER=8.8.8.8
term% ip/ipconfig
term% cat /net/ndb
ip=127.0.0.1 ipmask=/104 ipgw=::
sys=gnot
sys=gnot
dns=X.X.X.1
term% ndb/dns -r
term% ip/ping mike-bland.com
sending 32 64 byte messages 1000 ms apart to icmp!mike-bland.com!1
0: rtt 12682 µs, avg rtt 12682 µs, ttl = 52
1: rtt 13069 µs, avg rtt 12875 µs, ttl = 52
2: rtt 12618 µs, avg rtt 12789 µs, ttl = 52
Patching the SSL/TLS library
Since there is no official binary release of Go for Plan 9, I needed to build it
from source. Typically one would run git clone https://github.com/golang/go
or
some such, but as Git isn’t available for Plan 9 (a clever hack described below
notwithstanding), we can instead fetch a tarball of the sources at a tagged
version directly from GitHub using Plan 9’s hget
program (analogous to wget
or curl
on other Unices), in this case Go
1.4.2:
term% hget -o go1.4.2.tar.gz https://github.com/golang/go/archive/go1.4.2.tar.gz
tlsClient: tls: local invalid x509/rsa certificate
[...snip repeated errors...]
hget: too many errors with no progress fd out of range or not open
Whoops; seems hget
doesn’t grok GitHub’s SSL certs out-of-the-box.
Fortunately, I found an os.plan9.general thread pinpointing the problem and its
solution. The problem
is apparently related to Plan 9’s libsec
only understanding SHA1
signatures by default. Fortunately, it’s
relatively easy to patch the Plan 9 source code using an “official” patch, which
the thread helpfully described how to do:
term% 9fs sources
term% PATCH=libsec-x509-sha256rsa
term% mkdir -p $home/patch/$PATCH
term% bind -bc $home/patch/$PATCH /n/sources/patch/$PATCH
term% patch/apply $PATCH
merge...backup...copy...
to update sources:
update /sys/src/libsec/port/x509.c
term% ls -l /sys/src/libsec/port/x509.c
--rw-rw-r-- M 8 sys sys 54397 Jun 8 06:39 /sys/src/libsec/port/x509.c
With the patched file in place, I figured out by reading how to compile a Plan
9 kernel
the proper commands for recompiling libsec
:
term% cd /sys/src/libsec
term% mk -e -n
[...snip...]
ar vu /386/lib/libsec.a ... x509.8 ...
[...snip...]
From there, it was easy to recompile hget
and copy it over:
term% cd /sys/src/cmd
term% mk -e hget
hget.8(0) < /386/include/u.h(1367352099)
hget.8(0) < /sys/include/libc.h(1379544328)
hget.8(0) < /sys/include/bio.h(1367352282)
hget.8(0) < hget.c(1265743728)
8^c -FTVw hget.c
8.hget(0) < hget.8(1433760689)
8^l -o 8.hget hget.8
hget(0) < 8.hget(1433760689)
mv 8.hget hget
term% ls -l hget
--rwxrwxr-x M 8 glenda sys 247569 Jun 8 06:51 hget
term% ls -l /bin/hget
--rwxrwxr-x M 8 sys sys 244009 May 15 2014 /bin/hget
term% cp hget /bin/hget
Getting and Installing Go
With a patched libsec
and recompiled hget
supporting SHA2 signatures, it’s
now a straightforward affair to grab the Go sources from GitHub and build the
code:
term% hget -o go1.4.2.tar.gz https://github.com/golang/go/archive/go1.4.2.tar.gz
term% ls -l
--rw------- M 8 glenda glenda 10971897 Jun 8 06:52 go1.4.2.tar.gz
term% gunzip -c go1.4.2.tar.gz | tar x
term% ls
go-go1.4.2
go1.4.2.tar.gz
pax_global_header
term% ls go-go1.4.2
go-go1.4.2/.gitattributes
go-go1.4.2/.gitignore
go-go1.4.2/.hgignore
go-go1.4.2/.hgtags
go-go1.4.2/AUTHORS
go-go1.4.2/CONTRIBUTORS
go-go1.4.2/LICENSE
go-go1.4.2/PATENTS
go-go1.4.2/README
go-go1.4.2/VERSION
[...snip...]
term% cd go-go1.4.2/src
term% ./all.rc
# Building C bootstrap tool.
cmd/dist
# Building compilers and Go bootstrap tool for host, plan9/386.
lib9
libbio
liblink
cmd/cc
[...snip...]
So the Go compiler and libraries built successfully, and all the tests
passed…except the final multithreaded runtime test, which deadlocked and aborted
after four minutes. Oh well, can’t have everything. I went ahead and set up the
GOPATH
and path
environment variables and verified that the go
tool was
accessible (haven’t figured out what the equivalent to $HOME/.bashrc
is for
the rc shell yet):
term% cd
term% mkdir go
term% GOPATH=$home/go
term% echo $GOPATH
/usr/glenda/go
term% path=($path $GOPATH/bin $home/src/go-go1.4.2/bin)
term% echo $path
. /bin /usr/glenda/go/bin /usr/glenda/src/go-go1.4.2/bin
term% go version
go version go1.4.2 plan9/386
Getting Git (sort of)
There’s one last tool we need before we have a functioning Go environment: Git.
Problem is, there’s no Plan 9 port of Git, and apparently producing one would
take a non-trivial amount of effort. Fortunately, the maintainer of the Plan 9
port of Go hacked together an rc
shell script to approximate the Git commands
necessary to clone the repo and support go get
:
term% hget -o $home/bin/rc/git http://9legacy.org/9legacy/tools/git
term% git clone https://github.com/golang/go ./go
term% ls go
go/.git
go/.gitattributes
go/.gitignore
go/AUTHORS
go/CONTRIBUTING.md
go/CONTRIBUTORS
go/LICENSE
go/PATENTS
go/README.md
[...snip...]
Bear in mind, however, this clone contains the master
branch, not a stable
release, which is what is needed to run the continuous integration servers.
Hence, we built Go earlier using the tarball for version 1.4.2. (Still, later I
may build this version and see if the deadlock in the runtime test goes away.)
With both the git
script and the go
binary in place, now we’re ready to run
go get
to fetch a bunch of helpful tools:
term% go get golang.org/x/tools/cmd/...
# golang.org/x/tools/cmd/stress
go/src/golang.org/x/tools/cmd/stress/stress.go:65: undefined: syscall.SIGABRT
Whoops. Looks like someone didn’t set their build tags properly for Plan
-
At least we can still grab
godoc
:term% go get golang.org/x/tools/cmd/godoc
Building and Testing bitly/oauth2_proxy
Finally, we’re ready for the moment of truth…
term% go get github.com/bitly/oauth2_proxy
term% oauth2_proxy -h
Usage of oauth2_proxy:
-authenticated-emails-file="": authenticate against emails via file (one per line)
[...snip...]
Success! We fetched, built, and successfully executed oauth2_proxy
on Plan 9!
Now, finally, to run the bitly/oauth2_proxy tests on Plan 9 as I’d
promised:
term% cd $GOPATH/src/github.com/bitly/oauth2_proxy
term% go test ./...
# github.com/bitly/oauth2_proxy
cookies_test.go:5:2: cannot find package "github.com/bmizerany/assert" in any of:
/usr/glenda/src/go-go1.4.2/src/github.com/bmizerany/assert (from $GOROOT)
/usr/glenda/go/src/github.com/bmizerany/assert (from $GOPATH)
FAIL github.com/bitly/oauth2_proxy [setup failed]
[...snip...]
Whoops, forgot to run go get -t
to install the test dependencies:
term% go get -t
term% go test ./...
ok github.com/bitly/oauth2_proxy 0.968s
ok github.com/bitly/oauth2_proxy/api 0.722s
ok github.com/bitly/oauth2_proxy/providers 1.220s
Success again! Of course, just to make certain, let’s run the test.sh
script
that comes with the oauth2_proxy
sources (rc
helpfully ignores what it
doesn’t understand and runs the rest in this case):
term% cat test.sh
#!/bin/bash
set -e
go test -timeout 60s ./...
GOMAXPROCS=4 go test -timeout 60s -race ./...
term% rc ./test.sh
set: '/usr/glenda/src/go-go1.4.2/bin/set' does not exist
ok github.com/bitly/oauth2_proxy 0.970s
ok github.com/bitly/oauth2_proxy/api 1.245s
ok github.com/bitly/oauth2_proxy/providers 1.274s
go test: -race is only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64
What’s next?
So I’ve managed to reach my goal of building and executing the oauth2_proxy
tests on Plan 9. What else am I to do with Plan 9 now?
There’s nothing imminently practical for me to do, but I do love noodling about with different operating systems to see what tools are available, what design philosophies shaped the environment, and how easy (or not) they are to use. In the short term, I’m fascinated by the acme terminal/window manager/text editor. It seems a powerful tool that I’ve yet to fully appreciate, and may give me a new way of looking at things.
Funny thing is, I don’t necessarily need to run Plan 9 to try acme
, thanks to
the Plan 9 from User Space project. In
fact, it’s even available via Homebrew for OS X. Fun!