diff --git a/Osstest.pm b/Osstest.pm
index a78728cd..a0c0339c 100644
--- a/Osstest.pm
+++ b/Osstest.pm
@@ -227,6 +227,7 @@ sub readglobalconfig () {
     $c{TftpTmpDir} ||= "$c{TftpPlayDir}tmp/";
 
     $c{TftpDiBase} ||= "$c{TftpPlayDir}debian-installer";
+    $c{TftpFreeBSDBase} ||= "$c{TftpPlayDir}freebsd-installer";
     $c{TftpDiVersion} ||= $c{ "TftpDiVersion_$c{DebianSuite}" } // 'current';
 
     $c{TftpGrubBase} ||= "$c{TftpPlayDir}grub";
diff --git a/Osstest/TestSupport.pm b/Osstest/TestSupport.pm
index 8c7078c5..4418f024 100644
--- a/Osstest/TestSupport.pm
+++ b/Osstest/TestSupport.pm
@@ -118,7 +118,7 @@ BEGIN {
                       await_webspace_fetch_byleaf create_webfile
                       file_link_contents get_timeout
                       setup_netboot_di setup_netboot_local host_netboot_file
-		      subst_netboot_template
+                      subst_netboot_template setup_netboot_memdisk
 
                       ether_prefix
 
@@ -1032,7 +1032,7 @@ sub selecthost ($) {
     $ho->{Tftp} = { };
     $ho->{Tftp}{$_} = $c{"Tftp${_}_${tftpscope}"} || $c{"Tftp${_}"}
         foreach qw(Path TmpDir PxeDir NetbootGroup PxeTemplates PxeTemplatesReal
-                   DiBase GrubBase
+                   DiBase GrubBase FreeBSDBase
                    NetGrubDir NetGrubTemplates NetGrubTemplatesReal
                    PxeGroup);
     $ho->{TftpNetbootGroup} //= $ho->{TftpPxeGroup}; # compatibility
@@ -2553,6 +2553,20 @@ default local
 END
 }
 
+sub setup_netboot_memdisk ($$) {
+    my ($ho, $img) = @_;
+    setup_netboot_bootcfg($ho, <<END);
+serial 0 $c{Baud}
+timeout 5
+label overwrite
+	menu label ^Overwrite
+	menu default
+	kernel memdisk
+	append initrd=$img
+default overwrite
+END
+}
+
 # uboot emulates pxelinux, so reuse BIOS stuff
 sub setup_netboot_di_uboot ($$$$$;%) { return &setup_netboot_di_bios; }
 sub setup_netboot_local_uboot ($) { return &setup_netboot_local_bios; }
diff --git a/ts-freebsd-host-install b/ts-freebsd-host-install
new file mode 100755
index 00000000..d59b66a4
--- /dev/null
+++ b/ts-freebsd-host-install
@@ -0,0 +1,259 @@
+#!/usr/bin/perl -w
+# This is part of "osstest", an automated testing framework for Xen.
+# Copyright (C) 2017 Citrix Inc.
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+# 
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+use strict qw(vars);
+use DBI;
+use POSIX;
+
+unshift @INC, qw(.);
+use Osstest;
+use Osstest::TestSupport;
+
+tsreadconfig();
+
+our %xopts;
+
+our ($whhost) = @ARGV;
+$whhost ||= 'host';
+our $ho= selecthost($whhost);
+exit 0 if $ho->{Flags}{'no-reinstall'};
+exit 0 if $ho->{SharedReady};
+
+our %timeout= qw(Sshd 1000);
+
+our @sets = qw(base.txz kernel.txz);
+
+our $image = $r{"freebsd_image"} ||
+             get_stashed("path_freebsd-image", $r{"freebsd_buildjob"});
+
+sub get_sets_path () {
+    my @paths;
+
+    foreach (@sets, "MANIFEST") {
+        my $path;
+
+        if (!defined($r{"freebsd_sets"})) {
+            # Get everything before the "." (ie: get base from base.txz)
+            my $stash_name = lc((split /\./)[0]);
+            $path = get_stashed("path_freebsd-$stash_name",
+                                $r{"freebsd_buildjob"});
+        } else {
+            $path = $r{"freebsd_sets"} . "/$_";
+        }
+
+        push @paths, { name => "$_", path => "$path" };
+    }
+
+    return @paths;
+}
+
+sub create_ssh_overlay () {
+    my $url = create_webfile($ho, "ssh.tar", sub {
+        my ($fh) = @_;
+        contents_make_cpio($fh, 'ustar',  "$c{OverlayLocal}/etc/ssh/");
+    });
+
+    return $url;
+}
+
+sub setup_netboot_installer () {
+    my $pxeimg = "$ho->{Tftp}{FreeBSDBase}/install-$ho->{Name}.img";
+    my $script = <<END;
+set -ex
+basedir=$ho->{Tftp}{Path}/$ho->{Tftp}{FreeBSDBase}/
+hash=`sha256sum $image|head -c 64`
+localpath="$r{arch}/\$hash/install.img";
+mkdir -p \$basedir
+(
+flock -x -w 600 200
+cd \$basedir
+if [ ! -f \$localpath ]; then
+    mkdir -p `dirname \$localpath`
+    cp $image \$localpath
+fi
+rm -f install-$ho->{Name}.img
+ln \$localpath install-$ho->{Name}.img
+for hash in `ls $r{arch}/`; do
+    count=`stat -c %h $r{arch}/\$hash/install.img`
+    if [ \$count -eq 1 ]; then
+        rm -rf $r{arch}/\$hash
+    fi
+done
+) 200<\$basedir
+END
+
+    logm("Executing:\n$script");
+    my $ret = system("/bin/bash -c '$script'");
+    $ret == 0 or die "Unable to setup netboot";
+
+    # Setup the pxelinux config file
+    logm("Booting from installer image at $pxeimg");
+    setup_netboot_memdisk($ho, $pxeimg);
+}
+
+sub install () {
+    my $authkeys = authorized_keys();
+    my $knownhosts = known_hosts();
+    my $sshd_keys_url = create_ssh_overlay();
+    my $disk_names = "ada0 da0 ad0";
+    my $installer_sets = join(" ", @sets);
+    my $target_sets = "/tmp/osstest_sets";
+    my $disk;
+    my $nic;
+
+    target_cmd_root($ho, 'chsh -s /bin/sh', 10);
+
+    logm("Trying to find a disk to install to");
+    $disk = target_cmd_output_root($ho, <<END, 30);
+for disk in $disk_names; do
+    if [ -c "/dev/\$disk" ]; then
+        echo \$disk
+        exit 0
+    fi
+done
+exit 1
+END
+    defined($disk) or die "Unable to find a valid disk";
+    logm("Using $disk as destination disk device");
+
+    logm("Trying to figure out primary nic device name");
+    $nic = target_cmd_output_root($ho, <<END, 30);
+nics=`ifconfig -l`
+for nic in \$nics; do
+    addr=`ifconfig \$nic inet|grep inet|awk {'print \$2'}`
+    if [ "\$addr" = "$ho->{Ip}" ]; then
+        echo \$nic
+        exit 0
+    fi
+done
+exit 1
+END
+    defined($nic) or die "Unable to find primary network interface";
+    logm("Using $nic as primary network interface");
+
+    logm("Uploading the install sets to the system");
+    target_cmd_root($ho, <<END, 30);
+mkdir -p $target_sets
+mount -o size=1G -t tmpfs tmpfs $target_sets
+END
+
+    foreach (get_sets_path()) {
+        target_putfile_root($ho, 600, $_->{path}, "$target_sets/$_->{name}");
+    }
+
+    logm("Creating the installer script");
+    target_cmd_root($ho, <<END, 60);
+        set -e
+        cat << ENDSCRIPT > installscript
+set -a
+BSDINSTALL_DISTDIR="$target_sets"
+ZFSBOOT_DISKS="$disk"
+DISTRIBUTIONS="$installer_sets"
+nonInteractive=1
+
+#!/bin/sh
+set -ex
+
+# Setup nic and sshd
+echo "ifconfig_$nic=DHCP" >> /etc/rc.conf
+echo "sshd_enable=YES" >> /etc/rc.conf
+
+# Disable sendmail
+echo "sendmail_enable=NONE" >> /etc/rc.conf
+
+# Set proxy for the pkg manager
+mkdir -p /usr/local/etc/
+cat << ENDPKG >> /usr/local/etc/pkg.conf
+pkg_env: { http_proxy = $c{HttpProxy} }
+default_always_yes: true
+assume_always_yes: true
+ENDPKG
+
+# Bootstap the package manager
+export HTTP_PROXY=$c{HttpProxy}
+export ASSUME_ALWAYS_YES=yes
+pkg update
+
+# Allow root user login and setup ssh keys
+chsh -s /bin/sh root
+echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config
+mkdir -p /root/.ssh
+cat << ENDKEYS > /root/.ssh/authorized_keys
+$authkeys
+ENDKEYS
+cat << ENDHOSTS > /root/.ssh/known_hosts
+$knownhosts
+ENDHOSTS
+
+# Fetch host keys
+fetch $sshd_keys_url -o - | tar -xf - -C /etc/ssh/
+# Set correct permissions
+chown root:wheel /etc/ssh/ssh_host_*_key*
+chmod 0600 /etc/ssh/ssh_host_*_key
+chmod 0644 /etc/ssh/ssh_host_*_key.pub
+
+# Add a osstest user
+pw useradd osstest -m
+chsh -s /bin/sh osstest
+mkdir -p /home/osstest/.ssh
+cat << ENDKEYS > /home/osstest/.ssh/authorized_keys
+$authkeys
+ENDKEYS
+cat << ENDHOSTS > /home/osstest/.ssh/known_hosts
+$knownhosts
+ENDHOSTS
+
+# Setup serial console
+printf "%s" "-h -S$c{Baud}" >> /boot.config
+cat << ENDBOOT >> /boot/loader.conf
+boot_serial="YES"
+comconsole_speed="$c{Baud}"
+console="comconsole"
+boot_verbose="YES"
+beastie_disable="YES"
+ENDBOOT
+
+ENDSCRIPT
+END
+
+    logm("Launch the installer");
+    target_cmd_root($ho, 'bsdinstall script installscript', 1200);
+
+    target_reboot($ho);
+
+    logm("Waiting for the host to boot");
+    await_tcp(get_timeout($ho,'reboot',$timeout{Sshd}), 14, $ho);
+
+    logm("FreeBSD installed succesfully");
+}
+
+# Switch off, setup PXE and switch on to the installer
+power_state($ho, 0);
+setup_netboot_installer();
+power_cycle_sleep($ho);
+power_state($ho, 1);
+
+# Wait for the host to finish booting
+logm("Waiting for the installer to boot");
+await_tcp(get_timeout($ho,'reboot',$timeout{Sshd}), 14, $ho);
+
+# Next boot will be from local disk
+setup_netboot_local($ho);
+
+# Proceed with the install
+install();
+
