Linux 802.1q VLAN Trunking

This is mostly for future reference, but maybe you will find it useful. This is on an Ubuntu 10.04.3 LTS box.

Cisco Setup

All I am doing here is trunking one interface (G2/0/18) and restricting access to two vlans (101 and 102).

switch#configure terminal
Enter configuration commands, one per line.  End with CNTL/Z.
switch01(config)#interface G1/0/18
switch01(config-if)#switchport trunk encapsulation dot1q
switch01(config-if)#switchport mode trunk
switch01(config-if)#switchport trunk allowed vlan 101,102
switch01(config-if)#exit
switch01(config)#exit
switch01#show running-config interface G1/0/18
Building configuration...

Current configuration : 167 bytes
!
interface GigabitEthernet1/0/18
 switchport trunk encapsulation dot1q
 switchport trunk allowed vlan 101,102
 switchport mode trunk
end

switch01#

Linux Setup

  1. Add the 8021q module to the kernel
    # modprobe 8021q
  2. Add the module to the /etc/modules file, so that it loads at next startup
    # echo 8021q >> /etc/modules
  3. Install the appropriate package
    # apt-get install vlan
  4. Configure the network. In my example, eth0 is connected to a trunk port on a Cisco switch, with vlans 101 and 102 trunked to it. eth1 is connected to a separate network and switch.
    # cat /etc/network/interfaces.
    
    auto eth0.101
    iface eth0.101 inet static
    	address 172.17.101.9
    	netmask 255.255.255.0
    	network 172.17.101.0
    	broadcast 172.17.101.255
    	gateway 172.17.101.1
    	vlan_raw_device eth0
    
    auto eth0.102
    iface eth0.102 inet static
    	address 172.17.102.9
    	netmask 255.255.255.0
    	network 172.17.102.0
    	broadcast 172.17.102.255
    	vlan_raw_device eth0
    
    auto eth1
    iface eth1 inet static
    	address 172.17.100.9
    	netmask 255.255.255.0
    	network 172.17.100.0
    	broadcast 172.17.100.255
  5. Restart networking. I came across inconsistent results by using /etc/init.d/networking restart and the ifup and ifdown commands. While your mileage may vary, I just rebooted the box.
  6. Make sure things are working. As you can see, eth0 does not have an ip address, though the vlan interfaces, eth0.101 and eth0.102, do.
    kmjohnson@squid:~$ ifconfig
    eth0      Link encap:Ethernet  HWaddr 14:fe:b5:2c:15:86
              inet6 addr: fe80::16fe:b5ff:fe2c:1586/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:23763 errors:0 dropped:0 overruns:0 frame:0
              TX packets:10485 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000
              RX bytes:3481376 (3.4 MB)  TX bytes:2500480 (2.5 MB)
              Interrupt:36 Memory:d6000000-d6012800 
    
    eth1      Link encap:Ethernet  HWaddr 14:fe:b5:2c:15:88
              inet addr:172.17.100.9  Bcast:172.17.100.255  Mask:255.255.255.0
              inet6 addr: fe80::16fe:b5ff:fe2c:1588/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:973 errors:0 dropped:0 overruns:0 frame:0
              TX packets:257 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000
              RX bytes:75737 (75.7 KB)  TX bytes:29086 (29.0 KB)
              Interrupt:48 Memory:d8000000-d8012800 
    
    eth0.101  Link encap:Ethernet  HWaddr 14:fe:b5:2c:15:86
              inet addr:172.17.101.9  Bcast:172.17.101.255  Mask:255.255.255.0
              inet6 addr: fe80::16fe:b5ff:fe2c:1586/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:17260 errors:0 dropped:0 overruns:0 frame:0
              TX packets:10350 errors:0 dropped:4 overruns:0 carrier:0
              collisions:0 txqueuelen:0
              RX bytes:2445291 (2.4 MB)  TX bytes:2400114 (2.4 MB)
    
    eth0.102  Link encap:Ethernet  HWaddr 14:fe:b5:2c:15:86
              inet addr:172.17.102.9  Bcast:172.17.102.255  Mask:255.255.255.0
              inet6 addr: fe80::16fe:b5ff:fe2c:1586/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:6503 errors:0 dropped:0 overruns:0 frame:0
              TX packets:101 errors:0 dropped:3 overruns:0 carrier:0
              collisions:0 txqueuelen:0
              RX bytes:513299 (513.2 KB)  TX bytes:8438 (8.4 KB)
    
    lo        Link encap:Local Loopback
              inet addr:127.0.0.1  Mask:255.0.0.0
              inet6 addr: ::1/128 Scope:Host
              UP LOOPBACK RUNNING  MTU:16436  Metric:1
              RX packets:277 errors:0 dropped:0 overruns:0 frame:0
              TX packets:277 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0
              RX bytes:25230 (25.2 KB)  TX bytes:25230 (25.2 KB)
    
    kmjohnson@squid:~$ ping 172.17.101.1
    PING 172.17.101.1 (172.17.101.1) 56(84) bytes of data.
    64 bytes from 172.17.101.1: icmp_seq=1 ttl=64 time=0.124 ms
    ^C
    --- 172.17.101.1 ping statistics ---
    1 packets transmitted, 1 received, 0% packet loss, time 0ms
    rtt min/avg/max/mdev = 0.124/0.124/0.124/0.000 ms
    kmjohnson@squid:~$ ping 172.17.102.1
    PING 172.17.102.1 (172.17.102.1) 56(84) bytes of data.
    64 bytes from 172.17.102.1: icmp_seq=1 ttl=64 time=9.39 ms
    ^C
    --- 172.17.102.1 ping statistics ---
    1 packets transmitted, 1 received, 0% packet loss, time 0ms
    rtt min/avg/max/mdev = 9.391/9.391/9.391/0.000 ms
    kmjohnson@squid:~$

Issues

I ran into an issue where when connecting to an interface that did not have a gateway defined (eth0.102), the packet was being dropped by the kernel. To fix this, the following two lines were needed in /etc/sysctl.conf:

net.ipv4.conf.default.rp_filter=0
net.ipv4.conf.all.rp_filter=0

Environmental temperature monitoring with 1-Wire and Linux Part 1

After toying with the idea for a couple of years, I finally got started on setting up a 1-Wire network in my house to collect temperatures in each of my rooms.  The long delay in getting started with this project is almost entirely from having trouble in finding definitive information regarding what I needed, so I hope to accomplish that here.

Overview

A 1-Wire network is pretty simple: Connect a 1-Wire adapter to a PC, and connect that adapter to the network, be it a hub which connects multiple 1-Wire network segments, or a single 1-Wire run, as you can have multiple 1-Wire devices on a single run.

My setup looks like this:

Server – 1-Wire Serial Adapter6 Channel Hub – Two DS18S20s (one on two of the 6 channels of the hub, this leaves me room to expand 4 more channels.  You can also daisy-chain multiple sensors on a single run).

I am using standard CAT5e Eithernet cable for my 1-Wire network; the DS18S20 has 3 pins, two of which are used.  The first pin connects to the white-green wire, and the second to the blue wire.  I will add some more info here later, but it is really that simple.

Connecting it to your PC

I am running Linux on my server.  After wiring up the network and connecting it to the serial adapter, and the adapter to my PC, it was time to get started.

Install digitemp

Digitemp is used to communicate with 1-Wire networks, it has been around for a while, and it works.

sudo apt-get install digitemp

Make sure everything works

  1. We’re using a DS9097U serial adapter, so I symlinked the binary for ease of use.
    ln -s /usr/bin/digitemp_DS9097U /usr/local/bin/digitemp
  2. Setup the initial config file. My serial adapter was on /dev/ttyS0, yours may be on /dev/ttyS1.
    digitemp_DS9097U -i -s /dev/ttyS0 -c /usr/local/etc/digitemp.conf
  3. Get some actual data.
    digitemp -c /usr/local/etc/digitemp.conf -a

That third line should produce output similar to this:

kjohnson@zm:~$ digitemp -c /usr/local/etc/digitemp.conf -a
DigiTemp v3.5.0 Copyright 1996-2007 by Brian C. Lane
GNU Public License v2.0 - http://www.digitemp.com
Dec 21 23:09:35 Sensor 0 C: 15.44 F: 59.79
Dec 21 23:09:36 Sensor 1 C: 23.75 F: 74.75

Automate it

Super! Things work.  Now I’d like to start storing this data in a database, so that I can do neat things with it later (like trending graphs).  Make sure mysql is installed (apt-get install mysql-server).  I am using cron to call a perl script which calls digitemp and stores the data in a database (apt-get install libdbi-perl libdbd-mysql-perl)

#!/usr/bin/perl

use strict;
use warnings;
use DBI;

my $dbh = DBI->connect('DBI:mysql:temperature', 'temp', 'password') or die "Could not connect to db: $DBI::errstr";

my @sensors = ( # Digitemp returns sensors numerically, so I am naming them here; the array index matches up to that which digitemp returns.
 'Workshop',
 'Computer Room'
);
my $dt = '/usr/local/bin/digitemp -q -c /usr/local/etc/digitemp.conf';
my $s = 0;      # Start at sensor 0

foreach my $sensor (@sensors) { # For each sensor
 my $date = time;               # Get the current date
 my $temp = get_temp($s);       # Assign the return value of get_temp subroutine to $temp

 insert($s, $sensor, $date, $temp);     # Call the insert subroutine with the relevant data

 $s++;  # Move on the next sensor
}

sub get_temp {
 my $sensor = $_[0];    # Sensor ID
 my $temp = "$dt -t $sensor -o 3"; # Digitemp command to call
 chomp($temp = `$temp | awk '{print \$2}'`);    # Actually call the command.  Chomp removes the new line.
 return $temp;  # Return the temperature to whatever called this subroutine.
}

sub insert {
 my $sensor_id = $_[0];
 my $sensor_name = $_[1];
 my $date = $_[2];
 my $temp = $_[3];
 my $sth = $dbh->prepare("INSERT INTO temperature (sensor_id, sensor_name, time, temperature) VALUES ($sensor_id, '$sensor_name', '$date', $temp)");
 $sth->execute();
}

Now just put this in a cronjob to be called every 5 minutes, and you’re golden!

kjohnson@zm:~$ crontab -l
*/5 * * * * /home/kjohnson/1wire.pl
kjohnson@zm:~$

Scraping Amazon S3 files with Ruby

Below is a pretty simple ruby script for parsing files uploaded to an Amazon S3 bucket and inserting the file’s information into a MySQL database.

#!/usr/local/bin/ruby

require 'rubygems'
require 'aws/s3'
require 'mysql'
require 'lockfile'

begin
 Lockfile.new('/tmp/scraper.lock', :retries => 0) do # Setup the lock file

         my = Mysql::new("localhost", "nfssupport", "password", "upload_files") # Setup the MySQL connection
         q = my.query("Select FileName, FileModified from files") # Setup the MySQL query
         db = Array.new # Create the array for the MySQL file list
         q.each_hash do |f| # For each file in the DB
                 db << "#{f['FileName']} - #{f['FileModified']}" # Put it into the array
         end

         AWS::S3::Base.establish_connection!( # Create the S3 connection
                 :access_key_id      => 'access_key_id',
                 :secret_access_key  => 'secret_access_key'
         )
         files = AWS::S3::Bucket.objects( # Put the S3 files into the files array
                 'domain-tld',
                 :prefix => 'uploads/user@domain.tld/uuid'
         )

         files.each do |file| # For each S3 file
                 t = Time.parse(file.about['last-modified'])
                 file_date = "#{t.year}#{sprintf('%02d',t.month)}#{sprintf('%02d',t.day)}"
                 file_name = file.key.split('/',4).last.gsub(/^(\d+\-)/,'')
                 file_modified = file.about['last-modified'].split(' ',5).last

                if !db.include? "#{file_name} - #{file_modified}" # If file not in DB
                         st = my.prepare("insert into files (FileName, FileDate, FileModified, FileLink, FileDescription, FileSize) VALUES (?, ?, ?, ?, ?, ?)
")
                         st.execute(file_name, file_date, file_modified, "https://uploads.domain.com/download/#{file.key.split('/',3).last}", file.metada
ta['x-amz-meta-description'], file.about['content-length']) # Insert it
                         st.close
                end
         end
 end

rescue Lockfile::MaxTriesLockError => e
        puts "Scraper is already running!"
end

How To: Download files from Amazon S3 using perl and Amazon::S3

After having such a hard time finding (m)any good examples online, this article is going to explain how to use perl to connect to Amazon’s S3 service to download files. I am by no means a perl expert, so take the below code with a pound of salt. This example assumes that you have already a working Amazon S3 service, and the appropriate keys.

This code is used to download files which our customer’s upload to our support site. The files are downloaded and stored in a directory by date (YYYYMMDD). We have a number of different users and as such only want to download the files for a specific user ($prefix).

The first thing that you will need to do is to install the Amazon::S3 CPAN module with a command similar to:

cpan -i Amazon::S3

Now for the code:

#!/usr/bin/perl

use strict;
use warnings;
use Amazon::S3;

## Amazon S3 Stuff ##
my $aws_access_key_id     = 'aws_access_key_id';
my $aws_secret_access_key = 'aws_secret_access_key';
my $bucket = 'bucket-name';  # The bucket name that files are uploaded to.
my $prefix = 'uploads/bucket-name@domain.tld/uuid';  # We only want to get the files that were uploaded for a specific user.
my $http_prefix = 'https://uploads.domain.tld/download/uuid/';  # I use this string to build the URL
## Amazon S3 Stuff ##

## Script Variables ##
my $directory = '/zstore/uploads/';  # Top level of where to save files to
my $logfile = $directory . "scrape.log";  # Where to log the file downloads to.
## Script Variables ##

open(my $fh, "+>>", $logfile);  # Open the file handle for writing logs

my $s3 = Amazon::S3->new({  # This sets up the Amazon S3 connection.
 aws_access_key_id      => $aws_access_key_id,
 aws_secret_access_key  => $aws_secret_access_key
});

print $fh localtime() . ": Getting file list...\n";

my $files = $s3->list_bucket({  # This gets the entire list of files under the $prefix in the $bucket, or dies with an error.  $files is a multidimensional hash.
 bucket => $bucket,
 prefix => $prefix
}) or die $s3->err . ": " . $s3->errstr;

print $fh localtime() . ": Got file list...\n";                 # If we have made it this far, we now have the entire list of files.

foreach my $file ( @{ $files->{keys} } ) {                      # $file is a hash of arrays of hashes, AKA multidimensional hash.
 my $file_name = substr($file->{key}, 69);                      # 20110224110053-file.tar.gz
 my $file_true_name = substr($file->{key}, 84);                 # file.tar.gz
 my $file_date = substr($file->{key}, 69, 8);                   # 20110224
 my $sub_directory = $directory . $file_date;                   # /zstore/uploads/20110224
 my $file_path = $sub_directory . '/' . $file_true_name;        # /zstore/uploads/20110224/file.tar.gz
 my $url = $http_prefix . $file_name;                           # $url is the actual url to the file

 unless (-d $sub_directory){                                    # Unless the directory is already created
  print $fh localtime() . ": Creating $sub_directory...\n";     # Log that we are creating the directory
  mkdir($sub_directory);                                        # And create that directory
 }

 unless (-e $file_path) {                                       # Unless the file has already been downloaded
  print $fh localtime() . ": Fetching $file_name...\n";         # Log that we are fetching the file
  my $line = system("fetch -mq -o '$file_path' '$url'");        # Actually download the file, assigning the return code of `fetch` to $line
  if ($line == 0) {                                             # If the file is successfully downloaded
   print $fh localtime() . ": Succesfully got $file_path...\n"; # Log it
  } else {                                                      # Else
   print $fh localtime() . ": Problem getting $file_path...\n"; # Could not fetch it for whatever reason.  Move on.
  }
 }
}
print $fh localtime() . ": Exiting!\n\n";                       # We've went through the entire file list.  Log it.
close($fh);                                                     # Close the file handle.

If you spot any errors or have any questions, comments or feedback, please post a comment!

Improvements to ZoneMinder’s infinite scroll events list: pagemarks

I’ve been spending a lot of time working on my new ZoneMinder skin lately, specifically the Events page. While I implemented infinite scrolling a while back, I felt like the results (“events”) were missing context, and that the lack of pages was taking something away from navigation. Luckily, I came across Travis B. Isaacs’ Improving on Infinite Scrolling idea.  Here is the result:

Beware of Velociraptor

So I was nearing completion of the privacy fence that I was building for my back yard. I have a dog, and instead of going the the traditional “Beware of Dog” route, I wanted to do something a little bit more creative, so I went over to buildasign.com and designed my own sign:

Beware of Velociraptor
I couldn’t find any silhouetted-pictures of a Velociraptor, so I found nice side-view picture and edited it myself.

Well, the sign arrived yesterday:

Beware of Velociraptor sign on my fence

Diskless XBMC HTPC with FreeBSD, NFS, pfSense and PXE

XBMC Confluence Skin I have just finished setting up a new XMBC HTPC for my living room; I will walk you through this step-by-step so that you can set one up for yourself.  At over 1,700 words, this is a fairly lengthy tutorial; I have separated the steps into the correct order and have made them as easy to follow as possible.

  1. Introduction
  2. Setup BIOS
  3. Setup DHCP Server
  4. Setup FreeBSD Server
  5. Install XBMC-Live (Linux)
  6. Copy XBMC to NFS Server
  7. Setup XBMC
  8. Caveats

This will be broken down into a number of smaller steps. First, we will setup the BIOS of the HTPC. Next, we will want to setup your DHCP server for PXE / Network booting and then setup your FreeBSD server. Once your ‘backends’ are setup, it is time to configure your HTPC (frontend). This will consist of installing XBMC-Live, copying XBMC to your NFS server (FreeBSD), and then configuring a small number of XBMC options. Finally, there are a number of caveats to address.

Introduction

I decided to go with XBMC instead of MythTV as I 1) do not have cable and thus have no need for live TV recording and 2) have only one frontend, so I do not need the master / slave setup that MthTV has.

After about a week of research, I decided to go with the following hardware:

  1. ASUS AT3IONT-I
    This is an amazing little board. I have always had good experiences with Asus. It should be noted that the heatskin gets very hot even when the system is idling. You may opt to place a 40mm fan on the heatsink, as I did.
  2. Kingston KVR1066D3N7K2/4G
    I have always had good experiences with Kingston RAM.
  3. IN WIN IW-BQ656 Black Mini-ITX
    If you are used to HTPCs the size of a Revo, than this box will seem huge. But for what you’re packing, it is nicely sized. It should be noted that this case has an extra inch or so of height for a 2.5″ HDD and slim CDROM. Since we’ll be using neither, feel free to find a case that better suits your environment, if appropriate.

Setup BIOS of HTPC

  1. Advanced -> CPU Configuration -> Hyper Threading Technology: Disabled
    I decided to disable Hyper Threading to further reduce the power requirements and heat generation of the box.  Watching Avatar in 1080p, without Hyper Threading, my CPU load was at 0.01.  You neither need nor will miss this feature.
  2. Advanced -> Chipset -> MCP7A Configuration -> iGPU Frame Buffer Detect: Disabled
  3. Advanced -> Chipset -> MCP7A Configuration -> iGPU Frame buffer Size: 512MB
  4. Advanced -> Onboard Devices Configration -> Front Panel Select: HD Audio
    While I use HDMI for both audio and video, this feature may be useful to you.
  5. Advanced -> Onboard Devices Configration ->LAN Option ROM: Enabled
  6. Advanced -> PCIPnP -> Plug And Play O/S: Yes
  7. Power -> ACPI 2.0 Support: Enabled
  8. Power -> ACPI APIC support: Enabled
  9. Tools -> Express Gate: Disabled

You may notice that, with the above settings and 4GB installed RAM, POST will report “RAM:  3072 OK“.  This is because the BIOS is allocating ~1GB RAM to the GPU.  Linux will also report 3072MB of RAM.  This is normal.

Configure DHCP for PXE / Network Booting

You will need to configure your DHCP server for PXE / Network booting.  This will allow your front end to obtain an IP address and load the appropriate files to allow the system to boot the operating system over your network.  While the instructions below are for PFSense, the setup should be very similar for other systems.

  1. Services -> DHCP Server
  2. Click “Advanced – Show Network Booting”
  3. Check “Enable Network Booting”
  4. Enter the IP address of your file server into the first box.
  5. Enter “PXEClient/pxelinux.0″ into the second box.
  6. Click “Save”

Setup FreeBSD

I use FreeBSD for my home file / database / web / whatever server.  FreeBSD has an amazing technology called ZFS.  ZFS is a combined file system and logical volume manager which allows you to dynamically create filing systems, snapshots, rollbacks, and a whole slew of other neat things.  If you’re generally a GNU/Linux guy and am used to using LVM  and / or MDADM, I recommend you try out FreeBSD with ZFS.

ANYWAY, Here we will setup our tftp server (tftpd) and share out some folders with NFS.  While you do not need to use a FreeBSD backend, this tutorial assumes that you are, and that you have already created your filing systems.

Setup NFS shares

The home for our XBMC install will be /tank/xbmc.  tftpd will serve files from /tftpboot.  Our media will be stored in /tank/media.

  1. echo ‘nfs_server_enable=”YES”‘ >> /etc/rc.conf
  2. echo ‘rpcbind_enable=”YES”‘ >> /etc/rc.conf
  3. echo ‘mountd_enable=”YES”‘ >> /etc/rc.conf
  4. echo ‘mountd_flags=”-r”‘ >> /etc/rc.conf
  5. vi /etc/exports
    /tank/xbmc -maproot=root
    /tank/media -maproot=root
  6. /etc/rc.d/mountd start
    Protip: If you are using FreeBSD 7.3 or 8.1, you may use “service” in place of “/etc/rc.d”, so the above command would look like “service nfsd start”
  7. /etc/rc.d/rpcbind start
  8. /etc/rc.d/nfsd start

Executing “showmount -e” should now display your NFS-exported folders.

Setup tftp server

If you recall in the previous step of setting up the PXE server, we had to enter a path to “PXEClient/pxelinux.0″.  This file is served via tftp and is what instructs the PXE-booting (in this case, our HTPC) system to load the appropriate GNU/Linux files and correctly boot.

  1. Edit vi /etc/inetd.conf and uncomment the following line:
    tftp    dgram   udp     wait    root    /usr/libexec/tftpd      tftpd -l -s /tftpboot
  2. echo ‘ftpd_enable=”YES”‘ >> /etc/rc.conf
  3. Start ftpd
    /etc/rc.d/ftpd start

You should now be able to test that your tftp server is running by executing “ftp localhost” from the command line.

Configure tftp files

When we are finished, the directory structure of our tftp server will look like this:

cosmos# ll -RF /tftpboot/
total 2
drwxr-xr-x  3 root  wheel  512 Aug  7 10:25 PXEClient/

/tftpboot/PXEClient:
total 11730
-rw-r--r--  1 root  wheel  8047310 Aug  7 10:25 initrd.img
-rw-r--r--  1 root  wheel    14776 Jan 22  2010 pxelinux.0
drwxr-xr-x  2 root  wheel      512 Jan  5  2002 pxelinux.cfg/
-rw-r--r--  1 root  wheel  3892032 Aug  7 10:25 vmlinuz

/tftpboot/PXEClient/pxelinux.cfg:
total 2
-rw-r--r--  1 root  wheel  139 Aug 13 23:31 default
  1. mkdir -p /tftpboot/PXEClient
  2. cd /tftpboot/PXEClient
  3. fetch http://archive.ubuntu.com/ubuntu/dists/karmic/main/installer-amd64/current/images/netboot/pxelinux.0
  4. mkdir pxelinux.cfg
  5. cd pxelinux.cfg
  6. vi default
    LABEL linux
    KERNEL vmlinuz
    APPEND xbmc=autostart root=/dev/nfs initrd=initrd.img vga=788 nfsroot=192
    .168.9.10:/tank/xbmc ip=dhcp ro

Be sure to replace 192.168.9.10 with the IP address of your FreeBSD Server!

Install XBMC-Live

A hard disk is required for this step.  After the system is installed, we’ll be copying the files off to our NFS server, at which point you can remove the hard disk and disable the controller.  If you have ever installed Ubuntu, the XBMC-Live install will seem very familiar.  If you haven’t, the install will seem very easy!

  1. Download and burn CD.
    I am using the xbmc-9.11-live-repack version for this tutorial, which is linked from the “Live” link at http://xbmc.org/download/
  2. Boot from CD
  3. From CD menu, choose “Install XBMCLive to Disk
    We must first install to the hard disk.  Later we will move the system to a NFS share for diskless PXE booting.
  4. Follow the prompts to progress through setup…
  5. When you reach the partition disks part of the setup, choose “Guided – use entire disk
    The disk layout does not matter as it is only temporary.
  6. Choose “Yes” to “Write the changes to disks?”.
  7. Create your user account.  You’ll be using this account if / when you need to SSH into your media center for remote (read: couch) administration.
  8. Remove CD and reboot

At this point, XBMC should boot and you should have a fully-functional HTPC.  The next step is to copy the operating system to a remote server so that we can remove the local hard drive and network boot.

Copy XBMC to Server

This part of this how-to is based off of the guide at http://hype-o-thetic.com/2009/09/20/diskless-htpc-using-dd-wrt-pxe-xbmc-and-freenas-tftp-nfs/, with some modifications.

Copy the files to the server

Perform this step on the HTPC.

  1. sudo -s
  2. apt-get update
  3. apt-get install nfs-common portmap
  4. mkdir /mnt/tmp
  5. mkdir /mnt/nfs
  6. mount /dev/sda1 /mnt/tmp
  7. mount 192.168.9.10:/tank/xbmc /mnt/nfs
    Make sure to change the IP address!
  8. cp -a /mnt/tmp/* /mnt/nfs/
    This will take up to 10 or so minutes, so be patient.

Change root directory

Perform this step on the HTPC.

  1. chroot /mnt/nfs
  2. mount -t proc proc proc
    This command may cause your SSH / terminal session to ‘hang’.  That is OK – just open a new SSH or terminal connection to the box and proceed.

Edit some files

Perform this step on the HTPC

  1. chroot /mnt/nfs
  2. Change BOOT=local to BOOT=nfs
    vi etc/initramfs-tools/initramfs.conf
  3. Updated initrd.img
    update-initramfs -u
  4. Edit etc/fstab to point to the new NFS root.
    1. vi /etc/fstab
      Replace the “/” line with this one:
    2. /dev/nfs    /    nfs    defaults    0    0

Copy the new kernel image files to the tftp server

Perform this step on the FreeBSD server

  1. cp /tank/xbmc/vmlinuz /tftpboot/PXEClient/
  2. cp /tank/xbmc/initram.img /tftpboot/PXEClient/

Now go ahead and turn off your frontend, remove the hard disk, and set your network card to be the first boot device.  With any luck, XBMC should boot right up, over the network!

Configure XBMC

The first thing that I recommend you do is to snapshot your system so that you can easily revert back in the future.  I have had bad experiences in upgrading xbmc and the underlying OS and have been fortunate enough to have snapshots to roll back to.

Snapshot your OS

Perform this step on the FreeBSD server

  1. snapshot -r tank/xbmc@postinstall

Mount NFS Shares

We have already setup our NFS shares on the FreeBSD box – now we will mount them on our frontend so that we can access our media content.  This step can be performed either by SSH to the frontend, or by opening a terminal (after XBMC boots up, press CTRL+ALT+F2).

  1. sudo -s
  2. mkdir /media/movies
  3. vi /etc/fstab
    192.168.9.10:/tank/media        /media/movies   nfs     default 0       0
  4. mount -a

Caveats

While the majority of this setup goes without issue, there are a couple things to address.

smbus error

While booting, or in dmesg, you will see a message similar to “nForce2_smbus conflicts with ACPI region.”  The proposed fix for this is to add “acpi_enforce_resources=lax” as a kernel boot parameter.  While this will change the error message, it will not fix the problem.  I am working on a fix for this.

Fan

Even with Hyper Threading disabled, the passively-cooled CPU still runs very hot.  You may or may not require a fan.  I screwed a 40mm fan to the heat sink, which did the job.

In closing,

This tutorial was written in the hope that it will help others, as the information for such a setup is spread around many places, and also requires a lot of trial-and-error.  If you find that I have overlooked something, or if you have any ideas for improvement, feel free to leave some feedback!

Four reasons why DuckDuckGo is better than Google at Search

In light of the recent concern over Google’s now apparent stance on privacy, which is reflected in both Eric Schmidt being quoted as saying “If you have something that you don’t want anyone to know, maybe you shouldn’t be doing it in the first place”, and in their Verizon-Google Net Neutrality Deal, I think now is a better time than ever to consider the possibility that there are search engines other than Google out there.

One of them is DuckDuckGo.  I have been using DuckDuckGo as my primary search engine for over two weeks and I can honestly say that for all of my web searching, Google is being outperformed.

Why should you try DuckDuckGo?

  • Zero-click info — useful info above the links.
  • Privacy — we do not track you. Google does.
  • Goodies — keyboard shortcuts, answers & more
  • Less spam & ads — no ads above results.
  • Official sites — labeled and on top.
  • Customization — change the fonts and much more.
  • Search other sites — check out !bang syntax.

While these are all great, I want to highlight my biggest reasons for using DuckDuckGo.

Privacy First

DuckDuckGo does not track you.  Google does.  The creator of DuckDuckGo, Gabriel Weinberg, puts it clearly: “By default, DuckDuckGo does not collect or share personal information. That is our privacy policy in a nutshell.”  DuckDuckGo brings the issue or privacy to the forefront, offering it by default.

Google tracks everything that you do.  They track your search results, your web browsing history, they analyze your email to display targeted advertisement.  They have tracked your WiFi signals, flu outbreaks and earthquake reports.  And this touches on a good point – that tracking is not always a bad thing.  However, when they’re tracking and analyzing your personal searches and emails, it is.

While both DuckDuckGo and Google offer SSL encryption, which will keep your searches private from anyone in the middle – say your ISP or the rouge employee with a packet sniffer – DuckDuckGo also offers a way to prevent your search results from being shared with sites that you visit, which is enabled by default.

Feature-Rich

DuckDuckGo has an awesome number of features, not only via it’s !bang syntax, but also in the way that it displays results.  Need a random password?  Search for “pw”.  Want to know your IP address?  Search for “ip”.  A much more complete list of features can be found on their goodies page.

Google’s search settings page pales in comparison to DuckDuckGo’s.  With DuckDuckGo, you can customize your privacy settings, look and feel settings, result settings and interface settings.  You can even use URL parameters instead of cookies for your settings.

Time is money, friend

DuckDuckGo is optimized for speed.  If you’re looking for the characters from Stargate, why not have your search engine give you the results, instead of simply linking you to a page with the results?

Compare the following images:

With DuckDuckGo, you do not have to go to the information – it comes to you.

Look, Ma – no adds.

Feedback

DuckDuckGo listens to your feedback.  While few companies should cater to the needs of every client, it is nice to know that requests are not falling on deaf ears.  They even have a nice, big “Give Feedback” image on their main search page.

So why not give DuckDuckGo a try?  Wouldn’t you like to know what an advertisement-free, private web experience feels like?

XBMC HTPC

A few months back, I finally got around to setting up a proper HTPC solution.  I originally planned on using MythTV, but with only one frontend, and no cable subscription, I found XBMC to be more appropriate, and ultimately went that route.  I had an extra small form factor core2duo with HDMI lying around, so I choose that for my hardware.  My setup went something like this:

  1. Installed XBMC-Live onto the HTPC
  2. Updated the system
  3. Copied / over to a NFS share
  4. Removed hard drive
  5. Netboot from NFS share

And this all works pretty well.  However, the box has an intel chipset, and a lot of trouble playing back 1080p content.  So two days ago, I ordered a new motherboard, 4GB RAM, and a new case, for a new frontend that I plan on building.  And the parts are Out for Delivery as of 9AM this morning.

So over the next few days and this weekend, I am going to create a writeup for a netboot XBMC system.  The backend (where the system and media files reside) will be a FreeBSD 8.1 box.

Stay tuned.

UPDATE: I’ve written my tutorial.

I don’t need a bag

This seems to be one of my most commonly said phrases.  I was at Walmart earlier today to buy a new griddle and a bottle of laundry detergent.  Two items, both with strong, durable handles that were designed for moving, carrying or otherwise transporting said objects.  How many arms do I have? 2.  Sounds like a match made in heaven, no?

So as I am checking out, the cashier proceeds to double bag the detergent, and single bag the griddle.  Three unneeded bags for 2 items?

“I don’t need a bag”, though apparently I did need a dirty look.

Return top