VirtualBox + Vagrant + Landrush, running Ubuntu 16.04 LTS (Xenial Xersus) with your choice of Nginx or Apache + MariaDB (MySQL), PHP (choice of PHP 7.1, PHP 7.0, PHP 5.6, PHP 5.5), and WordPress.
You need VirtualBox, Vagrant, and a DNS plugin.
The following commands will do the trick for you.
$ brew install cask;
$ brew cask install virtualbox vagrant;
Tweak VirtualBox by running this line please. See details to learn more.
$ VBoxManage dhcpserver remove --netname HostInterfaceNetworking-vboxnet0;
Install a DNS plugin. See vagrant-hostsupdater
vs. LandRush
$ vagrant plugin install vagrant-hostsupdater; # Easiest (recommended).
# vagrant plugin install landrush; # More difficult, but greater flexibility.
Optionally install the disksize plugin. See plugin details.
If installed, the Ubuntu Bootstrap will automatically allocate 20GB instead of the default 10GB.
$ vagrant plugin install vagrant-disksize;
Optionally install the triggers plugin. See plugin details.
This enables some additional bootstrapping magic that can improve your experience.
$ vagrant plugin install vagrant-triggers;
Optionally install a caching plugin. See plugin details.
This reduces the amount of downloading the Ubuntu Bootstrap needs to do over time.
$ vagrant plugin install vagrant-cachier;
$ mkdir ~/vms && cd ~/vms;
$ git clone https://github.com/websharks/ubuntu-bootstrap my.vm;
Note the sub-directory name (my.vm
) becomes your domain name.
Change it if you like. Must end with .vm
please.
$ cd ~/vms/my.vm;
$ vagrant up;
$ vagrant ssh;
$ sudo /bootstrap/src/installer --CFG_USE_WIZARD=0;
Open https://my.vm. Upon first visit, you'll run into an SSL security warning. You can avoid that warning altogether later using the details below. For now, please bypass this self-signed certificate warning and proceed. You should then see the WordPress installation page!
Q: What if https://my.vm doesn't work for me?
A: Try flushing your local DNS cache.
Tip: WordPress dev containers are available too. In addition to my.vm
, you also have specific versions of PHP available at: php71.my.vm
, php70.my.vm
, php56.my.vm
, php55.my.vm
, and php54.my.vm
. By default, the main my.vm
web server runs Nginx, while all of the PHP version-specific dev containers run Apache.
If you'd like to always see a green SSL status for your local test sites (i.e., avoid https://
warnings on anything ending with .vm
), you can download and install this root CA certificate file and set your trust settings to "Always Trust" for this certificate.
To clarify, any SSL certificates created by the Ubuntu Bootstrap will use that root CA certificate. Trusting the root CA (it's fake, and only for the Ubuntu Bootstrap project) will green-light all of your local .vm
domains when accessing them over https://
.
On a Mac, you can simply drag n' drop the certificate file onto your Keychain.app. Then open the settings for the certificate and choose "Always Trust" at the top.
Note: Prior to macOS Sierra, there was a nasty bug in Keychain.app that would lock your system when attempting to 'Always Trust'. If you're running an older OS X release try this command-line alternative given by @raamdev.
Doc root: ~/vms/my.vm/src/app/src/
The latest version of WordPress will already be installed. However, you can add any additional application files that you'd like. e.g., phpBB, Drupal, Joomla, whatever you like. It's probably a good idea to put anything new inside a sub-directory; e.g., ~/vms/my.vm/src/app/src/phpBB
$_SERVER['CFG_MYSQL_DB_HOST']
Database host.$_SERVER['CFG_MYSQL_DB_NAME']
Database name.$_SERVER['CFG_MYSQL_DB_USERNAME']
Database username.$_SERVER['CFG_MYSQL_DB_PASSWORD']
Database password.
Tip: For a full list of all global environment variables, see: src/setups/env-vars
in the repo. Or, from the command-line on your VM type: $ cat /etc/environment
— shows you their values.
A username/password is required for access.
username: admin
, password: admin
- https://my.vm/---tools/pma/ PhpMyAdmin
DB name:db0
, DB user:admin
, DB pass:admin
- https://my.vm/---tools/opcache.php OPcache dump.
- https://my.vm/---tools/info.php
phpinfo()
output page. - https://my.vm/---tools/fpm-status.php PHP-FPM status page.
- https://my.vm/---tools/status.nginx NGINX status page (default web server).
- https://my.vm/---tools/apache-status Apache status page (if installed).
- https://my.vm/---tools/apache-info Apache info page (if installed).
- http://my.vm:8025 MailHog web interface for test emails.
$ cd ~/vms/my.vm;
$ vagrant destroy;
In the project directory you'll find a /src/vagrant/bootstrap-custom
file. This bash script runs as the root
user during vagrant up
. So, you can install software and configure anything you like in this script. By default, this script does nothing. All of the software installation and system configuration takes place whenever you run /bootstrap/src/installer
inside the VM.
-
Customize
/src/installer
and the associated setup files that it calls upon, which are located in:/src/setups/*
. Note: If you go this route, there really is no reason to customize the/src/vagrant/bootstrap-custom
file. You can leave it as-is. -
Or, instead of working with the more complex installer, you can keep things simple and add your customizations to the
/src/vagrant/bootstrap-custom
script, which is a very simple starting point. The/src/vagrant/bootstrap-custom
runs whenever you typevagrant up
, so this is a logical choice for beginners. Note: If you go this route, you can simply choose not to run/bootstrap/src/installer
, because all of your customizations will be in the/src/vagrant/bootstrap-custom
file; i.e., there will be no reason to run the installer.
$ vagrant up;
$ vagrant ssh;
$ sudo /bootstrap/src/installer; # Presents a configuration dialog.
# Tip: to bypass configuration add the `--CFG_USE_WIZARD=0` argument to the installer.
$ git clone https://github.com/jaswrks/vagrant-ubuntu-lemp my-second.vm;
$ cd my-second.vm;
$ vagrant up && vagrant ssh;
$ sudo /bootstrap/src/installer; # Presents a configuration dialog.
# Tip: to bypass configuration add the `--CFG_USE_WIZARD=0` argument to the installer.
The URL which leads to your VM is based on the name of the directory that you cloned the repo into; e.g., my.vm
or my-second.vm
in the examples here. The directory that you clone into MUST end with .vm
for this to work as expected. If the directory you cloned into doesn't end with .vm
, the default domain name will be http://ubuntu.vm
If you're running the Landrush plugin for Vagrant, the domain name is also wildcarded. So my.vm
, www.my.vm
, wordpress.my.vm
— these all map to the exact same document root: ~/vms/my.vm/app/src/
, which is helpful when testing WordPress multisite networks. You can easily setup a sub-domain network, or even an MU domain mapping plugin and run additional tests.
If instead, you're running the vagrant-hostsupdater
plugin, wildcard DNS is not possible, but the following sub-domains are mapped automatically by the Vagrantfile so you'll still have a few to work with; i.e., my.my.vm
, dev.my.vm
, io.my.vm
, api.my.vm
, cdn.my.vm
, sub.my.vm
, sub1.my.vm
, sub2.my.vm
, sub3.my.vm
, and perhaps others if you choose to install WordPress dev containers when following prompts in the installer; e.g., php54.my.vm
, php55.my.vm
, php56.my.vm
, php70.my.vm
, php71.my.vm
.
See /Vagrantfile
where you will find this section already implemented.
_~ See also: src/wordpress/install-symlinks
_
wp_project_dirs = ( ENV["WP_#{_VM_HOSTNAME_UC_VAR}_PROJECTS_DIR"] || ENV['WP_PROJECTS_DIR'] || File.expand_path('~/projects/wordpress') ).split(/[:;]+/).map(&:strip);
wp_personal_project_dirs = ( ENV["WP_#{_VM_HOSTNAME_UC_VAR}_PERSONAL_PROJECTS_DIR"] || ENV['WP_PERSONAL_PROJECTS_DIR'] || File.expand_path('~/projects/personal/wordpress') ).split(/[:;]+/).map(&:strip);
wp_business_project_dirs = ( ENV["WP_#{_VM_HOSTNAME_UC_VAR}_BUSINESS_PROJECTS_DIR"] || ENV['WP_BUSINESS_PROJECTS_DIR'] || File.expand_path('~/projects/business/wordpress') ).split(/[:;]+/).map(&:strip);
wp_project_dirs.each_with_index do |dir, i|
if File.directory?(dir)
config.vm.synced_folder dir, "/wp-projects-#{i}", mount_options: ['defaults', 'ro'];
end;
end;
wp_personal_project_dirs.each_with_index do |dir, i|
if File.directory?(dir)
config.vm.synced_folder dir, "/wp-personal-#{i}", mount_options: ['defaults', 'ro'];
end;
end;
wp_business_project_dirs.each_with_index do |dir, i|
if File.directory?(dir)
config.vm.synced_folder dir, "/wp-business-#{i}", mount_options: ['defaults', 'ro'];
end;
end;
The built-in default Vagrantfile
is automatically mounting drives on your VM, sourced by a local ~/projects/wordpress
directory — if you have that directory. So, put your WordPress themes and plugins in ~/projects/wordpress
, i.e. in your local filesystem. These will be mounted on the VM automatically as /wp-projects-0/[themes|plugins]/[basename]
.
Then, in the included src/wordpress/install-symlinks
file, the Ubuntu Bootstrap iterates through all /wp-projects-*
directories that were mounted on the VM. It build symlinks for each of your themes and plugins automatically. This means when you log into your WordPress Dashboard on the VM you will have all of your themes and plugins available for testing. If you make edits locally in your favorite editor, those changes take effect in real-time on the VM.
The additional mounts: ~/projects/personal/wordpress
and ~/projects/business/wordpress
are simply alternate locations. There are also some interesting variables being scanned in the above snippet. Those variables implement some powerful dynamics you can take advantage of — discussed in greater detail below.
~/projects/wordpress
in your local file system.- Is mounted on the VM as:
/wp-projects-0
- Is mounted on the VM as:
- Then, on the VM, the
src/wordpress/install-symlinks
script symlinks each theme/plugin into:/app/src/wp-content/[themes|plugins]
appropriately.
In your local file system, inside ~/projects/wordpress
create two sub-directories.
~/projects/wordpress/themes
(put themes in this directory; e.g.,.../my-theme/
)~/projects/wordpress/plugins
(put plugins here; e.g.,.../my-plugin/
)
When you run /bootstrap/src/installer
from the VM, your local copy of ~/projects/wordpress/themes/my-theme
becomes /app/src/wp-content/themes/my-theme
on the VM. Your local copy of ~/projects/wordpress/plugins/my-plugin
becomes /app/src/wp-content/plugins/my-plugin
on the VM ... and so on... for each theme/plugin sub-directory, and for each of the three possible mounts listed above. This all happens automatically if you followed the instructions.
Yes. Looking over the snippet above, you can see three environment variables can be set in your ~/.profile
. Setting them will override the default locations automatically. Here's a quick example showing how you might customize these in your own ~/.profile
export WP_PROJECTS_DIR=~/my-projects/wordpress;
export WP_PERSONAL_PROJECTS_DIR=~/my-personal-projects/wordpress;
export WP_BUSINESS_PROJECTS_DIR=~/my-business-projects/wordpress;
It's also possible to define hostname-specific environment variables. Take note of _MY_VM
in the examples below. This correlates with my.vm
(a specific hostname) converted to all uppercase with dots and hyphens now as _
underscores.
export WP_MY_VM_PROJECTS_DIR=~/my-projects/wordpress;
export WP_MY_VM_PERSONAL_PROJECTS_DIR=~/my-personal-projects/wordpress;
export WP_MY_VM_BUSINESS_PROJECTS_DIR=~/my-business-projects/wordpress;
It's also possible to set multiple locations in each environment variable by delimiting them with a colon :
or semicolon ;
. For example, if you work with multiple businesses.
export WP_BUSINESS_PROJECTS_DIR=~/business-1/wordpress:~/business-2/wordpress;
Or, by combining both techniques (hostname-specific and delimited).
export WP_MY_VM_BUSINESS_PROJECTS_DIR=~/business-1/wordpress:~/business-2/wordpress;
The following CLI arguments can be passed to /bootstrap/src/installer
, just in case you'd like to avoid the configuration wizard entirely. These are all optional; i.e., if you don't provide these arguments you will be prompted to configure the bootstrap using a command-line dialog interface whenever the installer runs.
Tip: You can learn more about how these work and what the defaults are by looking through the src/setups/cfg/setup
file carefully, and perhaps searching for their use in other files found in src/setups/*
.
--CFG_4CI=0|1
Building as a base image for a CI server?--CFG_4PKG=0|1
Building as a base image that will be packaged?
--CFG_USE_WIZARD=0|1
Set as0
to bypass the wizard.
--CFG_HOST=my.cool.vm
Host name.--CFG_ROOT_HOST=cool.vm
Root host name.
--CFG_SLUG=my-cool-vm
Slug w/ dashes, no underscores.--CFG_VAR=my_cool_vm
Slug w/ underscores, no dashes.
--CFG_ADMIN_GENDER=[male|female]
Admin gender.
--CFG_ADMIN_USERNAME=admin
Admin username.--CFG_ADMIN_PASSWORD=admin
Admin password.
--CFG_ADMIN_NAME='Admin Istrator'
Display name.--CFG_ADMIN_EMAIL='[email protected]'
Admin email address.--CFG_ADMIN_PUBLIC_EMAIL='[email protected]'
Public email address.
--CFG_ADMIN_PREFERRED_SHELL=/bin/zsh
Or/bin/bash
.--CFG_ADMIN_STATIC_IP_ADDRESS=[ip]
e.g.,123.456.789.0
--CFG_ADMIN_AUTHORIZED_SSH_KEYS=[file]
e.g.,/authorized_keys
--CFG_AWS_TRANSFER_ACCESS_KEY_ID=xxxxxxx...
AWS access key ID.--CFG_AWS_TRANSFER_SECRET_ACCESS_KEY=xxxxxxx...
AWS secret access key.
--CFG_INSTALL_SWAP=0|1
Install swap space?
--CFG_INSTALL_WS_CA_FILES=0|1
Use WebSharks certificate authority?
--CFG_INSTALL_POSTFIX=0|1
Install Postfix?--CFG_INSTALL_MAILHOG=0|1
Install MailHog instead of Postfix?
--CFG_INSTALL_OPENVPN=0|1
Install OpenVPN server?
--CFG_INSTALL_DOCKER=0|1
Install Docker?
--CFG_INSTALL_OAUTH_KEYS=0|1
Install OAuth keys?--CFG_OAUTH_PUBLIC_KEY=[file]
OAuth SSL public key file.--CFG_OAUTH_PRIVATE_KEY=[file]
OAuth SSL private key file.--CFG_OAUTH_ENCRYPTION_KEY=xxxxxxx...
OAuth 32-byte, base64-encoded key.
--CFG_INSTALL_MYSQL=0|1
Install MySQL?
--CFG_MYSQL_DB_HOST=127.0.0.1
MySQL DB host name.--CFG_MYSQL_DB_PORT=3306
MySQL DB port number.
--CFG_MYSQL_SSL_KEY=[file]
MySQL SSL key file.--CFG_MYSQL_SSL_CRT=[file]
MySQL SSL crt file.--CFG_MYSQL_SSL_CA=[file]
MySQL SSL ca file.--CFG_MYSQL_SSL_CIPHER=[cipher]
MySQL SSL cipher.
--CFG_MYSQL_SSL_ENABLE=0|1
MySQL over SSL?
--CFG_MYSQL_DB_CHARSET=utf8mb4
MySQL DB charset.--CFG_MYSQL_DB_COLLATE=utf8mb4_unicode_ci
MySQL DB collation.
--CFG_MYSQL_DB_NAME=db0
MySQL DB name.
--CFG_MYSQL_DB_USERNAME=client
MySQL DB username.--CFG_MYSQL_DB_PASSWORD=[password]
Default is auto-generated.
--CFG_MYSQL_X_DB_USERNAME=x_client
MySQL external DB username.--CFG_MYSQL_X_DB_PASSWORD=[password]
Default is auto-generated.
--CFG_MYSQL_X_REQUIRES_SSL=0|1
External connections require SSL?
--CFG_INSTALL_MEMCACHE=0|1
Install Memcached?--CFG_INSTALL_RAMDISK=0|1
Install a RAM disk partition?
--CFG_INSTALL_PHP_CLI=0|1
Install PHP command-line interpreter?--CFG_INSTALL_PHP_FPM=0|1
Install PHP-FPM process manager for Apache/Nginx?--CFG_INSTALL_PHP_VERSION=[7.1|7.0|5.6|5.5]
Which PHP version to install?
--CFG_ENABLE_PHP_OPCACHE=0|1
Enable the PHP OPcache extension?--CFG_INSTALL_PHP_XDEBUG=0|1
Install PHP XDebug extension?--CFG_ENABLE_PHP_PHAR_READONLY=0|1
Force PHAR readonly mode?--CFG_ENABLE_PHP_ASSERTIONS=0|1
Enable PHP assertions?
--CFG_INSTALL_COMPOSER=0|1
Install Composer?
--CFG_INSTALL_PMA=0|1
Install PhpMyAdmin?--CFG_PMA_BLOWFISH_KEY=[key]
Blowfish key for PMA.
--CFG_INSTALL_PSYSH=0|1
Install Psysh?--CFG_INSTALL_PHPCS=0|1
Install PHP Code Sniffer?--CFG_INSTALL_PHING=0|1
Install Phing?--CFG_INSTALL_PHPUNIT=0|1
Install PHPUnit?--CFG_INSTALL_SAMI=0|1
Install Sami codex generator?--CFG_INSTALL_APIGEN=0|1
Install APIGen codex generator?--CFG_INSTALL_CACHETOOL=0|1
Install PHP-FPM cachetool?--CFG_INSTALL_WP_CLI=0|1
Install WP CLI tool?--CFG_INSTALL_WP_I18N_TOOLS=0|1
Install WP i18n tools?--CFG_INSTALL_WEBSHARKS_CORE=0|1
Install WS Core?
--CFG_INSTALL_NGINX=0|1
Install Nginx?--CFG_INSTALL_APACHE=0|1
Install Apache?
--CFG_WEB_SERVER_SSL_ONLY=0|1
Servehttps://
requests only?--CFG_MAINTENANCE_BYPASS_KEY=[key]
Bypass key in maintenance mode.
--CFG_INSTALL_CASPERJS=0|1
Install CasperJS?
--CFG_INSTALL_APP_REPO=0|1
Install a Git repo?
--CFG_INSTALL_WORDPRESS=0|1
Install WordPress?--CFG_INSTALL_WORDPRESS_VM_SYMLINKS=0|1
Install symlinks?
--CFG_INSTALL_WORDPRESS_DEV_CONTAINERS=0|1
Install WP dev containers?
--CFG_WORDPRESS_DEV_GENDER=[male|female]
WP developer gender.
--CFG_WORDPRESS_DEV_USERNAME=[username]
WP developer username.--CFG_WORDPRESS_DEV_PASSWORD=[password]
Default is auto-generated.
--CFG_WORDPRESS_DEV_NAME=[name]
WP developer name.--CFG_WORDPRESS_DEV_EMAIL=[email]
WP developer email address.
--CFG_WORDPRESS_DEV_PREFERRED_SHELL=/bin/zsh
Or/bin/bash
.--CFG_WORDPRESS_DEV_STATIC_IP_ADDRESS=[ip]
e.g.,123.456.789.0
--CFG_WORDPRESS_DEV_AUTHORIZED_SSH_KEYS=[file]
e.g.,/authorized_keys
--CFG_INSTALL_DISCOURSE=0|1
Install Discourse?
--CFG_DISCOURSE_SMTP_HOST=email-smtp.us-east-1.amazonaws.com
SMTP host name.--CFG_DISCOURSE_SMTP_PORT=587
SMTP port number.
--CFG_DISCOURSE_SMTP_AUTH_TYPE=login
SMTP authentication type.--CFG_DISCOURSE_SMTP_USERNAME=[username]
SMTP username.--CFG_DISCOURSE_SMTP_PASSWORD=[password]
SMTP password.
--CFG_INSTALL_FIREWALL=0|1
Install firewall?
--CFG_FIREWALL_ALLOWS_ADMIN_ONLY_VIA_22=0|1
Allow admin only?- Requires
--CFG_ADMIN_STATIC_IP_ADDRESS
; for production use only.
- Requires
--CFG_FIREWALL_ALLOWS_MYSQL_VIA_3306=0|1
Allow external connections to MySQL?--CFG_FIREWALL_ALLOWS_MYSQL_INSIDE_VPN=0|1
Allow network-based connections?--CFG_FIREWALL_ALLOWS_CF_ONLY_VIA_80_443=0|1
Allow only CloudFlare?
--CFG_INSTALL_FAIL2BAN=0|1
Install Fail2Ban?
--CFG_INSTALL_UNATTENDED_UPGRADES=0|1
Configure unattended upgrades?
--CFG_CONFIG_FILE=/app/.config.json
This is for any purpose you like. The value that you set here becomes a global environment variable that your application can consume. If set, it should be a configuration file path on the VM. The file does not even need to exist when configured, it's simply an environment variable that you can use elsewhere in your application later.
The vagrant-hostsupdater
plugin is the easiest way to get started. It's quite simple in that it merely updates the /etc/hosts
file in macOS. This avoids any confusion. You can just $ sudo vi /etc/hosts
and take a quick peek at what's been done after you vagrant up
for the first time.
However, unlike the more powerful Landrush plugin, vagrant-hostsupdater
doesn't automatically assign a new IP for each VM instance that you bring up. Instead, the IP is established by the Vagrantfile
, and in the Ubuntu Bootstrap (if you run the vagrant-hostsupdater
plugin), your VM's IP address will always be the default hard-coded: 192.168.42.42
You may eventually want to run multiple VMs at the same time; i.e., you'll need multiple IP addresses. To accomplish this with the vagrant-hostsupdater
plugin you'll need to edit the Vagrantfile
manually. Bump the IP from 192.168.42.42
(default), to 192.168.42.43
, 192.168.42.44
, etc. — for each of your additional VM instances.
The Landrush plugin is slightly heavier, but it's also more flexible. It spins up a small DNS server and redirects DNS traffic, automatically registering/unregistering IP addresses for VMs as they come up and go down. With Landrush there is no need to edit the Vagrantfile
manually. You can run several VMs all at the same time, all on different IPs, and without needing to edit the Vagrantfile
.
Please see: Packaging a Custom Box for full instructions.