diff --git a/j3vm3_full/Dockerfile b/j3vm3_full/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..c74fff5f8fee2ec23975df1e06493ef73bca63e5
--- /dev/null
+++ b/j3vm3_full/Dockerfile
@@ -0,0 +1,54 @@
+FROM php:5.6-apache
+MAINTAINER Reinhold Kainhofer <reinhold@kainhofer.com>
+
+# Enable Apache Rewrite Module
+RUN a2enmod rewrite
+
+RUN apt-get update
+
+# Install PHP extensions
+RUN apt-get install -y libpng12-dev libjpeg-dev zip unzip sudo \
+	&& docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr \
+	&& docker-php-ext-install gd
+RUN docker-php-ext-install mysqli
+
+VOLUME /var/www/html
+
+# Install MySQL (will only be started if needed)
+# RUN export DEBIAN_FRONTEND=noninteractive
+RUN echo "mysql-server-5.5 mysql-server/root_password password root" | debconf-set-selections
+RUN echo "mysql-server-5.5 mysql-server/root_password_again password root" | debconf-set-selections
+RUN DEBIAN_FRONTEND=noninteractive apt-get install -y mysql-server
+
+RUN apt-get install -y supervisor
+
+
+# Define Joomla version and expected SHA1 signature
+ENV J_VERSION 3.5.1
+ENV VM_VERSION 3.0.16
+ENV VM_DLDIR 1001
+ENV VM_MD5 3a445fc3db1cb0373359bf7a36aec4c8
+ENV VM_POSTFIX ""
+
+# Download package and extract to web volume
+RUN curl -o virtuemart.zip -SL http://dev.virtuemart.net/attachments/download/${VM_DLDIR}/VirtueMart${VM_VERSION}_Joomla_${J_VERSION}-Stable-Full_Package${VM_POSTFIX}.zip \
+	&& echo "$VM_MD5 *virtuemart.zip" | md5sum -c - \
+	&& mkdir /usr/src/virtuemart \
+	&& unzip virtuemart.zip -d /usr/src/virtuemart \
+	&& rm virtuemart.zip \
+	&& chown -R www-data:www-data /usr/src/virtuemart
+
+
+# Clean up the apt cache etc.
+RUN rm -rf /var/lib/apt/lists/* 
+
+# Copy init scripts and custom .htaccess
+RUN echo "[program:mysql]\ncommand=/usr/bin/pidproxy /run/mysqld/mysqld.pid /usr/bin/mysqld_safe \nautorestart=true\n" > /etc/supervisor/conf.d/mysql.conf.save
+COPY supervisord.conf /etc/supervisor/supervisord.conf
+COPY docker-entrypoint.sh /entrypoint.sh
+COPY makedb.php /makedb.php
+COPY install-joomla.php /usr/src/virtuemart/installation/install.php
+COPY install-joomla-extension.php /usr/src/virtuemart/cli/install-joomla-extension.php
+
+ENTRYPOINT ["/entrypoint.sh"]
+CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]
diff --git a/j3vm3_full/docker-entrypoint.sh b/j3vm3_full/docker-entrypoint.sh
new file mode 100755
index 0000000000000000000000000000000000000000..5fb3093fea6790843bfc905ef44a9677f5304586
--- /dev/null
+++ b/j3vm3_full/docker-entrypoint.sh
@@ -0,0 +1,163 @@
+#!/bin/bash
+
+set -e
+
+if [[ ! -e "/etc/opentools-docker-configured" ]]; then
+	# This docker container has not been configured yet, use the env variables 
+	# to set up the MYSQL server or linked container
+
+	# check if a MYSQL container is linked:
+	if [ -n "$MYSQL_PORT_3306_TCP" ]; then
+		if [ -z "$JOOMLA_DB_HOST" ]; then
+			JOOMLA_DB_HOST='mysql'
+		else
+			echo >&2 "warning: both JOOMLA_DB_HOST and MYSQL_PORT_3306_TCP found"
+			echo >&2 "  Connecting to JOOMLA_DB_HOST ($JOOMLA_DB_HOST)"
+			echo >&2 "  instead of the linked mysql container"
+		fi
+	fi
+	
+	# If the DB user is 'root' and no DB password is given, then use the MySQL root password env var
+	: ${JOOMLA_DB_USER:=root}
+	if [ "$JOOMLA_DB_USER" = 'root' ]; then
+			: ${JOOMLA_DB_PASSWORD:=$MYSQL_ENV_MYSQL_ROOT_PASSWORD}
+	fi
+	
+	# Check for local MySQL installation:
+	if [ -z "$JOOMLA_DB_HOST" ]; then
+		# No linked container and no explicit DB host => local MySQL installation
+		echo >&2 "Neither linked database container nor mysql dabase server host given. "
+		echo >&2 "   Assuming local installation. An instance of the MySQL server will be installed locally."
+		MYSQL_LOCAL=1
+		JOOMLA_DB_HOST="127.0.0.1"
+		if [ -z "${JOOMLA_DB_PASSWORD}" ]; then
+			JOOMLA_DB_PASSWORD='root'
+			echo >&2 "No MySQL root password given. Assuming password 'root'."
+		fi
+		echo >&2 "   Root password is ${JOOMLA_DB_PASSWORD}."
+		
+		# Temporarily start the mysql daemon to set up the database and shut it 
+		# down again (supervisord will start it at the very end)
+		echo "Starting local mysql server temporarily to set up the database..."
+		/usr/bin/mysqld_safe > /dev/null 2>&1 &
+		timeout=30
+		echo -n "Waiting for database server to accept connections"
+		while ! /usr/bin/mysqladmin --user=root --password=root status > /dev/null 2>&1; do
+			timeout=$(($timeout-1))
+			if [ $timeout -eq 0 ]; then
+				echo -e "\n Unable to connecto the database server. Aborting..."
+				exit 1
+			fi
+			echo -n "."
+			sleep 1
+		done
+		echo
+		mysqladmin --password=root password "${JOOMLA_DB_PASSWORD}"
+		
+		# enable mysqld in the supervisor config
+		cp /etc/supervisor/conf.d/mysql.conf.save /etc/supervisor/conf.d/mysql.conf
+	fi
+
+	
+	# Now set up the Database for Joomla/VirtueMart:
+	: ${JOOMLA_DB_NAME:=virtuemart}
+
+	if [ -z "$JOOMLA_DB_PASSWORD" ]; then
+		echo >&2 "error: missing required JOOMLA_DB_PASSWORD environment variable"
+		echo >&2 "  Did you forget to -e JOOMLA_DB_PASSWORD=... or link to a container?"
+		echo >&2
+		echo >&2 "  (Also of interest might be JOOMLA_DB_USER and JOOMLA_DB_NAME.)"
+		exit 1
+	fi
+	# Ensure the MySQL Database is created
+	php /makedb.php "$JOOMLA_DB_HOST" "$JOOMLA_DB_USER" "$JOOMLA_DB_PASSWORD" "$JOOMLA_DB_NAME"
+
+
+	# Now set up the Joomla/VirtueMart installation files in apache's directory:
+	if ! [ -e index.php -a -e libraries/cms/version/version.php ]; then
+		echo >&2 "Virtuemart/Joomla not found in $(pwd) - copying now..."
+
+		if [ "$(ls -A)" ]; then
+			echo >&2 "WARNING: $(pwd) is not empty - press Ctrl+C now if this is an error!"
+			( set -x; ls -A; sleep 10 )
+		fi
+
+		# extract the joomla installer
+		tar cf - --one-file-system -C /usr/src/virtuemart . | tar xf -
+		
+		# Some versions of the full installer hae an additional subdir in the ZIP file.
+		# Search for web.config.txt and mv everything from that directory to the webroot
+		if [ ! -e web.config.txt ]; then
+			for jmanifest in *web.config.txt; do 
+				jdir=$(dirname $jmanifest)
+				echo
+				mv $jdir/** .
+				rm -rf $jdir
+			done
+		fi
+
+		if [ -e htaccess.txt -a ! -e .htaccess ]; then
+			# NOTE: The "Indexes" option is disabled in the php:apache base image so remove it as we enable .htaccess
+			sed -r 's/^(Options -Indexes.*)$/#\1/' htaccess.txt > .htaccess
+			chown www-data:www-data .htaccess
+		fi
+
+		sed 's/default="localhost"/default="'$JOOMLA_DB_HOST'"/;
+			 s/\(db_user.*\)$/\1 default="'$JOOMLA_DB_USER'"/;
+			 s/\(db_pass.*\)$/\1 default="'$JOOMLA_DB_PASSWORD'"/;
+			 s/\(db_name.*\)$/\1 default="'$JOOMLA_DB_NAME'"/' installation/model/forms/database.xml > installation/model/forms/database.xml.new
+		mv installation/model/forms/database.xml.new installation/model/forms/database.xml
+
+		echo >&2 "Complete! Virtuemart has been successfully copied to $(pwd)"
+	fi
+
+	# Now run the joomla Installer:
+	: ${JOOMLA_ADMIN_USER:=admin}
+	: ${JOOMLA_ADMIN_PASSWORD:=admin}
+	: ${JOOMLA_ADMIN_EMAIL:=admin@example.com}
+	: ${JOOMLA_SITE_NAME:=Joomla Installation}
+	if [ -z "$JOOMLA_DB_PREFIX" ]; then
+		DBPREFIX="--dbprefix=\"${JOOMLA_DB_PREFIX}_\""
+	fi
+
+	echo "Installing Joomla/VirtueMart site $JOOMLA_SITE_NAME using the CLI and database host $JOOMLA_DB_HOST"
+	php ./installation/install.php --name "$JOOMLA_SITE_NAME" \
+		--admin-user "$JOOMLA_ADMIN_USER" --admin-pass "$JOOMLA_ADMIN_PASSWORD" --admin-email "$JOOMLA_ADMIN_EMAIL" \
+		--db-host "$JOOMLA_DB_HOST" --db-user "$JOOMLA_DB_USER" --db-pass "$JOOMLA_DB_PASSWORD" --db-name "$JOOMLA_DB_NAME" $DBPREFIX  && \
+		rm -rf "./installation/"
+	chown www-data:www-data configuration.php
+
+
+	for p in /usr/src/virtuemart/*.zip; do
+		echo "Installing package $p"
+		if [ -e "$p" ]; then
+			sudo -u www-data php ./cli/install-joomla-extension.php --package=$p
+		fi
+	done
+
+
+	if [ "$MYSQL_LOCAL" = "1" ]; then
+		# Local installation, so shut down MySQL again, will later be started through supervisord
+		echo "Shutting down temporary MySQL instance ..."
+		/usr/bin/mysqladmin --user=root --password="${JOOMLA_DB_PASSWORD}" shutdown
+	fi
+
+	echo >&2 "========================================================================"
+	echo >&2
+	echo >&2 "This server is now configured to run Joomla!"
+	echo >&2 "You will need the following database information to install Joomla:"
+	echo >&2 "Host Name: $JOOMLA_DB_HOST"
+	echo >&2 "Database Name: $JOOMLA_DB_NAME"
+	echo >&2 "Database Username: $JOOMLA_DB_USER"
+	echo >&2 "Database Password: $JOOMLA_DB_PASSWORD"
+	echo >&2 
+	echo >&2 "Joomla admin user: $JOOMLA_ADMIN_USER"
+	echo >&2 "Joomla admin password: $JOOMLA_ADMIN_PASSWORD"
+	echo >&2
+	echo >&2 "========================================================================"
+
+	# create the file to indicate this container has been configured:
+	touch /etc/opentools-docker-configured
+fi
+
+exec "$@"
diff --git a/j3vm3_full/install-joomla-extension.php b/j3vm3_full/install-joomla-extension.php
new file mode 100644
index 0000000000000000000000000000000000000000..d3e52f7dc0a2966c0c2de8663fc4a92b14b17c1b
--- /dev/null
+++ b/j3vm3_full/install-joomla-extension.php
@@ -0,0 +1,458 @@
+<?php
+/**
+ * @package    Joomla.Cli
+ *
+ * @copyright  Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.
+ * @license    GNU General Public License version 2 or later; see LICENSE.txt
+ *
+ * Command-line installer for Joomla! extensions. Please note that this must be called
+ * from the command line, not the web. For example:
+ *
+ *     /usr/bin/php /path/to/site/cli/install-extension.php
+ *
+ * This file is based on ideas from
+ * https://github.com/alikon/joomla-platform-examples/blob/master/Joomla%20CLI%20App/cli/jeicli.php
+ * and
+ * https://github.com/akeeba/vagrant/master/vagrant/files/joomla/install-joomla-extension.php
+ *
+ * Error codes returned from this script are:
+ * 0	Success
+ * 1	Missing parameters
+ * 2	Package file not found
+ * 3	Could not find download URL in the XML manifest
+ * 4	Could not download package
+ * 5	Could not extract package
+ * 250	Installation failed (package error, unwriteable directories, etc)
+ */
+
+// Set flag that this is a parent file.
+const _JEXEC = 1;
+
+// Load system defines
+if (file_exists(dirname(__DIR__) . '/defines.php'))
+{
+	require_once dirname(__DIR__) . '/defines.php';
+}
+
+if ( !defined('_JDEFINES'))
+{
+	define('JPATH_BASE', dirname(__DIR__));
+	require_once JPATH_BASE . '/includes/defines.php';
+}
+
+require_once JPATH_LIBRARIES . '/import.legacy.php';
+require_once JPATH_LIBRARIES . '/cms.php';
+
+// Load the configuration
+require_once JPATH_CONFIGURATION . '/configuration.php';
+
+/**
+ * A command line script to install extensions and extension updates from a folder, file, URL or update XML source
+ *
+ * @since  3.4
+ */
+class JoomlaExtensionInstallerCli extends JApplicationCli
+{
+	/**
+	 * The installation method. One of folder, package, url, web
+	 *
+	 * @var    null|string
+	 * @since  3.4
+	 */
+	private $installationMethod = null;
+
+	/**
+	 * The installation source. It can be a folder, file or URL depending on the installationMethod.
+	 *
+	 * @var    null|string
+	 * @since  3.4
+	 */
+	private $installationSource = null;
+
+	/**
+	 * The path to the temporary package file downloaded from the web. Only used with url and web installation methods.
+	 *
+	 * @var    null|string
+	 * @since  3.4
+	 */
+	private $temporaryPackage = null;
+
+	/**
+	 * The path to the temporary folder where the package is extracted. Not used with the folder installation method.
+	 *
+	 * @var    null|string
+	 * @since  3.4
+	 */
+	private $temporaryFolder = null;
+
+	/**
+	 * Get the metadata of the possible options
+	 *
+	 * @return  array
+	 *
+	 * @since   3.4
+	 */
+	private function getOptionsMeta()
+	{
+		return array(
+			array(
+				'short_name'     => 'f',
+				'long_name'      => 'folder',
+				'filter'         => 'raw',
+				'help_parameter' => 'CLI_INSTALL_EXTENSION_HELP_OPTION_FOLDER_PARAM',
+				'help_text'      => 'CLI_INSTALL_EXTENSION_HELP_OPTION_FOLDER'
+			),
+			array(
+				'short_name'     => 'p',
+				'long_name'      => 'package',
+				'filter'         => 'raw',
+				'help_parameter' => 'CLI_INSTALL_EXTENSION_HELP_OPTION_PACKAGE_PARAM',
+				'help_text'      => 'CLI_INSTALL_EXTENSION_HELP_OPTION_PACKAGE'
+			),
+			array(
+				'short_name'     => 'u',
+				'long_name'      => 'url',
+				'filter'         => 'raw',
+				'help_parameter' => 'CLI_INSTALL_EXTENSION_HELP_OPTION_URL_PARAM',
+				'help_text'      => 'CLI_INSTALL_EXTENSION_HELP_OPTION_URL'
+			),
+			array(
+				'short_name'     => 'w',
+				'long_name'      => 'web',
+				'filter'         => 'raw',
+				'help_parameter' => 'CLI_INSTALL_EXTENSION_HELP_OPTION_WEB_PARAM',
+				'help_text'      => 'CLI_INSTALL_EXTENSION_HELP_OPTION_WEB'
+			),
+		);
+	}
+
+	/**
+	 * Shows the usage instructions of this script
+	 *
+	 * @return  void
+	 *
+	 * @since   3.4
+	 */
+	private function showUsage()
+	{
+		$phpPath = defined('PHP_BINARY') ? PHP_BINARY : '/usr/bin/php';
+		$this->out(JText::sprintf('CLI_INSTALL_EXTENSION_USAGE', $phpPath, basename(__FILE__)));
+		$this->out('');
+		$this->out(JText::_('CLI_INSTALL_EXTENSION_OPTIONS'));
+		$this->out('');
+
+		foreach ($this->getOptionsMeta() as $optionDef)
+		{
+			$this->out('-' . $optionDef['short_name'], false);
+			$this->out(' ' . JText::_($optionDef['help_parameter']), false);
+			$this->out(' | ', false);
+			$this->out('--' . $optionDef['long_name'], false);
+			$this->out('=' . JText::_($optionDef['help_parameter']), false);
+			$this->out();
+			$this->out("\t" . JText::_($optionDef['help_text']));
+			$this->out();
+		}
+	}
+
+	/**
+	 * Checks if at least one of the installation options is set and populates the installationMethod and
+	 * installationSource properties.
+	 *
+	 * @return  bool  True if there was an installation method and source specified
+	 *
+	 * @since  3.4
+	 */
+	private function getAndValidateParameters()
+	{
+		foreach ($this->getOptionsMeta() as $optionDef)
+		{
+			$value = $this->input->get($optionDef['short_name'], null, $optionDef['filter']);
+
+			if (empty($value))
+			{
+				$value = $this->input->get($optionDef['long_name'], null, $optionDef['filter']);
+			}
+
+			if ( !empty($value))
+			{
+				$this->installationMethod = $optionDef['long_name'];
+				$this->installationSource = $value;
+
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	/**
+	 * Execute the application.
+	 *
+	 * @return  void
+	 *
+	 * @since   3.4
+	 */
+	public function execute()
+	{
+		// Unset the exceptions handler (allows the exceptions to be presented to the user)
+		restore_exception_handler();
+
+		// Load the language files for the Joomla! library (lib_joomla)
+		$jlang = JFactory::getLanguage();
+		$jlang->load('lib_joomla', JPATH_SITE, 'en-GB', true);
+		$jlang->load('lib_joomla', JPATH_SITE, null, true);
+
+		// Load the language files for the extensions installer (com_installer). IMPORTANT: These language files are
+		// located in the back-end of the site, hence JPATH_ADMINISTRATOR.
+		$jlang->load('com_installer', JPATH_ADMINISTRATOR, 'en-GB', true);
+		$jlang->load('com_installer', JPATH_ADMINISTRATOR, null, true);
+
+		// Load the language files for this CLI APP
+		$jlang->load('cli_install_extension', JPATH_SITE, 'en-GB', true);
+		$jlang->load('cli_install_extension', JPATH_SITE, null, true);
+
+		// Add a logger
+		JLog::addLogger(
+			array(
+				// Set the name of the log file.
+				'text_file' => 'installer_cli.php',
+			), JLog::DEBUG
+		);
+
+		// Show the application banner
+		$jVersion = new JVersion;
+// 		$this->out(JText::sprintf('CLI_INSTALL_EXTENSION', $jVersion->getShortVersion()));
+// 		$this->out($jVersion->COPYRIGHT);
+// 		$this->out(str_repeat('=', 79));
+// 		$this->out();
+
+		// Verify the command-line options
+		if (!$this->getAndValidateParameters())
+		{
+			$this->showUsage();
+			$this->close(1);
+		}
+
+// 		$this->out(JText::sprintf('CLI_INSTALL_EXTENSION_INSTALL_WITH_METHOD', $this->installationMethod));
+// 		$this->out();
+
+		// Find the package file to extract
+		$packageFile = null;
+
+		switch ($this->installationMethod)
+		{
+			case 'folder' :
+				$packageFile = null;
+
+			case 'package' :
+				$packageFile = $this->installationSource;
+				break;
+
+			case 'web' :
+			case 'url' :
+				$url = $this->installationSource;
+
+				if ($this->installationMethod == 'web')
+				{
+					$this->out(JText::sprintf('CLI_INSTALL_EXTENSION_FIND_DOWNLOAD_FROM_XML', $this->installationSource));
+					$url = $this->getDownloadUrlFromXML($this->installationSource);
+
+					if ($url === false)
+					{
+						$this->out(JText::sprintf('CLI_INSTALL_EXTENSION_ERR_XML_PROVIDES_NO_URL', $this->installationSource));
+						$this->close(3);
+					}
+				}
+
+				// Download the package
+				$this->out(JText::sprintf('CLI_INSTALL_EXTENSION_DOWNLOAD_FROM_URL', $url));
+				$this->temporaryPackage = JInstallerHelper::downloadPackage($url);
+
+				if ($this->temporaryPackage === false)
+				{
+					$this->out(JText::sprintf('CLI_INSTALL_EXTENSION_ERR_CANT_DOWNLOAD', $url));
+					$this->close(4);
+				}
+
+				$this->temporaryPackage = JFactory::getConfig()->get('tmp_path') . '/' . $this->temporaryPackage;
+				$packageFile            = $this->temporaryPackage;
+
+				break;
+
+			default :
+				$this->showUsage();
+				$this->close(1);
+				break;
+		}
+
+		// Make sure the package file exists
+		if (!is_null($packageFile) && !file_exists($packageFile))
+		{
+			$this->out(JText::sprintf('CLI_INSTALL_EXTENSION_ERR_PACKAGE_NOT_EXISTS', $packageFile));
+			$this->close(2);
+		}
+
+		// Extract the package file, if required
+		$extensionDirectory = null;
+
+		if ($this->installationMethod == 'folder')
+		{
+			$extensionDirectory = $this->installationSource;
+		}
+
+		if (!is_null($packageFile))
+		{
+// 			$this->out(JText::sprintf('CLI_INSTALL_EXTENSION_EXTRACTING_PACKAGE', $packageFile));
+			$package = JInstallerHelper::unpack($packageFile);
+
+			if ($package === false)
+			{
+				$this->cleanUp();
+
+				$this->out(JText::sprintf('CLI_INSTALL_EXTENSION_ERR_CANNOT_EXTRACT', $packageFile));
+				$this->close(5);
+			}
+
+			$this->temporaryFolder = $package['extractdir'];
+			$extensionDirectory    = $this->temporaryFolder;
+		}
+
+		// Try installing the extension
+// 		$this->out(JText::sprintf('CLI_INSTALL_EXTENSION_INSTALLING_FROM', $extensionDirectory));
+		$installer = new JInstaller;
+		$installed = $installer->install($extensionDirectory);
+
+		// Remove the temporary folders and files
+		$this->cleanUp();
+
+		// Print a message
+		if ($installed)
+		{
+			$this->out(JText::_('CLI_INSTALL_EXTENSION_MSG_SUCCESS'));
+			$this->close(0);
+		}
+		else
+		{
+			$this->out(JText::_('CLI_INSTALL_EXTENSION_MSG_FAIL'));
+			$this->close(250);
+		}
+	}
+
+	/**
+	 * Gets the download URL of an extension from an Update XML source
+	 *
+	 * @param   string  $url  The URL to the update XML source
+	 *
+	 * @return  string|bool  The download URL or false if it's not found
+	 *
+	 * @since   3.4
+	 */
+	private function getDownloadUrlFromXML($url)
+	{
+		jimport('joomla.updater.update');
+
+		$update = new JUpdate;
+		$update->loadFromXML($url);
+		$package_url = trim($update->get('downloadurl', false)->_data);
+
+		return $package_url;
+	}
+
+	/**
+	 * Flush the media version to refresh versionable assets. Called by the extensions installation code.
+	 *
+	 * @return  void
+	 *
+	 * @since   3.4
+	 */
+	public function flushAssets()
+	{
+		$version = new JVersion;
+		$version->refreshMediaVersion();
+	}
+
+	/**
+	 * Gets the name of the current template. Called by the extensions installation code.
+	 *
+	 * @param   boolean  $params  An optional associative array of configuration settings
+	 *
+	 * @return  mixed  System is the fallback.
+	 *
+	 * @since       3.4
+	 *
+	 * @deprecated  4.0
+	 */
+	public function getTemplate($params = false)
+	{
+		$template           = new stdClass;
+		$template->template = 'system';
+		$template->params   = new \Joomla\Registry\Registry;
+
+		if ($params)
+		{
+			return $template;
+		}
+
+		return $template->template;
+	}
+
+	/**
+	 * This method is called by the extensions installation code. Since we're in the context of a CLI application we
+	 * cannot set HTTP headers, so we'll simply ignore any call to this method.
+	 *
+	 * @param   string   $name     Ignored
+	 * @param   string   $value    Ignored
+	 * @param   boolean  $replace  Ignored
+	 *
+	 * @return  $this
+	 *
+	 * @since   3.4
+	 */
+	public function setHeader($name, $value, $replace = false)
+	{
+		return $this;
+	}
+
+	/**
+	 * Cleans up temporary files and folders used in the installation
+	 *
+	 * @return  void
+	 *
+	 * @since   3.4
+	 */
+	private function cleanUp()
+	{
+		if (!empty($this->temporaryFolder) && JFolder::exists($this->temporaryFolder))
+		{
+			JFolder::delete($this->temporaryFolder);
+		}
+
+		if (!empty($this->temporaryPackage) && JFile::exists($this->temporaryPackage))
+		{
+			JFile::delete($this->temporaryPackage);
+		}
+	}
+	
+	public function isSite() {
+		return false;
+	}
+	public function isAdmin() {
+		return false;
+	}
+	public function enqueueMessage($msg, $type="message") {
+		print "[type] $msg\n";
+	}
+	public function getRouter() {
+		return null;
+	}
+	
+}
+
+// Instantiate the application object
+$app = JApplicationCli::getInstance('JoomlaExtensionInstallerCli');
+
+// The installation code assumes that JFactory::getApplication returns a valid reference. We must not disappoint it!
+JFactory::$application = $app;
+
+// Execute the CLI extensions installer application
+$app->execute();
\ No newline at end of file
diff --git a/j3vm3_full/install-joomla.php b/j3vm3_full/install-joomla.php
new file mode 100644
index 0000000000000000000000000000000000000000..22bb755a740a1f143d4f041f059db0724c8837da
--- /dev/null
+++ b/j3vm3_full/install-joomla.php
@@ -0,0 +1,476 @@
+<?php
+/**
+ * @package    Joomla.Cli
+ *
+ * @copyright  Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.
+ * @license    GNU General Public License version 2 or later; see LICENSE.txt
+ */
+
+/**
+ * TODO description
+ */
+
+// Set flag that this is a parent file.
+const _JEXEC = 1;
+
+error_reporting(E_ALL | E_NOTICE);
+ini_set('display_errors', 1);
+
+// Bootstrap the application
+if (!file_exists(dirname(__DIR__) . '/installation/application/bootstrap.php'))
+{
+	die("Installation application has been removed.\n");
+}
+
+require_once dirname(__DIR__) . '/installation/application/bootstrap.php';
+chdir(dirname(__DIR__) . '/installation');
+
+require_once JPATH_LIBRARIES . '/import.legacy.php';
+require_once JPATH_LIBRARIES . '/cms.php';
+
+/**
+ * TODO description
+ *
+ * @package  Joomla.Cli
+ * @since    3.4
+ */
+class JApplicationCliInstaller extends JApplicationCli
+{
+	/**
+	 * Get a list of command-line options
+	 *
+	 * @return array each item is keyed by the installation system's internal option name; values arrays with keys:
+	 *	 - arg: string, the name of the command-line argument
+	 *	 - required: bool, an indication of whether the value is required
+	 *	 - default: mixed, default value to use if none is provided
+	 *	 - factory: callable, a fnction which produces the default value
+	 *       - type: string, e.g. "bool"
+	 *
+	 * @since  3.4
+	 */
+	public function getOptionsMetadata()
+	{
+		$optionsMetadata = array(
+			'help' => array(
+				'arg'         => 'help',
+				'description' => 'Display help',
+				'type'        => 'bool',
+			),
+			'admin_email'         => array(
+				'arg'         => 'admin-email',
+				'description' => 'Admin user\'s email',
+				'required'    => true,
+			),
+			'admin_password' => array(
+				'arg'         => 'admin-pass',
+				'description' => 'Admin user\'s password',
+				'required'    => true,
+			),
+			'admin_user' => array(
+				'arg'         => 'admin-user',
+				'description' => 'Admin user\'s username',
+				'default'     => 'admin',
+			),
+			'db_host' => array(
+				'arg'         => 'db-host',
+				'description' => 'Hostname (or hostname:port)',
+				'default'     => 'localhost',
+			),
+			'db_name' => array(
+				'arg'         => 'db-name',
+				'description' => 'Database name',
+				'required'    => true,
+			),
+			'db_old' => array(
+				'arg'         => 'db-old',
+				'description' => 'Policy to use with old DB [remove,backup]]',
+				'default'     => 'backup',
+			),
+			'db_pass' => array(
+				'arg'         => 'db-pass',
+				'description' => 'Database password',
+				'required'    => true,
+			),
+			'db_prefix' => array(
+				'arg'         => 'db-prefix',
+				'description' => 'Table prefix',
+				'factory'     => function () {
+					// FIXME: Duplicated from installation/model/fields/prefix.php
+					$size    = 5;
+					$prefix  = '';
+					$chars   = range('a', 'z');
+					$numbers = range(0, 9);
+
+					// We want the fist character to be a random letter:
+					shuffle($chars);
+					$prefix .= $chars[0];
+
+					// Next we combine the numbers and characters to get the other characters:
+					$symbols = array_merge($numbers, $chars);
+					shuffle($symbols);
+
+					for ($i = 0, $j = $size - 1; $i < $j; ++$i)
+					{
+						$prefix .= $symbols[$i];
+					}
+
+					// Add in the underscore:
+					$prefix .= '_';
+
+					return $prefix;
+				},
+			),
+			'db_type' => array(
+				'arg'         => 'db-type',
+				'description' => 'Database type [mysql,mysqli,pdomysql,postgresql,sqlsrv,sqlazure]',
+				'default'     => 'mysqli',
+			),
+			'db_user' => array(
+				'arg'         => 'db-user',
+				'description' => 'Database user',
+				'required'    => true,
+			),
+			'helpurl' => array(
+				'arg'         => 'help-url',
+				'description' => 'Help URL',
+				'default'     => 'http://help.joomla.org/proxy/index.php?option=com_help&amp;keyref=Help{major}{minor}:{keyref}',
+			),
+			// FIXME: Not clear if this is useful. Seems to be "the language of the installation application"
+			// and not "the language of the installed CMS"
+			'language' => array(
+				'arg'         => 'lang',
+				'description' => 'Language',
+				'default'     => 'en-GB',
+			),
+			'site_metadesc' => array(
+				'arg'         => 'desc',
+				'description' => 'Site description',
+				'default'     => ''
+			),
+			'site_name' => array(
+				'arg'         => 'name',
+				'description' => 'Site name',
+				'default'     => 'Joomla'
+			),
+			'site_offline' => array(
+				'arg'         => 'offline',
+				'description' => 'Set site as offline',
+				'default'     => 0,
+				'type'        => 'bool',
+			),
+			'sample_file' => array(
+				'arg'         => 'sample',
+				'description' => 'Sample SQL file (sample_blog.sql,sample_brochure.sql,...)',
+				'default'     => '',
+			),
+			'summary_email' => array(
+				'arg'         => 'email',
+				'description' => 'Send email notification',
+				'default'     => 0,
+				'type'        => 'bool',
+			),
+		);
+
+		// Installer internally has an option "admin_password2", but it
+		// doesn't seem to be necessary.
+		foreach (array_keys($optionsMetadata) as $key)
+		{
+			if (!isset($optionsMetadata[$key]['type']))
+			{
+				$optionsMetadata[$key]['type'] = 'raw';
+			}
+			if (!isset($optionsMetadata[$key]['syntax']))
+			{
+				if ($optionsMetadata[$key]['type'] == 'bool')
+				{
+					$optionsMetadata[$key]['syntax'] = '--' . $optionsMetadata[$key]['arg'];
+				}
+				else
+				{
+					$optionsMetadata[$key]['syntax'] = '--' . rtrim($optionsMetadata[$key]['arg'], ':') . '="..."';
+				}
+			}
+		}
+
+		return $optionsMetadata;
+	}
+
+	/**
+	 * Entry point for the script
+	 *
+	 * @return  void
+	 *
+	 * @since   3.4
+	 */
+	public function doExecute()
+	{
+		JFactory::getApplication('CliInstaller');
+
+		// Parse options
+		$options = $this->parseOptions();
+
+		if (array_key_exists('help', $options))
+		{
+			$this->displayUsage();
+			$this->close(0);
+		}
+
+		$errors = $this->validateOptions($options);
+
+		if (!empty($errors))
+		{
+			foreach ($errors as $error)
+			{
+				$this->enqueueMessage($error, 'fatal');
+			}
+
+			$this->displayUsage();
+			$this->close(1);
+		}
+
+		// Attempt to initialise the database.
+		$db = new InstallationModelDatabase;
+
+		if (!$db->createDatabase($options))
+		{
+			$this->fatal("Error executing createDatabase");
+		}
+
+		/*
+		   FIXME InstallationModelDatabase relies on session manipulation which doesn't work well in cli
+		   $session = JFactory::getSession();
+		   $options = $session->get('setup.options', NULL);
+		*/
+		$options['db_created'] = 1;
+		$options['db_select']  = 1;
+
+		if ($options['db_old'] == 'backup')
+		{
+			if (!$db->handleOldDatabase($options))
+			{
+				$this->fatal("Error executing handleOldDatabase");
+			}
+		}
+
+		if (!$db->createTables($options))
+		{
+			$this->fatal("Error executing createTables");
+		}
+
+		// Attempt to setup the configuration.
+		$configuration = new InstallationModelConfiguration;
+
+		if (!$configuration->setup($options))
+		{
+			$this->fatal("Error executing setup");
+		}
+
+		// Attempt to create the database tables.
+		if ($options['sample_file'])
+		{
+			if (!$db->installSampleData($options))
+			{
+				$this->fatal("Error executing installSampleData");
+			}
+		}
+
+		$this->out('Done');
+	}
+
+	/**
+	 * Display help text
+	 *
+	 * @return void
+	 *
+	 * @since  3.4
+	 */
+	public function displayUsage()
+	{
+		$this->out("Install Joomla");
+		$this->out("usage: php install.php [options]");
+
+		foreach ($this->getOptionsMetadata() as $spec)
+		{
+			$syntax = sprintf("%-25s", $spec['syntax']);
+
+			if (isset($spec['description']))
+			{
+				$syntax .= $spec['description'];
+			}
+
+			if (isset($spec['required']) && $spec['required'])
+			{
+				$syntax .= ' (required)';
+			}
+
+			if (isset($spec['default']))
+			{
+				$syntax .= " (default: {$spec['default']})";
+			}
+
+			if (isset($spec['factory']))
+			{
+				$syntax .= " (default: auto-generated)";
+			}
+
+			$this->out("	" . $syntax);
+		}
+	}
+
+	/**
+	 * Validate the inputs
+	 *
+	 * @param   array  $options  parsed input values
+	 *
+	 * @return  array  An array of error messages
+	 *
+	 * @since   3.4
+	 */
+	public function validateOptions($options)
+	{
+		$optionsMetadata = $this->getOptionsMetadata();
+		$errors = array();
+
+		foreach ($optionsMetadata as $key => $spec)
+		{
+			if (!isset($options[$key]) && isset($spec['required']) && $spec['required'])
+			{
+				$errors[] = "Missing required option: {$spec['syntax']}";
+			}
+		}
+
+		return $errors;
+	}
+
+	/**
+	 * Parse all options from the command-line
+	 *
+	 * @return array
+	 *
+	 * @since  3.4
+	 */
+	public function parseOptions()
+	{
+		global $argv;
+
+		if (count($argv) <= 1)
+		{
+			return array('help' => 1);
+		}
+
+		$optionsMetadata = $this->getOptionsMetadata();
+		$options         = array();
+
+		foreach ($optionsMetadata as $key => $spec)
+		{
+			if ($this->input->get($spec['arg'], null, $spec['type']))
+			{
+				$options[$key] = $this->input->get($spec['arg'], null, $spec['type']);
+			}
+			elseif (isset($spec['factory']))
+			{
+				$options[$key] = call_user_func($spec['factory']);
+			}
+			elseif (isset($spec['default']))
+			{
+				$options[$key] = $spec['default'];
+			}
+		}
+
+		return $options;
+	}
+
+	/**
+	 * Enqueue a system message.
+	 *
+	 * @param   string  $msg   The message to enqueue.
+	 * @param   string  $type  The message type. Default is message.
+	 *
+	 * @return  void
+	 *
+	 * @since   3.4
+	 */
+	public function enqueueMessage($msg, $type = 'message')
+	{
+		$this->out("[$type] $msg");
+	}
+
+	/**
+	 * Trigger a fatal error
+	 *
+	 * @param   string  $msg  The message to enqueue.
+	 *
+	 * @return  void
+	 *
+	 * @since   3.4
+	 */
+	public function fatal($msg)
+	{
+		$this->enqueueMessage($msg, 'fatal');
+		$this->close(1);
+	}
+
+	/**
+	 * Returns the installed language files in the administrative and
+	 * front-end area.
+	 *
+	 * @param   mixed  $db  JDatabaseDriver instance.
+	 *
+	 * @return  array  Array with installed language packs in admin and site area.
+	 *
+	 * @since   3.4
+	 */
+	public function getLocaliseAdmin($db = false)
+	{
+		// Read the files in the admin area
+		$path               = JLanguage::getLanguagePath(JPATH_ADMINISTRATOR);
+		$langfiles['admin'] = JFolder::folders($path);
+
+		// Read the files in the site area
+		$path              = JLanguage::getLanguagePath(JPATH_SITE);
+		$langfiles['site'] = JFolder::folders($path);
+
+		if ($db)
+		{
+			$langfiles_disk     = $langfiles;
+			$langfiles          = array();
+			$langfiles['admin'] = array();
+			$langfiles['site']  = array();
+
+			$query = $db->getQuery(true)
+				->select($db->quoteName(array('element', 'client_id')))
+				->from($db->quoteName('#__extensions'))
+				->where($db->quoteName('type') . ' = ' . $db->quote('language'));
+			$db->setQuery($query);
+			$langs = $db->loadObjectList();
+
+			foreach ($langs as $lang)
+			{
+				switch ($lang->client_id)
+				{
+					// Site
+					case 0 :
+						if (in_array($lang->element, $langfiles_disk['site']))
+						{
+							$langfiles['site'][] = $lang->element;
+						}
+
+						break;
+
+					// Administrator
+					case 1 :
+						if (in_array($lang->element, $langfiles_disk['admin']))
+						{
+							$langfiles['admin'][] = $lang->element;
+						}
+
+						break;
+				}
+			}
+		}
+
+		return $langfiles;
+	}
+}
+
+JApplicationCli::getInstance('JApplicationCliInstaller')->execute();
diff --git a/j3vm3_full/makedb.php b/j3vm3_full/makedb.php
new file mode 100644
index 0000000000000000000000000000000000000000..2362ee777c3ff64639b66b871200d7524eef1333
--- /dev/null
+++ b/j3vm3_full/makedb.php
@@ -0,0 +1,46 @@
+<?php
+// Args: 0 => makedb.php, 1 => "$VM_DB_HOST", 2 => "$VM_DB_USER", 3 => "$VM_DB_PASSWORD", 4 => "$VM_DB_NAME"
+$stderr = fopen('php://stderr', 'w');
+fwrite($stderr, "\nEnsuring Joomla database is present\n");
+
+if (strpos($argv[1], ':') !== false)
+{
+	list($host, $port) = explode(':', $argv[1], 2);
+}
+else
+{
+	$host = $argv[1];
+	$port = 3306;
+}
+
+$maxTries = 10;
+
+do
+{
+	$mysql = new mysqli($host, $argv[2], $argv[3], '', (int) $port);
+
+	if ($mysql->connect_error)
+	{
+		fwrite($stderr, "\nMySQL Connection Error: ({$mysql->connect_errno}) {$mysql->connect_error}\n");
+		--$maxTries;
+
+		if ($maxTries <= 0)
+		{
+			exit(1);
+		}
+
+		sleep(3);
+	}
+}
+while ($mysql->connect_error);
+
+if (!$mysql->query('CREATE DATABASE IF NOT EXISTS `' . $mysql->real_escape_string($argv[4]) . '`'))
+{
+	fwrite($stderr, "\nMySQL 'CREATE DATABASE' Error: " . $mysql->error . "\n");
+	$mysql->close();
+	exit(1);
+}
+
+fwrite($stderr, "\nMySQL Database Created\n");
+
+$mysql->close();
diff --git a/j3vm3_full/supervisord.conf b/j3vm3_full/supervisord.conf
new file mode 100644
index 0000000000000000000000000000000000000000..d5d19a313ccd350bf7ed729de8ae6a1e0a1de4bc
--- /dev/null
+++ b/j3vm3_full/supervisord.conf
@@ -0,0 +1,10 @@
+[supervisord]
+nodaemon=true
+
+[program:apache]
+command=/usr/local/bin/apache2-foreground
+autorestart=true
+
+[include]
+files = /etc/supervisor/conf.d/*.conf
+