diff --git a/.gitignore b/.gitignore
index bd71aa97184..9749b2b4692 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,4 @@ docs/_build
.DS_Store
james.ini
build.py
+.vagrant/
diff --git a/Vagrantfile b/Vagrantfile
new file mode 100644
index 00000000000..325dba8c32b
--- /dev/null
+++ b/Vagrantfile
@@ -0,0 +1,42 @@
+require "yaml"
+
+# Load up our vagrant config files -- vagrantconfig.yaml first
+_config = YAML.load(File.open(File.join(File.dirname(__FILE__),
+ "vagrantconfig.yaml"), File::RDONLY).read)
+
+# Local-specific/not-git-managed config -- vagrantconfig_local.yaml
+begin
+ extra = YAML.load(File.open(File.join(File.dirname(__FILE__),
+ "vagrantconfig_local.yaml"), File::RDONLY).read)
+ if extra
+ _config.merge!(extra)
+ end
+rescue Errno::ENOENT # No vagrantconfig_local.yaml found -- that's OK; just
+ # use the defaults.
+end
+
+CONF = _config
+MOUNT_POINT = '/home/vagrant/kitsune'
+
+Vagrant::Config.run do |config|
+ config.vm.box = "ubuntu-14.04"
+ config.vm.box_url = "https://oss-binaries.phusionpassenger.com/vagrant/boxes/latest/ubuntu-14.04-amd64-vbox.box"
+
+ Vagrant.configure("1") do |config|
+ config.vm.customize ["modifyvm", :id, "--memory", CONF['memory']]
+ end
+
+ Vagrant.configure("2") do |config|
+ config.vm.provider "virtualbox" do |v|
+ v.name = "KITSUNE_VM"
+ v.customize ["modifyvm", :id, "--memory", CONF['memory']]
+ end
+ end
+
+ config.vm.network :hostonly, "33.33.33.77"
+ config.vm.forward_port 8000, 8000
+
+ config.vm.share_folder("vagrant-root", MOUNT_POINT, ".")
+ config.vm.provision "shell", path: "bin/vagrant_provision.sh"
+end
+
diff --git a/bin/vagrant_provision.sh b/bin/vagrant_provision.sh
new file mode 100644
index 00000000000..9b69973b499
--- /dev/null
+++ b/bin/vagrant_provision.sh
@@ -0,0 +1,70 @@
+#!/bin/bash
+
+set -e
+
+INSTALL_DIR=/home/vagrant
+
+cd $INSTALL_DIR/kitsune
+
+# Install package for add-apt-repository
+apt-get install -y software-properties-common
+
+# ElasticSearch key add/setup
+curl http://packages.elasticsearch.org/GPG-KEY-elasticsearch | apt-key add -
+echo "deb http://packages.elasticsearch.org/elasticsearch/0.90/debian stable main" \
+ > /etc/apt/sources.list.d/elasticsearch.list
+
+# Add the needed repositories for Node/Redis/Python2.6
+add-apt-repository ppa:chris-lea/node.js
+add-apt-repository ppa:chris-lea/redis-server
+add-apt-repository ppa:fkrull/deadsnakes
+
+apt-get update
+
+# Set default password for MariaDB
+export DEBIAN_FRONTEND=noninteractive
+debconf-set-selections <<< 'mariadb-server-5.5 mysql-server/root_password password rootpass'
+debconf-set-selections <<< 'mariadb-server-5.5 mysql-server/root_password_again password rootpass'
+
+# Install services and their dependencies
+# Services: Sphinx, MariaDB, ElasticSearch, Redis, and Memcached
+apt-get install -y sphinx-common libapache2-mod-wsgi python-pip libmysqlclient-dev git \
+ libxml2-dev libxslt1-dev zlib1g-dev libjpeg-dev python-dev libssl-dev \
+ openjdk-7-jre-headless mariadb-server-5.5 nodejs elasticsearch redis-server \
+ memcached python2.6 python2.6-dev
+
+# Setup the virtualenv and start using it
+pip install virtualenv
+virtualenv -p /usr/bin/python2.6 $INSTALL_DIR/virtualenv
+chown -R vagrant $INSTALL_DIR/virtualenv
+source $INSTALL_DIR/virtualenv/bin/activate
+
+python $INSTALL_DIR/kitsune/scripts/peep.py install -r $INSTALL_DIR/kitsune/requirements/py26.txt
+pip install nose-progressive==1.5.0
+
+# Copy configurations for kitsune and mysql
+# MySQL Default User: root
+# MySQL Default Pass: rootpass
+cp $INSTALL_DIR/kitsune/configs/vagrant/settings_local.py \
+ $INSTALL_DIR/kitsune/kitsune/settings_local.py
+
+cp $INSTALL_DIR/kitsune/configs/vagrant/my.cnf /etc/mysql/my.cnf
+
+# Fix default port to match kitsune
+sed -ie 's/^port 6379$/port 6383/' /etc/redis/redis.conf
+service redis-server restart
+
+# Create the kitsune database
+mysql -e 'CREATE DATABASE kitsune CHARACTER SET utf8 COLLATE utf8_unicode_ci'
+mysql -e "GRANT ALL ON kitsune.* TO kitsune@localhost IDENTIFIED BY 'password'"
+
+# Install npm and included packages (lessc is the one we need of these)
+npm install
+./node_modules/.bin/gulp nunjucks
+
+# Retrieve and store historical version data
+./manage.py update_product_details
+
+# Setup tables and generate some data
+./manage.py syncdb --migrate --noinput
+./manage.py generatedata
diff --git a/configs/vagrant/my.cnf b/configs/vagrant/my.cnf
new file mode 100644
index 00000000000..c57c9bb19d5
--- /dev/null
+++ b/configs/vagrant/my.cnf
@@ -0,0 +1,129 @@
+#
+# The MySQL database server configuration file.
+#
+# You can copy this to one of:
+# - "/etc/mysql/my.cnf" to set global options,
+# - "~/.my.cnf" to set user-specific options.
+#
+# One can use all long options that the program supports.
+# Run program with --help to get a list of available options and with
+# --print-defaults to see which it would actually understand and use.
+#
+# For explanations see
+# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
+
+# This will be passed to all mysql clients
+# It has been reported that passwords should be enclosed with ticks/quotes
+# escpecially if they contain "#" chars...
+# Remember to edit /etc/mysql/debian.cnf when changing the socket location.
+[client]
+user = root
+password = rootpass
+port = 3306
+socket = /var/run/mysqld/mysqld.sock
+
+# Here is entries for some specific programs
+# The following values assume you have at least 32M ram
+
+# This was formally known as [safe_mysqld]. Both versions are currently parsed.
+[mysqld_safe]
+socket = /var/run/mysqld/mysqld.sock
+nice = 0
+
+[mysqld]
+#
+# * Basic Settings
+#
+user = mysql
+pid-file = /var/run/mysqld/mysqld.pid
+socket = /var/run/mysqld/mysqld.sock
+port = 3306
+basedir = /usr
+datadir = /var/lib/mysql
+tmpdir = /tmp
+lc-messages-dir = /usr/share/mysql
+skip-external-locking
+#
+# Instead of skip-networking the default is now to listen only on
+# localhost which is more compatible and is not less secure.
+bind-address = 127.0.0.1
+#
+# * Fine Tuning
+#
+key_buffer = 16M
+max_allowed_packet = 16M
+thread_stack = 192K
+thread_cache_size = 8
+# This replaces the startup script and checks MyISAM tables if needed
+# the first time they are touched
+myisam-recover = BACKUP
+#max_connections = 100
+#table_cache = 64
+#thread_concurrency = 10
+#
+# * Query Cache Configuration
+#
+query_cache_limit = 1M
+query_cache_size = 16M
+#
+# * Logging and Replication
+#
+# Both location gets rotated by the cronjob.
+# Be aware that this log type is a performance killer.
+# As of 5.1 you can enable the log at runtime!
+#general_log_file = /var/log/mysql/mysql.log
+#general_log = 1
+#
+# Error log - should be very few entries.
+#
+log_error = /var/log/mysql/error.log
+#
+# Here you can see queries with especially long duration
+#log_slow_queries = /var/log/mysql/mysql-slow.log
+#long_query_time = 2
+#log-queries-not-using-indexes
+#
+# The following can be used as easy to replay backup logs or for replication.
+# note: if you are setting up a replication slave, see README.Debian about
+# other settings you may need to change.
+#server-id = 1
+#log_bin = /var/log/mysql/mysql-bin.log
+expire_logs_days = 10
+max_binlog_size = 100M
+#binlog_do_db = include_database_name
+#binlog_ignore_db = include_database_name
+#
+# * InnoDB
+#
+# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/.
+# Read the manual for more InnoDB related options. There are many!
+#
+# * Security Features
+#
+# Read the manual, too, if you want chroot!
+# chroot = /var/lib/mysql/
+#
+# For generating SSL certificates I recommend the OpenSSL GUI "tinyca".
+#
+# ssl-ca=/etc/mysql/cacert.pem
+# ssl-cert=/etc/mysql/server-cert.pem
+# ssl-key=/etc/mysql/server-key.pem
+
+
+
+[mysqldump]
+quick
+quote-names
+max_allowed_packet = 16M
+
+[mysql]
+#no-auto-rehash # faster start of mysql but no tab completition
+
+[isamchk]
+key_buffer = 16M
+
+#
+# * IMPORTANT: Additional settings that can override those from this file!
+# The files must end with '.cnf', otherwise they'll be ignored.
+#
+!includedir /etc/mysql/conf.d/
diff --git a/configs/vagrant/settings_local.py b/configs/vagrant/settings_local.py
new file mode 100644
index 00000000000..6a6fba499d1
--- /dev/null
+++ b/configs/vagrant/settings_local.py
@@ -0,0 +1,80 @@
+from kitsune.settings import *
+import sys
+
+INSTALLED_APPS = list(INSTALLED_APPS)
+MIDDLEWARE_CLASSES = list(MIDDLEWARE_CLASSES)
+JINGO_EXCLUDE_APPS = list(JINGO_EXCLUDE_APPS)
+
+TESTING = 'test' in sys.argv
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+SESSION_COOKIE_SECURE = False
+
+# Allows you to run Kitsune without running Celery---all tasks
+# will be done synchronously.
+CELERY_ALWAYS_EAGER = True
+
+# Allows you to specify waffle settings in the querystring.
+WAFFLE_OVERRIDE = True
+
+# Change this to True if you're going to be doing search-related
+# work.
+ES_LIVE_INDEXING = False
+
+# Basic cache configuration for development.
+CACHES = {
+ 'default': {
+ 'BACKEND': 'caching.backends.memcached.CacheClass',
+ 'LOCATION': 'localhost:11211',
+ 'PREFIX': 'sumo:',
+ }
+}
+
+DATABASES = {
+ 'default': {
+ 'NAME': 'kitsune',
+ # 'NAME': 'kitsune_generatedata',
+ 'ENGINE': 'django.db.backends.mysql',
+ # 'HOST': 'mariadb',
+ 'HOST': 'localhost',
+ 'USER': 'root',
+ 'PASSWORD': 'rootpass',
+ 'OPTIONS': {'init_command': 'SET storage_engine=InnoDB'},
+ 'TEST_CHARSET': 'utf8',
+ 'TEST_COLLATION': 'utf8_unicode_ci',
+ },
+}
+
+REDIS_BACKENDS = {
+ 'default': 'redis://localhost:6383?socket_timeout=0.5&db=0',
+ 'karma': 'redis://localhost:6383?socket_timeout=0.5&db=1',
+ 'helpfulvotes': 'redis://localhost:6383?socket_timeout=0.5&db=2',
+}
+
+LESS_PREPROCESS = True
+LESS_BIN = path('node_modules/.bin/lessc')
+UGLIFY_BIN = path('node_modules/.bin/uglifyjs')
+CLEANCSS_BIN = path('node_modules/.bin/cleancss')
+NUNJUCKS_PRECOMPILE_BIN = path('node_modules/.bin/nunjucks-precompile')
+
+INSTALLED_APPS += ['django_qunit']
+
+AXES_BEHIND_REVERSE_PROXY = False
+
+
+# if not TESTING:
+# # debug_toolbar breaks the tests.
+# INSTALLED_APPS += ['debug_toolbar']
+# MIDDLEWARE_CLASSES += ['debug_toolbar.middleware.DebugToolbarMiddleware']
+# JINGO_EXCLUDE_APPS += ['debug_toolbar']
+
+# class ContainsEverything(object):
+# def __contains__(self, item):
+# return True
+
+# INTERNAL_IPS = ContainsEverything()
+
+# DEBUG_TOOLBAR_CONFIG = {
+# 'SHOW_COLLAPSED': True,
+# }
diff --git a/docs/hacking_howto.rst b/docs/hacking_howto.rst
index 15c6ee8efd2..bdbe4938f9d 100644
--- a/docs/hacking_howto.rst
+++ b/docs/hacking_howto.rst
@@ -51,6 +51,30 @@ distributions. It's likely that you'll encounter some steps that are
slightly different. If you run into problems, let us know.
+Vagrant
+-------
+
+We also have an option of using a virtual machine with Vagrant for an
+all-in-one installation. This installs all required dependencies and
+sets up your environment in such a way that makes it easy to run.
+
+For help with installation, check out Vagrant's documentation
+`here `_.
+
+Once Vagrant is installed, run ``vagrant up`` to start and configure your
+virtual machine and ``vagrant ssh`` to SSH into the box.
+
+Once inside the virtual machine, you can start the server by running the
+following commands::
+
+ source virtualenv/bin/activate
+ cd kitsune
+ ./manage.py runserver 0.0.0.0:8000
+
+Now, just navigate to `` to see the application!
+
+:ref:`Skip to Testing `
+
Requirements
============
@@ -320,6 +344,8 @@ to ensure that they render correctly. You have two options here:
$ /path/to/gulp watch
+.. _testing-it-out:
+
Testing it out
==============
diff --git a/vagrantconfig.yaml b/vagrantconfig.yaml
new file mode 100644
index 00000000000..35c275004a5
--- /dev/null
+++ b/vagrantconfig.yaml
@@ -0,0 +1,12 @@
+# Default config for Vagrant
+
+# Don't change this; use vagrantconfig_local.yaml to override these
+# settings instead.
+
+memory: 256
+
+# enable this to see verbose and debug puppet output
+debug_mode: false
+
+# set this to "gui" if vagrant cannot connect
+boot_mode: none
diff --git a/vagrantconfig_local.yaml b/vagrantconfig_local.yaml
new file mode 100644
index 00000000000..8259b661859
--- /dev/null
+++ b/vagrantconfig_local.yaml
@@ -0,0 +1,8 @@
+# Overwritable config for Vagrant
+
+# Don't change this; copy this to vagrantconfig_local.yaml, and change that instead.
+
+#memory: 256
+
+# set this to "gui" if vagrant cannot connect
+#boot_mode: gui