Sunday, December 21, 2008

Geeking Out - Setting Up an Ubuntu Server

I've been working on this project for a few weeks now and its finally coming to completion, so I thought I'd document it here so others can save some of the time and hassles I have had in getting to this point.

When I bought a new MacBook for myself, I convinced Steph to ditch her P.O.S. Windows XP machine and take my old MacBook. We now needed a few thing:
  • Home file server for sharing documents, photos, etc
  • Automated back up system (TimeMachine would be ideal, but I didn't want to purchase a TimeCapsule for the network based backups. I'm cheap!)
  • Shared printing (again, I'm cheap, I don't want to buy a new printer and my existing printers don't support networked printing)
  • Home-based VPN to allow me access to the home network when on the road
So the obvious solution was to repurpose Steph's old Dell box into a server to support our needs. Here's what I did:

First, I replaced the hard drve with an unused 160GB SATA drive I had sitting around. After burning a CD from an ISO of Ubuntu 8.10 Server (Intrepid Ibex), I installed the server and got it up and running on my home network with a static IP address. The server is called "papaya". The initial install included an ssh daemon for remote access so I could work away from the console. Eventually the box will be headless, but for now its connected to my home office KVM.

Next, I configured ufw (Uncomplicated Firewall) to start locking down services. First, set the firewall into the "default deny" mode (a.k.a. whitelisting of approved inbound connections):

sudo ufw default deny

And then I added a rule to allow inbound ssh from the local network:

sudo ufw allow proto tcp from 192.168.5.0/24 to 192.168.5.2 port 22

Next I installed netatalk to support AppleTalk, allowing me to connect my MacOS X systems to papaya's shared disks. I started with directions from here and here, but I found they didn't work exactly as presented, and I needed some tuning to make it work. (See the referenced links for more details on all of these steps, I just distilled this down to the most important info.)

First, install netatalk with encryption support (required by MacOS X):

sudo aptitude update
mkdir -p /tmp/src/netatalk
cd /tmp/src/netatalk
sudo aptitude install devscripts cracklib2-dev dpkg-dev libssl-dev
apt-get source netatalk
sudo apt-get build-dep netatalk
cd netatalk-2.0.3
sudo DEB_BUILD_OPTIONS=ssl dpkg-buildpackage -us -uc
sudo debi
echo "netatalk hold" | sudo dpkg --set-selections

Note the last line, it places a hold on any updates to netatalk when running updates on the Ubuntu server, this is necessary to prevent updates from breaking the installed version. Next I configured netatalk by editing a few files. First, /etc/default/netatalk was modified with the following configuration:

ATALKD_RUN=no
PAPD_RUN=no
CNID_METAD_RUN=yes
AFPD_RUN=yes
TIMELORD_RUN=no
A2BOOT_RUN=no

Next, edit /etc/netatalk/afpd.conf by adding the following line to the end of the file:

- -transall -uamlist uams_randnum.so,uams_dhx.so -nosavepassword -advertise_ssh

Now, configure your shared volumes in /etc/netatalk/AppleVolumes.default by adding the following lines to the end of the file (make sure its one line!):

/media/TimeMachine TimeMachine allow:username1,username2 cnidscheme:cdb options:usedots,upriv

This mounts a shared volume named TimeMachine located at /media/TimeMachine (your mount point may vary, this is an external 1TB USB drive at the moment). List the specific users who should be able to login to the share with their credentials. The remaining options have to do with dealing with invisible files/folders which are used by MacOS X. I actually created a handful of shares, each of them with different functions (TimeMachine, generic file share, etc.).

Now we restart netatalk:

sudo /etc/init.d/netatalk restart

Unfortunately, this share is not publicized to the local network, which I wanted for ease of use. So I set up Avahi, a daemon for Apple's Bonjour zero-configuration service:

sudo apt-get install avahi-daemon
sudo apt-get install libnss-mdns

Edit /etc/nsswitch.conf to add the mdns service to the end of the line beginning with hosts. In the end the line should look like:

hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4 mdns

Next, configure Avahi to publish the service. Create a file with the name /etc/avahi/services/afpd.service containing the following XML:

<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name replace-wildcards="yes">%h</name>
<service>
<type>_afpovertcp._tcp</type>
<port>548</port>
</service>
<service>
<type>_device-info._tcp</type>
<port>0</port>
<txt-record>model=Xserve</txt-record>
</service>
</service-group>

Note that this sets up Avahi on port 548 and tells Avahi to publish the device as an XServe, which will make papaya appear as an XServe icon on any Macs connected to the network. Open port 548 to listen for inbound connections:

sudo ufw allow proto tcp from 192.168.5.0/24 to 192.168.5.2 port 548

Restart Avahi to publish the servers:

sudo /etc/init.d/avahi-daemon restart

Woohoo, now I have the server publishing its shares to the network which are seen by my Macs, as seen below.



Now we need to configure the Mac to be able to use papaya as a TimeCapsule without paying for Apple's hardware. Drop to a command line and run the following (on your Mac, not Ubuntu!):

defaults write com.apple.systempreferences TMShowUnsupportedNetworkVolumes 1

Mount any of the remote volumes from the Mac and use the TimeMachine preferences to select the remote system for backups. TimeMachine will actually create a disk image on the remote system and utilize that image for its backup volume. Or, in my case, maybe not! But we can easily fix that. Use MacOS X Disk Utility to create a new disk image as a "sparsebundle disk image". The naming is very specific and in the format machine_name_MAC_ADDRESS.sparsebundle. For instance, if your machine name is joeyjr and the MAC address of the primary interface (en0) is 00:13:24:1f:12:10 then the name of the disk image should be:

joeyjr_0013241f1210.sparsebundle



Note that the MAC address separators have been removed. How do you find the MAC address of the primary adapter? Drop to a command line and execute the command ifconfig, it should return something like:

lo0: flags=8049 mtu 16384
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
inet 127.0.0.1 netmask 0xff000000
inet6 ::1 prefixlen 128
gif0: flags=8010 mtu 1280
stf0: flags=0<> mtu 1280
en0: flags=8863 mtu 1500
inet6 fe80::223:32ff:febf:cd2%en0 prefixlen 64 scopeid 0x4
inet 192.168.5.114 netmask 0xffffff00 broadcast 192.168.5.255
ether 00:23:32:bf:0c:d2
media: autoselect (100baseTX ) status: active
supported media: none autoselect 10baseT/UTP 10baseT/UTP 10baseT/UTP 10baseT/UTP 100baseTX 100baseTX 100baseTX 100baseTX 1000baseT 1000baseT 1000baseT
en1: flags=8863 mtu 1500
inet6 fe80::223:6cff:fe7f:5cd%en1 prefixlen 64 scopeid 0x5
inet 192.168.5.3 netmask 0xffffff00 broadcast 192.168.5.255
ether 00:23:6c:7f:05:cd
media: autoselect status: active
supported media: autoselect
vmnet8: flags=8863 mtu 1500
inet 192.168.94.1 netmask 0xffffff00 broadcast 192.168.94.255
ether 00:50:56:c0:00:08
vmnet1: flags=8863 mtu 1500
inet 192.168.200.1 netmask 0xffffff00 broadcast 192.168.200.255
ether 00:50:56:c0:00:01

The lines after en0 refer to the primary adapter, in this case the ethernet adapter, and the MAC address is found on the line in bold.

Create a sufficiently large image (i.e. 500GB) (note: this image will only take a few MB until it is filled, so this can be done on a pretty full disk) and move it to the root of the share you wish to use for TimeMachine.

Mount the TimeMachine share from above. Open the System Preferences, choose the share as your TimeMachine volume and let it go to work. If you did everything correctly, bacups should begin. My 160GB backup took at least 8 hours, if not longer.

Now backups are great, but they only work for me if you can restore from them in a crisis. How do I define a crisis? Not restoring a file that has been accidentially deleted by using the TimeMachine application, that should work as long as I have the volume mounted. How about Installing MacOS on a blank drive and having the MacOS installer pull all of the data from your networked backup?

In theory, everything should work as follows. I have not done a full disaster recovery yet (though I will before I depend on this as my only backup solution) so take all of this with a large grain of NaCl. Boot from the install CD and start the terminal from the Utilities menu. In the terminal, mount your afp file share:

mkdir /Volumes/timemachine
mount_afp afp://username:password@papaya/TimeMachine /Volumes/timemachine

If the disk is mounted you should be able to find your .sparsebundle in the directory /Volumes/timemachine. Exit the terminal and now open the Restore from Backup utility. The restore utility will find the remotely mounted TimeMachine volume and allow you to restore from that point.

OK, we now know we can back up and restore from the backup. That's all good news. Let's get some printers set up. I have 2 HP printers, a HP LaserJet 1100 which runs on a paralell port, and a HP OfficeJet 5510 All-In-One, running from the USB port. First, ensure hp-lip and cups are installed:

sudo apt-get install hplip
sudo apt-get install cups

Run the hp-setup command to set up your printers (follow the prompts):

sudo hp-setup

Configure cups to listen on port 631 for remote printing and configuration by editing /etc/cups/cupsd.conf

# Allow remote access
Port 631
Listen /var/run/cups/cups.sock

And configure cups to allow remote administration at http://papaya:631/:

<Location />
Allow all
Allow all
# Allow shared printing and remote administration...
Order allow,deny
Allow all
</Location>
<Location /admin>
AuthType Default
Require user @SYSTEM
Allow all
# Allow remote administration...
Order allow,deny
Allow all
</Location>
<Location /admin/conf>
AuthType Default
Require user @SYSTEM
Allow all
# Allow remote access to the configuration files...
Order allow,deny
Allow all
</Location>

See http://ubuntuforums.org/showthread.php?t=736489 for more information on configuring cups. I'm not perfectly happy with this yet, I believe it can be locked down further, but its good for now.

Now, open the firewall to allow access on port 631:

sudo ufw allow proto tcp from 192.168.5.0/24 to 192.168.5.2 port 631

Restart cups:

sudo /etc/init.d/cupsys restart

Now I browse to http://papaya:631/ to manage configured printers. With the printer URLs in hand I can add remote printers to my MacOS X machines through the Printers preference pane. Printing on the LaserJet is a bit wonky at times, but printing to the OfficeJet is perfect. I still need to set up remote scanning, but that's a project for another day.

The VPN is still a work in progress. I'll post details on setting up OpenVPN once I have had chance to configure and test it completely.

(All the info posted herein is for informational purposes only. Use this at your own risk as I will provide no support.)