diff --git a/deps.nix b/deps.nix
index 18c1f1d3..4a437d66 100644
--- a/deps.nix
+++ b/deps.nix
@@ -1,37 +1,38 @@
-{pkgs}:
+{ pkgs }:
 
 with pkgs;
 
-[ perlPackages.CatalystDevel
-  perlPackages.CatalystPluginSessionStoreFastMmap
-  perlPackages.CatalystPluginStackTrace
+[ perlPackages.CatalystAuthenticationStoreDBIxClass
+  perlPackages.CatalystPluginAccessLog
   perlPackages.CatalystPluginAuthorizationRoles
   perlPackages.CatalystPluginSessionStateCookie
-  perlPackages.CatalystPluginAccessLog
-  perlPackages.CatalystAuthenticationStoreDBIxClass
-  perlPackages.CatalystViewTT
+  perlPackages.CatalystPluginSessionStoreFastMmap
+  perlPackages.CatalystPluginStackTrace
   perlPackages.CatalystViewDownload
   perlPackages.CatalystViewJSON
+  perlPackages.CatalystViewTT
   perlPackages.CatalystXScriptServerStarman
-  perlPackages.XMLSimple
-  perlPackages.IPCRun
-  perlPackages.IOCompress
-  perlPackages.Readonly
+  perlPackages.CryptRandPasswd
   perlPackages.DBDPg
   perlPackages.DBDSQLite
-  perlPackages.EmailSender
-  perlPackages.TextTable
-  perlPackages.TextDiff
-  perlPackages.FileSlurp
-  perlPackages.NetTwitterLite
-  perlPackages.PadWalker
   perlPackages.DataDump
-  perlPackages.JSONXS
   perlPackages.DateTime
   perlPackages.DigestSHA1
-  perlPackages.CryptRandPasswd
-  perlPackages.TestMore
-  perlPackages.SysHostnameLong
+  perlPackages.EmailSender
+  perlPackages.FileSlurp
+  perlPackages.IOCompress
+  perlPackages.IPCRun
+  perlPackages.JSONXS
+  perlPackages.NetTwitterLite
+  perlPackages.PadWalker
+  perlPackages.CatalystDevel
+  perlPackages.Readonly
+  perlPackages.SQLSplitStatement
   perlPackages.Starman
+  perlPackages.SysHostnameLong
+  perlPackages.TestMore
+  perlPackages.TextDiff
+  perlPackages.TextTable
+  perlPackages.XMLSimple
   nixUnstable
 ]
diff --git a/doc/manual/installation.xml b/doc/manual/installation.xml
index 44280524..3234efc7 100644
--- a/doc/manual/installation.xml
+++ b/doc/manual/installation.xml
@@ -73,21 +73,23 @@
   <section>
     <title>Installation</title>
 
+<!--
     <para>
       Hydra can be installed using Nixpkgs:
 
       <screen>
-nix-env -Ai hydra -f /path/to/nixpkgs</screen>
+nix-env -f /path/to/nixpkgs -iA hydra</screen>
 
       This makes the tools available in your Nix user environment,
       <literal>$HOME/.nix-profile</literal> by default.
     </para>
+-->
 
     <para>
-      Alternatively, the latest development snapshot can be installed
+      The latest development snapshot of Hydra can be installed
       by visiting the URL <link
       xlink:href="http://hydra.nixos.org/view/hydra/unstable"><literal>http://hydra.nixos.org/view/hydra/unstable</literal></link>
-      and use the one-click install available at one of the build
+      and using the one-click install available at one of the build
       pages. You can also install Hydra through the channel by
       performing the following commands:
 
@@ -101,8 +103,10 @@ nix-env -i hydra</screen>
       Command completion should reveal a number of command-line tools from Hydra:
 
           <screen>
-hydra-build      hydra-evaluator     hydra-server
-hydra-eval-jobs  hydra-queue-runner  hydra-update-gc-roots</screen>
+hydra-build      hydra-init          hydra-update-gc-roots
+hydra-eval-jobs  hydra-queue-runner  
+hydra-evaluator  hydra-server
+</screen>
     </para>
   </section>
 
@@ -116,24 +120,46 @@ hydra-eval-jobs  hydra-queue-runner  hydra-update-gc-roots</screen>
 
     <para>
       To setup a PostgreSQL database with <emphasis>hydra</emphasis>
-      as database name and user name, issue the following commands:
+      as database name and user name, issue the following commands on
+      the PostgreSQL server:
 
       <screen>
-createdb hydra
-echo "CREATE USER hydra WITH PASSWORD '&lt;your-password&gt;' ;" | psql hydra
-cat $prefix/share/hydra/sql/hydra-postgresql.sql | psql hydra
-echo "GRANT ALL ON DATABASE hydra TO hydra;" | psql hydra</screen>
+createuser -S -D -R -P hydra
+createdb -O hydra hydra</screen>
 
       Note that <emphasis>$prefix</emphasis> is the location of Hydra
       in the nix store.
     </para>
 
     <para>
-      For SQLite, the following command is all it takes to create the
-      database:
+      Hydra uses an environment variable to know which database should
+      be used, and a variable which point to a location that holds
+      some state. To set these variables for a PostgreSQL database,
+      add the following to the file <filename>~/.profile</filename> of
+      the user running the Hydra services.
 
       <screen>
-cat $prefix/share/hydra/sql/hydra-sqlite.sql | sqlite3 /path/to/hydra.sqlite</screen>
+export HYDRA_DBI="dbi:Pg:dbname=hydra;host=dbserver.example.org;user=hydra;"
+export HYDRA_DATA=/var/lib/hydra</screen>
+
+      You can provide the username and password in the file
+      <filename>~/.pgpass</filename>, e.g.
+
+      <screen>
+dbserver.example.org:*:hydra:hydra:password</screen>
+
+      Make sure that the <emphasis>HYDRA_DATA</emphasis> directory
+      exists and is writable for the user which will run the Hydra
+      services.  For a SQLite database, the
+      <varname>HYDRA_DBI</varname> should be set to something like
+      <literal>dbi:SQLite:/path/to/hydra.sqlite</literal>
+    </para>
+
+    <para>
+      Having set these environment variables, you can now initialise
+      the database by doing:
+      <screen>
+hydra-init</screen>
     </para>
 
     <para>
@@ -148,23 +174,17 @@ echo "INSERT INTO UserRoles(userName, role) values('root', 'admin');" | psql hyd
       /path/to/hydra.sqlite</command>.
     </para>
 
-    <para>
-      Hydra uses an environment variable to know which database should
-      be used, and a variable which point to a location that holds
-      some state. To set these variables for a PostgreSQL database,
-      add the following to the <filename>.profile</filename> of the
-      user running the Hydra services.
+  </section>
 
+  <section>
+    <title>Upgrading</title>
+
+    <para>If you're upgrading Hydra from a previous version, you
+    should do the following to perform any necessary database schema migrations:
       <screen>
-export HYDRA_DBI="dbi:Pg:dbname=hydra;host=localhost;"
-export HYDRA_DATA=/var/lib/hydra</screen> 
-
-      Make sure that the <emphasis>HYDRA_DATA</emphasis> directory
-      exists and is writable for the user which will run the Hydra
-      services.  For a SQLite database, the
-      <varname>HYDRA_DBI</varname> should be set to something like
-      <literal>dbi:SQLite:/path/to/hydra.sqlite</literal>
+hydra-init</screen>
     </para>
+
   </section>
 
   <section>
diff --git a/src/lib/Hydra/Helper/Nix.pm b/src/lib/Hydra/Helper/Nix.pm
index d230bce3..2a699455 100644
--- a/src/lib/Hydra/Helper/Nix.pm
+++ b/src/lib/Hydra/Helper/Nix.pm
@@ -8,7 +8,7 @@ use Hydra::Helper::CatalystUtils;
 
 our @ISA = qw(Exporter);
 our @EXPORT = qw(
-    getHydraPath getHydraDBPath openHydraDB getHydraConf txn_do
+    getHydraPath getHydraHome getHydraDBPath openHydraDB getHydraConf txn_do
     registerRoot getGCRootsDir gcRootFor
     getPrimaryBuildsForView
     getPrimaryBuildTotal
@@ -21,6 +21,13 @@ sub getHydraPath {
     return $dir;
 }
 
+
+sub getHydraHome {
+    my $dir = $ENV{"HYDRA_HOME"} or die "The HYDRA_HOME directory does not exist!\n";
+    return $dir;
+}
+
+
 sub getHydraConf {
     my $conf = $ENV{"HYDRA_CONFIG"} || (getHydraPath . "/hydra.conf");
     die "The HYDRA_CONFIG file ($conf) does not exist!\n" unless -f $conf;
diff --git a/src/script/hydra-init b/src/script/hydra-init
new file mode 100755
index 00000000..a0cbe146
--- /dev/null
+++ b/src/script/hydra-init
@@ -0,0 +1,58 @@
+#! /var/run/current-system/sw/bin/perl -w
+
+use strict;
+use Hydra::Schema;
+use Hydra::Helper::Nix;
+use File::Slurp;
+use SQL::SplitStatement;
+use List::Util qw(max);
+
+my $db = openHydraDB;
+my $dbh = $db->storage->dbh;
+$dbh->{RaiseError} = 1;
+
+my $home = getHydraHome;
+
+my $sql_splitter = SQL::SplitStatement->new;
+
+# Figure out the target schema version.
+my $maxSchemaVersion = max (map { /.*\/upgrade-(\d.*)\.sql/; $1 } (glob "$home/sql/upgrade-[0-9]*.sql")) || 1;
+
+# Check whether the database has been initialised.  If not, load the
+# schema.
+my @tables = $dbh->tables;
+if (! grep { /SchemaVersion/i } @tables) {
+    print STDERR "initialising the Hydra database schema...\n";
+    my $schema = read_file(
+	$dbh->{Driver}->{Name} eq 'SQLite' ? "$home/sql/hydra-sqlite.sql" :
+	$dbh->{Driver}->{Name} eq 'Pg' ? "$home/sql/hydra-postgresql.sql" :
+	die "unsupported database type\n");
+    my @statements = $sql_splitter->split($schema);
+    eval {
+	$dbh->begin_work;
+	$dbh->do($_) foreach @statements;
+	$db->resultset('SchemaVersion')->create({version => $maxSchemaVersion});
+	$dbh->commit;
+    };
+    die "schema initialisation failed: $@\n" if $@;
+    exit 0;
+}
+
+# Get the current schema version.
+my @versions = $db->resultset('SchemaVersion')->all;
+die "couldn't get Hydra schema version!" if scalar @versions != 1;
+my $schemaVersion = $versions[0]->version;
+
+for (my $n = $schemaVersion; $n < $maxSchemaVersion; $n++) {
+    my $m = $n + 1;
+    print STDERR "upgrading Hydra schema from version $n to $m\n";
+    my $schema = read_file("$home/sql/upgrade-$m.sql");
+    my @statements = $sql_splitter->split($schema);
+    eval {
+	$dbh->begin_work;
+	$dbh->do($_) foreach @statements;
+	$db->resultset('SchemaVersion')->update({version => $m});
+	$dbh->commit;
+    };
+    die "schema upgrade failed: $@\n" if $@;
+}
diff --git a/src/sql/Makefile.am b/src/sql/Makefile.am
index 5e374945..dafebba7 100644
--- a/src/sql/Makefile.am
+++ b/src/sql/Makefile.am
@@ -1,6 +1,6 @@
 EXTRA_DIST = hydra.sql hydra-postgresql.sql hydra-sqlite.sql
 
-sqldir = $(datadir)/hydra/sql
+sqldir = $(libexecdir)/hydra/sql
 nobase_sql_DATA = $(EXTRA_DIST)
 
 hydra-postgresql.sql: hydra.sql
diff --git a/src/sql/hydra.sql b/src/sql/hydra.sql
index 2993c2dd..6f4a8254 100644
--- a/src/sql/hydra.sql
+++ b/src/sql/hydra.sql
@@ -3,8 +3,6 @@ create table SchemaVersion (
     version       integer not null
 );
 
-insert into SchemaVersion (version) values (1);
-
 
 create table Users (
     userName      text primary key not null,
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e491353c..8ced1ed7 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -31,7 +31,7 @@ clean :
 check_SCRIPTS = db.sqlite repos
 
 db.sqlite : $(top_srcdir)/src/sql/hydra-sqlite.sql
-	sqlite3 db.sqlite <  $(top_srcdir)/src/sql/hydra-sqlite.sql
+	perl $(top_srcdir)/src/script/hydra-init
 
 repos : dirs git-repo hg-repo svn-repo svn-checkout-repo bzr-repo bzr-checkout-repo