OpenCSW is where the goodness is

Executive summary: OpenCSW rocks. (and the like) is the mirror setting you want. (See the README files for more mirrors.)

Solaris 10, as installed from a DVD, has a very small number of software packages. It has packages that are relevant to the OS itself, but it does not have packages with things such as Apache or PostgreSQL vim, or subversion client, or GNU utilities (awk, grep, etc). These ones you need to either compile yourself or use a precompiled binary package. A project called blastwave used to provide those for quite a number of years. However, sometime in August 2008, “things happened”. What those things are, I’ve decided I don’t want to know. The current state of affairs is that there are 2 (two) projects now, one is called “blastwave” and one is “opencsw”. I did a bit of research on the web to find out about their source repositories and binary package statuses.

One thing that struck me pretty strong is that none of those projects advertises its code repository. With open source projects, the code repository is usually the first thing published. “We have a new project! Here’s our code:!” That’s what the phrase “open source” means, according to a common sense understanding. If you’re interested in the project, you can download the source, tinker with it and if you come up with something useful, you offer your change in a form of a patch. Without the source code, you can’t do that. So, where’s the source?

Finding the source code of OpenCSW was a bit harder than the source code of Blastwave. Here it is:

To check out the source (takes a long time to complete):

svn co --ignore-externals opencsw

The code repository, looking at the statistics page, looks pretty active. There’s also a wiki page with instructions.

If you want to update a package or change something in a package from CSW, or you’re wondering how does package building work there, check out this source, then change into a directory with a package, like cups/trunk and type ‘gmake’. It works in a similar fashion to BSD ports.

I didn’t do full exhaustive stats, but it seems that packages in OpenCSW are generally much more recent than the ones from Blastwave. So, check your pkg-get.conf (yes, it’s a newer version of or pkgutil.conf if you use this alternative to pkg-get) and replace the old blastwave mirror with OpenCSW one, and see the goodness flowing in.

(updated on 2009-03-11 according to Phil’s comments)


Accessing ZFS snapshots

Suppose you use ZFS and have pool/foo mounted at /foo.

zfs create -o mountpoint=/foo pool/foo

Suppose you’ve created a snapshot:

zfs snapshot pool/foo@bar

Now they tell you that you can access it inside .zfs/snapshot directory. However, if you go into /foo and type ls -la (option ‘a’ means you want to see files and directories beginning with a dot), you don’t see the .zfs directory. You’ll see ‘.’ and ‘..’ and all others, but not ‘.zfs’. However, an innocent ‘cd .zfs’ or ‘cd /foo/.zfs’ will get you there. A truly hidden directory indeed.

What was it called at esr’s The Art of Unix Programming? The Principle of Least Surprise?

IPv6-enabled OpenCSW mirror

My home network has native IPv6 with radvd running on the router. Any host connected to it automatically gets an IPv6 address. (Unless it’s a Solaris zone, but that’s another story.) For a reason I haven’t worked out yet, all IPv4 traffic on my downlink seems to be throttled to 60kB/s. However, when downloading over IPv6, I’m easily getting 150kB/s or 200kB/s.

When setting up a Solaris 10 system (this time using kvm), I’m getting an IPv6 address straight away:

bash-3.00# ifconfig -a6
lo0: flags=2002000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv6,VIRTUAL> mtu 8252 index 1
inet6 ::1/128
rtls0: flags=2000841<UP,RUNNING,MULTICAST,IPv6> mtu 1500 index 2
inet6 fe80::5053:ff:fe13:9457/10
ether 52:53:0:13:94:57
rtls0:1: flags=2080841<UP,RUNNING,MULTICAST,ADDRCONF,IPv6> mtu 1500 index 2
inet6 2001:770:18d:0:5053:ff:fe13:9457/64

(the ‘rtls0’ interface is a name for a rtl8139 NIC)

I want to use an IPv6-enabled OpenCSW mirror! Such as

You may want that too. Edit /etc/wgetrc (or /opt/csw/etc/wgetrc if you’re using OpenCSW wget) in your Solaris system and add a line:

prefer-family = IPv6


bash-3.00# pkg-get -U
WARNING: gpg not found
Getting catalog...
=> `catalog'
Resolving 2001:770:18:aa40::c101:c140,
Connecting to|2001:770:18:aa40::c101:c140|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 357,696 (349K) [text/plain]

100%[==============>] 357,696      452.07K/s

20:58:53 (451.18 KB/s) - `catalog' saved [357696/357696]

wget will now try to use IPv6 where available. When IPv6-enabled site is not there (no AAAA record, for instance), it will fall back to IPv4.

UPDATE: Putting network interface in a (VirtualBox 1.6.4) virtual machine into promiscuous mode does in fact make the interface accept icmp6 traffic.

UPDATE (2009-03-11): Added information about OpenCSW wget configuration path.

Serial port in VirtualBox

While installing Solaris on VirtualBox on Linux host, I was slightly annoyed by the graphical interface. I had to go out of my screen session, use mouse, click the virtual machine window, let it steal the input and then press right ctrl key to go out, and use mouse again to go back to my screen session.

Solaris x86 supports installation over a serial port. Why not use it?

VirtualBox supports attaching a serial device to a guest machine. By default, serial ports are disabled. If you go to the details tab, and see ‘Serial Ports’, you can click it and get a dialog box. Enable serial port COM1 (IRQ 4 I/O port 0x3F8). There are two port modes. One of them is ‘Host Device’. It would be very nice to use it, but VirtualBox run as a normal user lacks permissions to create devices. The other option is ‘Host Pipe’. Normal user permssions are sufficient to create a pipe, but when you run VirtualBox and examine the file type, you’ll find out that what has been actually created is a unix domain socket rather than a pipe.

How do you access serial port exposed as a socket? Use socat!

I’ve worked out two ways of accessing the serial port: by converting to TCP and by converting to a pty (pseudo teletype device). First, TCP solution. Let’s say, that the path to the socket is “/tmp/foo-socket”. We’ll use socat to convert it to a TCP server.

socat UNIX-CONNECT:/tmp/foo-socket TCP-LISTEN:8040

This command shouldn’t return to prompt. If it does, your serial port device on the guest virtual machine isn’t ready yet. If it doesn’t return, go to a different terminal window and type:

telnet localhost 8040

Voila! Another solution is to create a pty.

socat UNIX-CONNECT:/tmp/foo-socket PTY,link=/tmp/foo-pty

…and on another terminal:

screen /tmp/foo-pty

If socat returns immediately, it means your guest system doesn’t use the serial port at the moment. If you’re installing Solaris 10, you’ll have to select a serial port (ttya) installation mode first, in the bootloader.

FQDN in Solaris 10

The ‘hostname’ command should return an FQDN, that is, fully qualified domain name. For example:

$ hostname

How do you set it up? Google search doesn’t return much of a useful information. And no, putting stuff into /etc/hosts doesn’t solve the issue. The solution is to edit /etc/nodename and put the FQDN in there and reboot.

echo > /etc/nodename
shutdown -g0 -i6 -y

I have a hunch that reboot is unnecessary, but I haven’t figured out which service needs restarting for this change to take effect.

ipv6 in a Solaris zone

This is a continuation of my saga of Solaris zones. In this episode, you’ll be presented with a ipv6 routing problem on Solaris.

Looking for information about ipv6 in Solaris zones, you’ll be likely to get across this page. It will tell you, how to assign an ipv6 address to your zone: get into the global zone and use zonecfg.

netra / $ zonecfg -z wibble
Sorry, I don't know anything about your "screen" terminal.
netra / $ export TERM=vt100
netra / $ zonecfg -z wibble
zonecfg:wibble> add net
zonecfg:wibble:net> set address=2001:0:0:1::4/64
zonecfg:wibble:net> set physical=eri0
zonecfg:wibble:net> end
zonecfg:wibble> verify
zonecfg:wibble> commit
zonecfg:wibble> exit
netra / $ zoneadm -z wibble reboot

After zone reboot:

bash-3.00# ifconfig -a
lo0:1: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1
inet netmask ff000000
eri0:1: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2
inet netmask ffffff00 broadcast
lo0:2: flags=2002000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv6,VIRTUAL> mtu 8252 index 1
inet6 ::1/128
eri0:4: flags=2000841<UP,RUNNING,MULTICAST,IPv6> mtu 1500 index 2
inet6 2001:0:0:1::4/64

Nice, we have an ipv6 address.

bash-3.00# ping
ICMPv6 No Route to Destination from gateway 2001:0:0:1::4
for icmp6 from 2001:0:0:1::4 to 2001:4860:0:1001::68

The address resolves, but there’s no routing. The aforementioned page does actually say something about it:

Starting in the Solaris 10 8/07 release, the /etc/hosts and /etc/inet/ipnodes files are unified and are symbolic links to each other. Routing must be done in the global zone as is discussed in the Trusted Extensions and Zones forums.

The question is, what’s the URL to the relevant thread? I couldn’t find it. Maybe my Google seach-fu isn’t good enough. My friend and me found a way to make this work, although we have no idea whether this solution is correct. All we know is that is somehow… works.

If you look at the ipv6 routing table in the global zone, you’ll see something like this:

Routing Table: IPv6
Destination/Mask            Gateway                   Flags Ref   Use    If
--------------------------- --------------------------- ----- --- ------- -----
2001:0:0:1::/64        U       1       6 eri0:1
fe80::/10                   fe80::203:baff:fe0b:fd4b    U       1       1 eri0
ff00::/8                    fe80::203:baff:fe0b:fd4b    U       1       0 eri0
default                     fe80::213:a9ff:fe80:43be    UG      1       1 eri0
localhost                   localhost                   UH      1       0 lo0

It seems like routing is done via a link-local type address. If you look at the correspoding table in your non-global zone, you’ll see:

Routing Table: IPv6
Destination/Mask            Gateway                   Flags Ref   Use    If
--------------------------- --------------------------- ----- --- ------- -----
2001:0:0:1::/64             2001:0:0:1::4               U       1       0 eri0:4
ff00::/8                    2001:0:0:1::4               U       1       0 eri0:4
localhost                   localhost                   UH      1       0 lo0:2

Apparently, there is no link-local address here. Normally, link-local addresses are derived from the MAC addresses of network cards. Here, we have just one network card, and one MAC address – hence one link-local address, and it’s already assigned to the global zone. We need one more link-local address here… why not make one up?

netra / $ ifconfig -a | ggrep -B1 fe80
eri0: flags=2000841<UP,RUNNING,MULTICAST,IPv6> mtu 1500 index 2
inet6 fe80::203:baff:fe0b:fd4b/10

We’ll just pick the next address.

netra / $ zonecfg -z wibble
zonecfg:wibble> add net
zonecfg:wibble:net> set address=fe80::213:a9ff:fe80:43c0/10
zonecfg:wibble:net> set physical=eri0
zonecfg:wibble:net> end
zonecfg:wibble> verify
zonecfg:wibble> commit
zonecfg:wibble> exit
netra / $ zoneadm -z wibble reboot

After logging (using ‘zlogin wibble’) to the zone:

netra / $ zlogin wibble
[Connected to zone 'wibble' pts/3]
Last login: Sat Aug 30 11:57:01 on pts/3
Sun Microsystems Inc.   SunOS 5.10      Generic January 2005
# bash -l
bash-3.00# ifconfig -a | /opt/csw/bin/ggrep -B1 fe80 # GNU grep FTW!
eri0:5: flags=2000841<UP,RUNNING,MULTICAST,IPv6> mtu 1500 index 2
inet6 fe80::213:a9ff:fe80:43c0/10

We’ve got our address! It’s completely arbitrary and probably makes no sense. But the probability of collision is low and…

bash-3.00# ping is alive

…it works!

UPDATE 2008-09-05: Another way of doing it is creating an IPv6 route on the global zone, using a global IPv6 address (as opposed to link-local).

sshd doesn’t start in Solaris zone

This describes a quite silly problem I once had. Google had no useful search results, so I’m putting the solution here for the sake of all the lost souls not knowing why their pet sshd doesn’t want to run in a Solaris zone. Yes, you can solve it using truss and analyzing SMF startup methods. But I think there are better ways to spend your time.

The solution was found by me and my friend one warm Polish summer night. Here we go, then!

Solaris zone tutorials will tell you something along the lines of:

netra / $ zonecfg -z wibble
Sorry, I don't know anything about your "screen" terminal.
netra / $ export TERM=vt100
netra / $ zonecfg -z wibble
wibble: No such zone configured
Use 'create' to begin configuring a new zone.
zonecfg:wibble> create
zonecfg:wibble> set autoboot=true
zonecfg:wibble> add net
zonecfg:wibble:net> set address=
zonecfg:wibble:net> set physical=eri0
zonecfg:wibble:net> end
zonecfg:wibble> set zonepath=/zones/wibble
zonecfg:wibble> verify
zonecfg:wibble> commit
zonecfg:wibble> exit
netra / $ zoneadm -z wibble install
Preparing to install zone <wibble>.
Creating list of files to copy from the global zone.
Copying <8442> files to the zone.
Initializing zone product registry.
Determining zone package initialization order.
Preparing to initialize <239> packages on the zone.
Initialized <239> packages on zone.
Zone <wibble> is initialized.
The file </zones/wibble/root/var/sadm/system/logs/install_log> contains a log of the zone installation.
netra / $ zoneadm -z wibble boot

At this point, I was pretty convinced I would already be able to log into the zone via ssh and IP address But there was nothing listening on port 22 in the zone. I logged into it to find the problem.

netra / $ zlogin wibble
[Connected to zone 'wibble' pts/2]
Sun Microsystems Inc.   SunOS 5.10      Generic January 2005
# ▊

I spent a bit of time there, looking for reasons. Ssh service was offline.

bash-3.00# svcs -a | grep ssh
offline         1:48:51 svc:/network/ssh:default

Using svcs -x -v, I’ve found out that sshd was not running because of network/rpc/gss, which depends on network/inetd, which depends on system/sysidtool. And sysidtool is ‘starting’.

It turns out, after booting a zone, you need to zlogin to its console, that is you have to use ‘zlogin -C wibble’ command. You’ll then be presented with a text installer interface.

This means, that even though ‘zoneadm -z wibble install’ completes, your zone isn’t quite as installed as you would wish. It still doesn’t know its locale, terminal settings, it doesn’t have ssh public/private key pairs, hostname, DNS server (name service configuration), NFSv4 domain configuration, time zone and root password.

zlogin -C zonename

…is your friend!