MacMini

This page has information about how I have set up a Mac Mini as my Debian server. The most interesting part is probably this section, notably the "Boot mechanism" part where I am describing how I got rEFIt (an EFI boot manager) to work.


Hardware

The hardware I bought is this:

  • Processor = 2.53 GHz Intel Core 2 Duo
  • L2 Cache = 3 MB
  • Bus speed = 1.07 GHz
  • RAM = 4 GB 1067 MHz DDR3 (2x 2 GB)
  • Serial number = YM01916WB9X
  • Hardware UUID = C6EEF74A-3CCB-5220-8BE9-BE712E4FE166
  • Graphics card = NVIDIA GeForce 9400
    • VRAM = 256 MB
  • Hard disks = 2x S-ATA Hitachi HTS545050B9SA02, 5400 rpm
    • Capacity = 500 GB each
    • Partition table type = GPT (GUID Partition Table)
    • Filesystem = Journaled HFS+
    • Disk 1 in use = 7.22 GB
    • Disk 2 in use = 0
  • Connectors
    • Layout as seen from behind
                                                         USB
Power  Ethernet  Firewire  DisplayPort1  DisplayPort2  1 2 3 4 5
    • 1x built-in FireWire 800 MBit/s
    • 1x built-in Ethernet Controller
      • MAC = 34:15:9e:2e:ca:38
    • 1x built-in WiFi Controller
      • Type = AirPort Extreme
      • Firmware = Broadcom BCM43xx 1.0
      • MAC = 7c:6d:62:a4:2c:15
    • 5x built-in USB 2.0, split into 2 USB buses
      • Bus 1
        • USB ports 1, 2 und 5 (see layout above) run on this bus
        • Additional device on this bus: IR receiver (manufacturer = Apple)
      • Bus 2
        • USB ports 3 und 4 (see layout above) run on this bus
        • Additional device on this bus: BRCM2046 hub (manufacturer = Broadcom)
        • Additional device on this bus: Bluetooth USB host controller (manufacturer = Apple)
      • Output of lsusb
root@pelargir:~# lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 004: ID 0b95:772a ASIX Electronics Corp. 
Bus 003 Device 002: ID 03f0:0324 Hewlett-Packard SK-2885 keyboard
Bus 003 Device 003: ID 05ac:8242 Apple, Inc. IR Receiver [built-in]
Bus 002 Device 003: ID 1737:0039 Linksys USB1000
Bus 004 Device 002: ID 0a5c:4500 Broadcom Corp. BCM2046B1 USB 2.0 Hub (part of BCM2046 Bluetooth)
Bus 004 Device 003: ID 05ac:8216 Apple, Inc. Bluetooth USB Host Controller
Bus 004 Device 004: ID 05ac:820a Apple, Inc. 
Bus 004 Device 005: ID 05ac:820b Apple, Inc. 

root@pelargir:~# lsusb -t
4-1.1:1.2: No such file or directory
4-1.1:1.3: No such file or directory
/:  Bus 04.Port 1: Dev 1, Class=root_hub, Driver=ohci_hcd/5p, 12M
    |__ Port 1: Dev 2, If 0, Class=hub, Driver=hub/3p, 12M
        |__ Port 1: Dev 3, If 0, Class='bInterfaceClass 0xe0 not yet handled', Driver=btusb, 12M
        |__ Port 1: Dev 3, If 1, Class='bInterfaceClass 0xe0 not yet handled', Driver=btusb, 12M
        |__ Port 1: Dev 3, If 2, Class=vend., Driver=, 12M
        |__ Port 1: Dev 3, If 3, Class=app., Driver=, 12M
        |__ Port 2: Dev 4, If 0, Class=HID, Driver=usbhid, 12M
        |__ Port 3: Dev 5, If 0, Class=HID, Driver=usbhid, 12M
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=ohci_hcd/7p, 12M
    |__ Port 1: Dev 2, If 0, Class=HID, Driver=usbhid, 1.5M
    |__ Port 5: Dev 3, If 0, Class=HID, Driver=usbhid, 1.5M
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ehci_hcd/5p, 480M
    |__ Port 2: Dev 3, If 0, Class=vend., Driver=asix, 480M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci_hcd/7p, 480M
    |__ Port 7: Dev 4, If 0, Class=vend., Driver=asix, 480M
  • Additional hardware
    • 1x Ethernet-over-USB controller (Fast Ethernet)
      • MAC = 00:24:32:01:a7:83
    • 1x Ethernet-over-USB controller (Gigabit)
      • MAC = 00:12:17:f2:34:05


Bringing Debian Linux to the Mac Mini

References

Other people have written articles about their experiences with setting up Linux on a Mac Mini


Procedure overview

  • After turning on the Mac Mini for the first time, Mac OS X Server starts up and runs you through its initial system configuration wizard
  • When this is finished you have one account with administrator privileges and the entire disk space partitioned for usage with Mac OS X (each hard disk being a separate partition)
  • The first thing to do is to resize the Mac partition on the first hard disk to the bare minimum, and to leave the rest for later partitioning by the Debian installer
  • Once the disks have thus been prepared, the Debian installer can be run for further partitioning and installing the base system
  • After the Debian base system is installed, the boot mechanism must be changed so that Debian will boot up by default when the system restarts


Resizing the Mac partition

The goal of this step is to have one small bootable partition on the first hard disk, with Mac OS X installed on it but using up only minimal space. Since Linux will be the main OS running on the system, we want to give it the maximum possible space.

  • Disk Utility has the capability of resizing a partition (or volume, to use the Mac OS X term) non-destructively
  • The problem is that only volumes can be resized that are not the startup volume
  • The trick is to boot from the Mac OS X install CD (using an external CD/DVD drive) and to launch Disk Utility from within the Mac OS X setup program
  • The Mac OS X volume on the hard disk can now be resized since it is no longer the startup volume
  • The drag handle allows to resize only to about 50 GB, but you can manually type a smaller size into the edit field
  • I went for a partition size of 20 GB. The pre-installed system (Mac OS X 10.6 Server) took up about 7-9 GB, which still leaves me at least another 10 GB of space if I need to add something


Partitioning for Linux

  • Download a suitable Debian installation media image and burn it to CD/DVD
  • I went for a small netinst image, which is around 200 MB in size (Debian 6.0.1a-i386-netinst, to be exact)
  • Boot from the CD/DVD
  • Step through the installer until you get to the partitioning step
  • Set up your partitions as needed; I went for the following layout, which I believe is quite sensible, and which also reflects the state on my old server
(parted) select /dev/sda
Using /dev/sda
(parted) print
Model: ATA Hitachi HTS54505 (scsi)
Disk /dev/sda: 500GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number  Start   End     Size    File system     Name                  Flags
 1      20.5kB  210MB   210MB   fat32           EFI system partition  boot
 2      210MB   20.1GB  19.9GB  hfs+            Customer
 3      20.1GB  22.1GB  2000MB  ext3            root
 4      22.1GB  26.1GB  4000MB  ext3            tmp
 5      26.1GB  30.1GB  4000MB  linux-swap(v1)  swap
 6      30.1GB  50.1GB  20.0GB  ext3            usr
 7      50.1GB  70.1GB  20.0GB  ext3            home
 8      70.1GB  90.1GB  20.0GB  ext3            var
 9      90.1GB  190GB   100GB   ext3            backups
10      190GB   290GB   100GB   ext3            daten
11      290GB   340GB   50.0GB  ext3            cache

(parted) select /dev/sdb
Using /dev/sdb
(parted) print
Model: ATA Hitachi HTS54505 (scsi)
Disk /dev/sdb: 500GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number  Start   End    Size   File system  Name                  Flags
 1      20.5kB  210MB  210MB  fat32        EFI System Partition  boot
 2      210MB   500GB  500GB  ext3         media
  • Note that I'm using GNU parted here to display the GPT partition table. fdisk does NOT support GPT, it can handle only the MBR partition table format. Of course, it is not necessary to know which utility is used by the Debian installer (in fact I don't know if it is parted), but if you want to inspect or manipulate the partition table later on, you must install parted
  • Also note that it's a good idea to nicely label partitions in the Debian installer, later on you will have less trouble identifying partitions when you look at them through a tool like parted. I'm not sure if labels like this are possible with the MBR partition table format, but it does work with the GPT format.
  • If you sum up the partition sizes on the first hard disk, you will note that I didn't use up the entire 500 GB. This is intentional - in my experience with my old server, the sizes as displayed are more than sufficient. I leave the leftover so that I can add another partition later on in an emergency, when I actually know where more space is needed


Installing the base system

  • Once partitioning is over, a base Debian system can be installed
  • You will probably need net access to download packages, unless you have burned a large install image
  • When the Debian installer runs tasksel, I select only the task that refers to the base system (I don't recall the actual name of the task)
  • I explicitly do not select any other tasks (e.g. web server) because tasks usually install too many packages, or not exactly those that I want
  • In addition, packages installed via tasksel are marked as "manually installed" in the APT package management system. This is not helpful because when I later decide to remove a package, dependencies will not be automatically removed as well.


Boot mechanism

  • The Debian installer includes a step where grub can be installed on the system. I tried this, but when I rebooted after the Debian setup was complete, the system that came up was Mac OS X and not Debian
  • The reason for this is that grub installs itself into the MBR, but the Mac Mini's EFI firmware ignores the legacy MBR and only boots from one of the GPT partitions marked as bootable
    • Apparently if EFI cannot find a bootable GPT partition, it falls back into some sort of legacy mode where it also starts to look at the MBR
    • In such a case it would successfully boot grub
    • In my case, though, I still have a working and bootable Mac OS X partition, which is why this fallback mechanism does not kick in
  • The solution is rEFIt, an EFI boot manager, which can be made to chainload grub
  • But first we have to solve a few tricky issues :-)
  • Reboot into Mac OS X
  • Download rEFIt (0.14 at the time of writing)
  • Run the .mpkg installer package inside the disk image to install rEFIt
  • Launch Terminal.app and execute the following commands to actually install the boot manager:
cd /efi/refit
./enable.sh
  • Edit /efi/refit/refit.conf with a text editor and change the default OS that should be booted when the system comes up. Read the rEFIt documentation for details on how to do this. The following example shows the line that I changed - the "L" refers to "Linux":
default_selection L
  • Reboot the system
  • You should now see the rEFIt boot menu and rEFIt should automatically detect two boot options
    • Mac OS X
    • Linux
  • Select the "Linux" option, then from the submenu select and run the "Partitioning Tool"
  • The tool will automatically synchronize the MBR with the content from the GPT partition table. This needs to be done because when we created partitions in the Debian installer, the installer wrote the partitioning information only into the GPT, but not into the MBR.
  • Now that the MBR is correct and up-to-date, grub needs to be re-installed. I did this by booting into the rescue mode of the Debian netinst CD
  • In the rescue mode menu, select the root file system
  • The menu automatically detects that grub is present on the file system and offers an option to re-install grub
  • One can choose where to install grub; I am a bit hazy here which choice is the correct one
    • I first tried to install into the MBR because I had read that this is the correct thing to do
    • But grub complained with an error message, so next I tried to install into the root file system
    • grub still complained with an error message
    • I then rebooted and found out that I was suddenly able to boot Linux
    • I didn't have the nerve to destroy the system just so that I could find out exactly which action did the trick


Regardless of which grub install option makes grub work, you can now reboot the system and enjoy watching beautiful Debian starting up. Phew, that was a bit of work... :-)


System installation continued

Configure Debian distribution

  • Edit /etc/apt/sources.list to point the APT system to the proper Debian distribution
  • In my case I like to use Debian testing because it offers more up-to-date package versions; I usually can cope with any problems that crop up...
  • This is how the file looked like at the time of writing
# Security updates
deb http://security.debian.org/ stable/updates main
deb http://security.debian.org/ testing/updates main

# Stable - Primary mirrors
deb http://ftp.ch.debian.org/debian/ stable main
deb-src http://ftp.ch.debian.org/debian/ stable main

# Testing - Primary mirrors
deb http://ftp.ch.debian.org/debian/ testing main
deb-src http://ftp.ch.debian.org/debian/ testing main

# Testing - Secondary mirrors
# Enable if primary mirrors are not available
#deb ftp://mirror.switch.ch/mirror/debian/ testing main
#deb-src ftp://mirror.switch.ch/mirror/debian/ testing main

# Unstable - currently not configured

# Non-Debian
deb http://debian.mcmillan.net.nz/debian squeeze awm

# Experimental - enable if required
#deb http://ftp.ch.debian.org/debian experimental main


Upgrade the system

  • Download the newest package descriptions
  • Update the entire system with this command
apt-get dist-upgrade
  • Install the newest Linux kernel image; at the time of writing this is the package
linux-image-2.6.38-2-686
  • Reboot


Install packages

Following is a list of packages that I am installing to prepare the system to run the services that I need. Migration of configuration files and databases from the old server is done separately and not documented here.

apache2
apache2-doc
slapd
ldap-utils
samba
smbclient
swat
phpldapadmin         (pulls in php via dependencies; a little bit of fiddling around is needed to make aptitude happy)
ssh                  (meta package that installs client and server packages)
phpmyadmin           (pulls in mysql via dependencies)
mediawiki-extensions (pulls in mediawiki and various extension packages via dependencies)
davical              (pulls in postgresql via dependencies)
squirrelmail
squirrelmail-compatibility
squirrelmail-quicksave
squirrelmail-secure-login
squirrelmail-spam-buttons
torrentflux
git-core             (pulls in rsync via dependencies)
gitosis
gitweb
greylistd
courier-imap-ssl
courier-webadmin
parted
exim4-daemon-heavy   (replaces preinstalled exim4-daemon-light)
exim4-doc-html
spamassassin         (pulls in spamc via dependencies)
libpam-ldap
libnss-ldap          (pulls in nscd via dependencies)
isc-dhcp-server-ldap
tshark


Kernel driver for Gigabit ethernet-over-USB controller

The Fast Ethernet-over-USB controller worked out of the box, but the Gigabit thingy refused to work at first: The interface was recognized and I was able to bring it up with ifup, but the interface did not transmit any data. The Gigabit controller has an ASIX chipset, just like the Fast Ethernet controller, but apparently the chipset requires a newer kernel driver than the one supplied by Debian.

See the Kernel page on this wiki for detailed information on how I got the device to work.


USB device information

root@pelargir:~# lsusb -vs 2:3

Bus 002 Device 003: ID 1737:0039 Linksys USB1000
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass          255 Vendor Specific Class
  bDeviceSubClass       255 Vendor Specific Subclass
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x1737 Linksys
  idProduct          0x0039 USB1000
  bcdDevice            0.01
  iManufacturer           1 USB2.0
  iProduct                2  USB2.0 Gigabit Adapter 
  iSerial                 3 007858
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           39
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          4 0
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              450mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           3
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass    255 Vendor Specific Subclass
      bInterfaceProtocol      0 
      iInterface              7 0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval              11
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
Device Qualifier (for other device speed):
  bLength                10
  bDescriptorType         6
  bcdUSB               2.00
  bDeviceClass          255 Vendor Specific Class
  bDeviceSubClass       255 Vendor Specific Subclass
  bDeviceProtocol         0 
  bMaxPacketSize0         8
  bNumConfigurations      1
Device Status:     0x0000
  (Bus Powered)