diff --git a/library/Icinga/Application/WebInstaller.php b/library/Icinga/Application/WebInstaller.php
index 736e74cd9..e09b58d55 100644
--- a/library/Icinga/Application/WebInstaller.php
+++ b/library/Icinga/Application/WebInstaller.php
@@ -8,6 +8,7 @@ use Exception;
 use Zend_Config;
 use PDOException;
 use Icinga\Web\Setup\DbTool;
+use Icinga\Application\Icinga;
 use Icinga\Application\Config;
 use Icinga\Web\Setup\Installer;
 use Icinga\Config\PreservingIniWriter;
@@ -49,6 +50,17 @@ class WebInstaller implements Installer
     {
         $success = true;
 
+        if (isset($this->pageData['setup_db_resource']) && ! $this->pageData['setup_db_resource']['skip_validation']) {
+            try {
+                $this->setupDatabase();
+            } catch (Exception $e) {
+                $this->log(sprintf(t('Failed to set up the database: %s'), $e->getMessage()), false);
+                return false; // Bail out as early as possible as not being able to setup the database is fatal
+            }
+
+            $this->log(t('The database has been successfully set up!'));
+        }
+
         $configIniPath = Config::resolvePath('config.ini');
         try {
             $this->writeConfigIni($configIniPath);
@@ -189,6 +201,159 @@ class WebInstaller implements Installer
         $writer->write();
     }
 
+    /**
+     * Setup the database
+     */
+    protected function setupDatabase()
+    {
+        $resourceConfig = $this->pageData['setup_db_resource'];
+        if (isset($this->pageData['setup_database_creation'])) {
+            $resourceConfig['username'] = $this->pageData['setup_database_creation']['username'];
+            $resourceConfig['password'] = $this->pageData['setup_database_creation']['password'];
+        }
+
+        $db = new DbTool($resourceConfig);
+        if ($resourceConfig['db'] === 'mysql') {
+            $this->setupMysqlDatabase($db);
+        } elseif ($resourceConfig['db'] === 'pgsql') {
+            $this->setupPgsqlDatabase($db);
+        }
+    }
+
+    /**
+     * Setup a MySQL database
+     *
+     * @param   DbTool      $db     The database connection wrapper to use
+     *
+     * @todo    Escape user input or make use of prepared statements!
+     */
+    private function setupMysqlDatabase(DbTool $db)
+    {
+        try {
+            $db->connectToDb();
+            $this->log(sprintf(
+                t('Successfully connected to existing database "%s"...'),
+                $this->pageData['setup_db_resource']['dbname']
+            ));
+        } catch (PDOException $e) {
+            $db->connectToHost();
+            $this->log(sprintf(
+                t('Creating new database "%s"...'),
+                $this->pageData['setup_db_resource']['dbname']
+            ));
+            $db->exec('CREATE DATABASE ' . $this->pageData['setup_db_resource']['dbname']);
+            $db->reconnect($this->pageData['setup_db_resource']['dbname']);
+        }
+
+        $loginIdent = "'" . $this->pageData['setup_db_resource']['username'] . "'@'" . Platform::getFqdn() . "'";
+        if (false === array_search($loginIdent, $db->listLogins())) {
+            $this->log(sprintf(
+                t('Creating login "%s"...'),
+                $this->pageData['setup_db_resource']['username']
+            ));
+            $db->exec(
+                "CREATE USER $loginIdent IDENTIFIED BY '" .
+                $this->pageData['setup_db_resource']['password'] . "'"
+            );
+        } else {
+            $this->log(sprintf(
+                t('Login "%s" already exists...'),
+                $this->pageData['setup_db_resource']['username']
+            ));
+        }
+
+        $diff = array_diff(array('account', 'preference'), $db->listTables());
+        if (empty($diff)) {
+            $this->log(t('Database schema already exists...'));
+        } else {
+            $this->log(t('Creating database schema...'));
+            $db->import(Icinga::app()->getApplicationDir() . '/../etc/schema/mysql.sql');
+        }
+
+        $privileges = array('SELECT', 'INSERT', 'UPDATE', 'DELETE', 'EXECUTE', 'CREATE TEMPORARY TABLES');
+        if ($db->checkPrivileges(array_merge($privileges, array('GRANT OPTION')))) {
+            $this->log(sprintf(
+                t('Granting required privileges to login "%s"...'),
+                $this->pageData['setup_db_resource']['username']
+            ));
+            $db->exec(sprintf(
+                "GRANT %s ON %s.* TO %s",
+                join(',', $privileges),
+                $this->pageData['setup_db_resource']['dbname'],
+                $loginIdent
+            ));
+        }
+    }
+
+    /**
+     * Setup a PostgreSQL database
+     *
+     * @param   DbTool      $db     The database connection wrapper to use
+     *
+     * @todo    Escape user input or make use of prepared statements!
+     */
+    private function setupPgsqlDatabase(DbTool $db)
+    {
+        try {
+            $db->connectToDb();
+            $this->log(sprintf(
+                t('Successfully connected to existing database "%s"...'),
+                $this->pageData['setup_db_resource']['dbname']
+            ));
+        } catch (PDOException $e) {
+            $db->connectToHost();
+            $this->log(sprintf(
+                t('Creating new database "%s"...'),
+                $this->pageData['setup_db_resource']['dbname']
+            ));
+            $db->exec('CREATE DATABASE ' . $this->pageData['setup_db_resource']['dbname']);
+            $db->reconnect($this->pageData['setup_db_resource']['dbname']);
+        }
+
+        if (false === array_search($this->pageData['setup_db_resource']['username'], $db->listLogins())) {
+            $this->log(sprintf(
+                t('Creating login "%s"...'),
+                $this->pageData['setup_db_resource']['username']
+            ));
+            $db->exec(sprintf(
+                "CREATE USER %s WITH PASSWORD '%s'",
+                $this->pageData['setup_db_resource']['username'],
+                $this->pageData['setup_db_resource']['password']
+            ));
+        } else {
+            $this->log(sprintf(
+                t('Login "%s" already exists...'),
+                $this->pageData['setup_db_resource']['username']
+            ));
+        }
+
+        $diff = array_diff(array('account', 'preference'), $db->listTables());
+        if (empty($diff)) {
+            $this->log(t('Database schema already exists...'));
+        } else {
+            $this->log(t('Creating database schema...'));
+            $db->import(Icinga::app()->getApplicationDir() . '/../etc/schema/pgsql.sql');
+        }
+
+        $privileges = array('SELECT', 'INSERT', 'UPDATE', 'DELETE');
+        if ($db->checkPrivileges(array_merge($privileges, array('GRANT OPTION')))) {
+            $this->log(sprintf(
+                t('Granting required privileges to login "%s"...'),
+                $this->pageData['setup_db_resource']['username']
+            ));
+            $db->exec(sprintf(
+                "GRANT %s ON TABLE account TO %s",
+                join(',', $privileges),
+                $this->pageData['setup_db_resource']['username']
+            ));
+            $db->exec(sprintf(
+                "GRANT %s ON TABLE preference TO %s",
+                join(',', $privileges),
+                $this->pageData['setup_db_resource']['username']
+            ));
+        }
+    }
+
     /**
      * @see Installer::getSummary()
      */
diff --git a/library/Icinga/Web/Setup/DbTool.php b/library/Icinga/Web/Setup/DbTool.php
index a3ded9707..982c6bc67 100644
--- a/library/Icinga/Web/Setup/DbTool.php
+++ b/library/Icinga/Web/Setup/DbTool.php
@@ -9,6 +9,7 @@ use PDOException;
 use LogicException;
 use Zend_Db_Adapter_Pdo_Mysql;
 use Zend_Db_Adapter_Pdo_Pgsql;
+use Icinga\Util\File;
 use Icinga\Exception\ConfigurationError;
 
 /**
@@ -129,6 +130,18 @@ class DbTool
         }
     }
 
+    /**
+     * Reestablish a connection with the database or just the server by omitting the database name
+     *
+     * @param   string  $dbname     The name of the database to connect to
+     */
+    public function reconnect($dbname = null)
+    {
+        $this->pdoConn = null;
+        $this->zendConn = null;
+        $this->connect($dbname);
+    }
+
     /**
      * Initialize Zend database adapter
      *
@@ -228,6 +241,35 @@ class DbTool
         }
     }
 
+    /**
+     * Execute a SQL statement and return the affected row count
+     *
+     * @param   string  $statement  The statement to execute
+     *
+     * @return  int
+     */
+    public function exec($statement)
+    {
+        return $this->pdoConn->exec($statement);
+    }
+
+    /**
+     * Import the given SQL file
+     *
+     * @param   string  $filepath   The file to import
+     */
+    public function import($filepath)
+    {
+        $file = new File($filepath);
+        $content = join(PHP_EOL, iterator_to_array($file)); // There is no fread() before PHP 5.5 :(
+
+        foreach (explode(';', $content) as $statement) {
+            if (($statement = trim($statement)) !== '') {
+                $this->exec($statement);
+            }
+        }
+    }
+
     /**
      * Return whether the given privileges were granted
      *
@@ -250,4 +292,28 @@ class DbTool
         $this->assertConnectedToDb();
         return $this->zendConn->listTables();
     }
+
+    /**
+     * Return a list of all available database logins
+     *
+     * @return  array
+     */
+    public function listLogins()
+    {
+        $users = array();
+
+        if ($this->config['db'] === 'mysql') {
+            $query = $this->pdoConn->query('SELECT DISTINCT grantee FROM information_schema.user_privileges');
+            foreach ($query->fetchAll() as $row) {
+                $users[] = $row['grantee'];
+            }
+        } elseif ($this->config['db'] === 'pgsql') {
+            $query = $this->pdoConn->query('SELECT usename FROM pg_catalog.pg_user');
+            foreach ($query->fetchAll() as $row) {
+                $users[] = $row['usename'];
+            }
+        }
+
+        return $users;
+    }
 }