Debian on the AppleTV

It's hardly a first, but I did find some of the information out there a bit spread out. So, just incase I need to go through this again, I figured a 'blog post might be interesting - doubly so as I've not really got anything interesting from work, that I can blog about at the moment!

So, a bit of background. The AppleTV (ATV) is basically a dumb x86 PC - Pentium M 1GHz, 256MB of RAM, 40 or 160GB PATA HDD, 1x USB 2, 1x IR receiver, 10/100Mb ethernet, 801.11n Broadcom WiFi and a Nvidia Geforce GO 7300 - all which uses about 17W of power in a fairly compact and quiet, form factor. What I hadn't banked on was the very retarded power supply. I knew that the ATV wasn't able to power off, but I assumed that was a software thing. Oh no. The actual power supply has no concept of switching. It's either on or off. Which is slightly annoying.

The whole "hacking" process is largely taken care of - a bunch of enterprising invididuals have got it running, over the course of several iterations. The most recent is the efforts from the ATV-Bootloader team, who have basically built a small recovery image, which translates some of the EFI structures into BIOS compatible (allowing unpatched kernels to run) and has a very cut down Linux installation which then chainloads (using kexec) another Linux kernel. The really awesome thing is that these guys have made some nice tools to stream line the efforts if you want the ATV OS and Linux to co-habit. I didn't want this particularly.

So first thing first was the old hard disk was removed and a new one was prepared under my desktop install of Linux, via a USB to IDE converter, using the instructions on the ATV-Bootloader project wiki. Pay close attention to the requirements for a patched parted.

Next I used debootstrap to install a basic Debian (squeeze) system into /dev/sda4 (ATV-Bootloader sees all drives as /dev/sd*, where as when you boot into a kexec'ed kernel they will be seen as /dev/hd* - this confused me for a few minutes - not something you want when you're scrabbling around at stupid o'clock in the morning). At this point I then chroot'ed into it and used apt to install a kernel, but no bootloader. Since the ATV-Bootloader uses kexec all you need to do is have a valid one of the following: mb_boot_tv.conf, menu.lst (grub), syslinux.cfg (ISOLinux), or kboot.conf. Having played with grub files quite a lot I thought that I knew the syntax well, but do you think I could get it to work with a grub file? No. I ended up whimping out and using a mb_boot_tv.conf (popped it into the root of the Linux partition) which is a lot simplier[1] and is infact the first file searched for (so its slightly faster to boot). If you don't fancy that then check out boot_linux.sh from the ATV-Bootloader trunk to see all the options and example configs (in-line comments). The only other things you need to remember are the usual when debootstrapping - create a valid /etc/network/interafces (man 5 interfaces, if you're unsure), make sure udev numbers your network cards correctly (/etc/udev/rules.d/70-persistent-net.rules), and of course your root password. Exit, reboot and hey presto, you should be into a very basic Debian install.

My next annoyance was the flashing LED. By default it flashes orange to tell you that its booting, and then the ATV OS would reset it to a white light. Thankfully a great chap by the name of Peter Korsgaard has written a tool (available from git and here - note needs to be compiled) called atvtool to control the LED and the fan. It's a little basic and doesn't play well with lircd at the moment (you can set atvtool to release the controller back, at which point lircd needs to be restarted), although I'm hoping to have a poke and understand why and hopefully fix this.

WiFi is also fairly important to me since I'm going to use the ATV to replace my WRT54G bridging 2 networks here. Sadly the only real options seem to be using ndiswrapper or the Broadcom-STA drivers. I opted for the Broadcom-STA and things are going well, with no issues at present - the only special thing I did, for my own brain, was to rename the adapter to wlan0 (again, udev persistent-net.rules).

From here on out, if you're running headless, everything should be working like a dream. At this point I elected to install the nvidia kernel module only to see if I could get anything useful from lm-sensors, but there wasn't much luck on that front. if you're planning on using the ATV as a media center or with a monitor/TV, then you'll definitely need it.

What does this leave you with? A low power, almost silent, fairly capable machine to run part of your network. The only sad thing, in my eyes, is the limitation of a single USB port. From here you could run forked-daapd to share your music, any of the several network file systems, DHCP, DNS, you name it. Just watch the memory usage - don't forget that there's only 256MB of RAM to play with.

[1] Vaguely what my mb_boot_tv.conf looks like - note the /dev/hda4 instead of /dev/sda4. #try-net-boot kernel /vmlinuz append ro root=/dev/hda4 initrd /initrd.gz

LXC: IPv6? Yes!

Following up to yesterday's post on LXC: Linux Containers, I had a quick play with 2 ULA subnets (aka RFC4193 addresses - dont forget that site-local was depreciated) - one subnet was dedicated to the LXC containers, one for my normal LAN. Perhaps unsurprisingly IPv6 appears to work perfectly well in this setup.

I also altered the setup and bridged a container directly to eth0 on the host node, and watched the container assign itself a stateless address based on my prefix, and again everything appeared to work perfectly well out onto the public v6 network (courtesy of Hurricane Electric's Tunnel Broker service).

So all in all I'd say that LXC is looking pretty good so far. There are a few other things I'd like to test, like how effective iptables are in the context of containers, and whether or not it is secure enough. Unfortunately I'm not going to have time to play with these things this weekend really. Answers on a postcard to the usual address if you already know though!

LXC: Linux Containers

I've been toying with migrating my server into a containerized system, and almost bought a new server in preparation to migrate everything across. I'd chosen and tested my solution, OpenVz. All was good with the world. Until I saw that OpenVz was effectively being dropped from Ubuntu 10.04 (Lucid Lynx) and most likely Debian 6.0 (Squeeze).

The reason for the drop is simply because the OpenVz patches haven't been forward ported into the current kernel. Now thats obviously a bit of a problem, since I prefer Debian no straight dist-upgrade from Lenny to Squeeze would be slightly annoying. To put it mildly.

It turns out that a few people that realised this is going to be equally annoying, should such a thing occur, and they've been working LXC: Linux Containers and got the implementation into the main kernel tree. However there are a few issues with LXC;

  • Documentation: It's thin on the ground, but if you're capable there is enough to get you going, and if absolutely necessary you can dive into the source (although I will admit it can does take a bit of time if you're not familiar with the basics of linux kernel development [like me]).
  • It's not as mature as OpenVz (userspace tools, for instance can do odd things, and there are data leaks [for instance in Squeeze at the moment you can see the host mounts via /proc/mounts] although many seem to be resolved in git).

The OpenVz team seem to be updating the OpenVz patches for a more recent kernel, however the decision by a few distros to migrate to LXC might provoke the same sort of effect that migrating to KVM had on Xen's popularity.

Anyway, here's my quick start guide:

  1. You need a relatively recent kernel with control groups (cgroups) and capabilities support. If you're not planning on rolling your own kernel the current kernel in Squeeze or Lucid should be fine.
  2. Use the package manager of your choice to install lxc, bridgeutils and debootstrap. That should pull in everything you need for a basic install (if you want to run Debian based container).
  3. Run lxc-checkconfig and you should see everything is enabled and ready to go, with exception of cgroup memory controller, which LXC doesnt appear to require.
  4. So now we need the control groups pseudo-file system setup mkdir /cgroups and mounted (add the following to /etc/fstab cgroup /cgroups cgroup defaults 0 0 and run mount).
  5. Next choose how you're going to network your containers. In both these examples br0 is the device that the containers will be attached to. Aside from these 2 options there are other ways you could do it, but honestly I can envisage these being the most common options.
    • You could attach them straight onto your network by creating a bridge including eth0 (for example), which your containers will attach to. In this example your /etc/network/interfaces might look something like
      auto lo
      iface lo inet loopback
      
      iface br0 inet static
          max_wait 0
          bridge_ports eth0
          address 192.168.0.3
          netmask 255.255.255.0
          gateway 192.168.0.1
    • Alternatively you could create a dummy network device, add that to the bridge and then attach your containers to that, and either NAT (using iptables) or route to your containers. Or just keep them on their own. It really depends what do you want to do. I chose to add a dummy network and route between the 2. The host node interface in this example could look like
      auto lo
      iface lo inet loopback
      
      allow-hotplug eth0
      iface eth0 inet static
          address 192.168.0.3
          netmask 255.255.255.0
          gateway 192.168.0.1
      
      iface br0 inet static
          max_wait 0
          bridge_ports dummy0
          address 10.10.10.1
          netmask 255.255.255.0
  6. Now you need to create the files for the container. debootstrap or febootstrap, etc. are your friends. I chose to keep my containers in /var/lxc/guests. So for my first container (called "one", which is a Lenny basic install) debootstrap lenny /var/lxc/guests/one You'll need to ensure that the /etc/resolv.conf is setup correctly under /var/lxc/guests/one, as is /etc/network/interfaces. For resolv.conf you can most likely copy from the host node. Your interfaces will just need eth0 and lo setup with the correct IPs.
  7. Next you need to create a LXC config. This file is pretty much full of voodoo and dragons. I've saved this one under /var/lxc/guests/one.conf
    # Hostname
    lxc.utsname = one
    # Number of TTYs to allocate to the container
    # Relies on some lxc.cgroup.devices settings
    lxc.tty = 4
    # Networking type
    lxc.network.type = veth
    # State of networking at boot
    lxc.network.flags = up
    # Bridge you want to attach to
    lxc.network.link = br0
    # Internal container network interface name
    lxc.network.name = eth0
    lxc.network.mtu = 1500
    # Address you intend to add the container to
    # Doesn't seem to care too much as far as I can tell
    lxc.network.ipv4 = 192.168.0.3/24
    # Location of the root, from within the host node
    lxc.rootfs = /var/lxc/guests/one
    # Lots of stuff I've not fully yet looked into, but attempted to make
    # some intelligent guesses about
    lxc.cgroup.devices.deny = a
    # /dev/null, /dev/zero
    lxc.cgroup.devices.allow = c 1:3 rwm
    lxc.cgroup.devices.allow = c 1:5 rwm
    # TTYs
    lxc.cgroup.devices.allow = c 5:1 rwm
    lxc.cgroup.devices.allow = c 5:0 rwm
    lxc.cgroup.devices.allow = c 4:0 rwm
    lxc.cgroup.devices.allow = c 4:1 rwm
    # /dev/random, /dev/urandom
    lxc.cgroup.devices.allow = c 1:9 rwm
    lxc.cgroup.devices.allow = c 1:8 rwm
    # /dev/pts/* - Seems to be unused at this point?
    lxc.cgroup.devices.allow = c 136:* rwm
    lxc.cgroup.devices.allow = c 5:2 rwm
    # No idea
    lxc.cgroup.devices.allow = c 254:0 rwm
  8. Next create the container lxc-create -n one -f /var/lxc/guests/one.conf.
  9. And now you can start it. I've discovered that you need to set the container to be daemonised otherwise lxc-start will never return: lxc-start -n one -d To attach to your container just run lxc-console -n one To stop lxc-stop
  10. You will notice at this point that lxc-ls returns 2 sets of lists. The top list is the list of available containers, and the second list of the currently running containers.

This is obviously by no means a definitive guide, but it is just what I've done this evening to get stuff up and running. I've not yet tried getting IPv6 working into the containers, mostly because I wanted to try the v4 networking in a few different ways, and it's now bed time. However looking at the docs, it shouldn't be all that tricky working straight out of the box - something that OpenVz doesn't do in all circumstances (the same can be said for Linux Vservers).

As for whether or not it's worth it.. Lets just say it's not been unpleasant.

OpenSSH 5.4: Great Scott!

One point twenty one jiggawatts! Yesterday (March 8, 2010) the OpenSSH project released version 5.4 and naturally will start hitting the various distributions and platforms soon, and again there are some great things to be interested in:

  • Although many distributions of OpenSSH have SSH1 disabled, the project is now shipping with SSH1 disabled by default.
  • There is the ability to revoke keys (host and user) in both sshd and ssh.
  • Netcat mode connects stdio on the client to a single port forward on the server. For example the following would connect to smtp.server.example.org on port 25, and redirect the output to stdio on my client side. Useful if you need to test connectivity to a mail server, but can't from your direct location, but can from your SSH server (my.ssh.server.example.org). ssh -W smtp.server.example.org:25 my.ssh.server.example.org That has pretty much bags of possibilities, ranging from simple connection tests to piping a file to a remote server that you can't get to directly.
  • sftp-server has gained a read only mode!
  • Passphrase-protected SSH2 private keys are now protected with AES-128 instead of 3DES. This counts if you reencrypt your key or create a new one.

Graphing Micromiser with Munin

I've been playing with Micromiser for a few days, and wanted to graph what it claims to be saving on one of the servers. Luckily this is pretty easy with Munin (which is already running on the box), since Micromiser logs into syslog occasionally. Below is the plugin I hacked together that looks at syslog and uses sed to extract the percentage saving. It's not pretty, but it does work.

Perhaps this'll save you a few minutes.

#!/bin/sh

# Plugin to graph the savings made by micromiser

if [ "$1" = "autoconf" ]; then
        echo yes
        exit 0
fi

if [ "$1" = "config" ]; then

        echo 'graph_title Micromiser Savings (percentage)'
        echo 'graph_args --upper-limit 100 -l 0'
        echo 'graph_vlabel savings'
        echo 'graph_category system'
        echo 'savings.label savings'
	echo 'savings.draw AREA'
        echo 'savings.min 0'
        exit 0
fi

RES=`grep Estimated /var/log/syslog | tail -1 | sed 's/.*(\([0-9\.]*\)%)$/\1/'`
echo -n "savings.value $RES"

 1 2 3 … 11 Next →