Codeup Vagrant & Ansible Configuration
This repository contains configuration files intended for Codeup students to use throughout their class. It contains:
- A Vagrantfile for local development and testing of web based applications
- Ansible playbooks for provisioning development and production servers, and deploying those applications. Primarily targetting servers hosted by DigitalOcean
Installation & Setup
One of the goals for this environment is make set up as simple and straight forward as possible.
The easiest way to get started with this repository is using the LAMP Setup Script hosted in Codeup's GitHub account. In addition to installing the necessary tools and utilities, it will also create an SSH key for Ansible to use with DigitalOcean droplets.
Our environment depends on three third party utilities:
To install these on your Mac, we recommend using Homebrew. Run the following commands in your Terminal or iTerm:
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Use Homebrew to install Ansible
brew install ansible
Use Homebrew to install Cask
brew install caskroom/cask/brew-cask
Use Homebrew Cask to install Vagrant and VirutalBox
brew cask install vagrant brew cask install virtualbox
Clone this repository,
cdinto it, and start the Vagrant box with
Both the Vagrant and production servers can be managed with Ansible using what are called "playbooks". Our playbooks are located in the directory
ansible/playbooks. The available playbooks are:
ansible/playbooks +-- vagrant | +-- init.yml | +-- sites | | +-- hhvm.yml | | +-- node.yml | | +-- php.yml | | +-- python2.yml | | +-- python3.yml | | +-- ruby.yml | | +-- static.yml | +-- mysql | | +-- admin.yml | | +-- database.yml | | +-- app | | +-- hhvm.yml | | +-- php.yml | | +-- python2.yml | | +-- python3.yml | | +-- ruby.yml | | +-- wordpress.yml | +-- postgres | | +-- admin.yml | | +-- database.yml | | +-- app | | +-- php.yml | | +-- python2.yml | | +-- python3.yml | | +-- ruby.yml | +-- mongodb | +-- admin.yml | +-- database.yml | +-- app | +-- node.yml +-- production | +-- init.yml | +-- enable-root.yml | +-- sites | | +-- hhvm.yml | | +-- node.yml | | +-- php.yml | | +-- python.yml | | +-- ruby.yml | | +-- static.yml | +-- mysql | | +-- install.yml | | +-- admin.yml | | +-- database.yml | | +-- app | | +-- hhvm.yml | | +-- php.yml | | +-- python.yml | | +-- ruby.yml | | +-- wordpress.yml | +-- postgres | | +-- install.yml | | +-- admin.yml | | +-- database.yml | | +-- app | | +-- php.yml | | +-- python.yml | | +-- ruby.yml | +-- mongodb | +-- install.yml | +-- admin.yml | +-- database.yml | +-- app | +-- node.yml +-- warpspeed | +-- init.yml | +-- sites | | +-- node.yml | | +-- php.yml | | +-- python.yml | | +-- ruby.yml | | +-- static.yml | +-- mysql | | +-- admin.yml | | +-- database.yml | | +-- app | | +-- php.yml | | +-- python.yml | | +-- ruby.yml | +-- postgres | +-- admin.yml | +-- database.yml | +-- app | +-- php.yml | +-- python.yml | +-- ruby.yml +-- deploy +-- node.yml +-- php.yml +-- python.yml +-- ruby.yml
You should not run the
init.yml playbook by hand; this is done the first time your run
vagrant up or by running
Our Vagrant environment supports creating virtual hosts running PHP (either "static" or "dynamic"), Facebook's HipHop VM, Ruby, Node.js, or Python (either versions 2.7 or 3.4). To create a new site, run one of the following playbooks:
# Static PHP Site ansible-playbook ansible/playbooks/vagrant/site/static.yml # Dynamic PHP Site ansible-playbook ansible/playbooks/vagrant/site/php.yml # HipHop VM Site ansible-playbook ansible/playbooks/vagrant/site/hhvm.yml # Node.js Site ansible-playbook ansible/playbooks/vagrant/site/node.yml # Python 2.7 Site ansible-playbook ansible/playbooks/vagrant/site/python2.yml # Python 3.4 Site ansible-playbook ansible/playbooks/vagrant/site/python3.yml # Ruby Site ansible-playbook ansible/playbooks/vagrant/site/ruby.yml
These playbooks will first prompt you for a new domain name (all domains in the Vagrant environment must end with
.dev), install any necessary software, create the required configuration files, and then restart Nginx, if needed.
Static vs. Dynamic
A "dynamic" PHP site will route all requests for missing files through
index.php. This is useful for frameworks such as Laravel. If you are not using such a framework, a "static" site will still execute any PHP file requested directly.
We have included playbooks for managing MySQL, PostgreSQL, and MongoDB database servers. You can use the playbooks either to create a new administrator or databases in any one of these. By default, when these servers are created, Ansible will create a default administrator with the username
vagrant and password
vagrant. (Do not delete the
vagrant user from any of these database servers, otherwise Ansible will no longer be able to manage that service.)
To create a new database administrator in either MySQL, PostgreSQL, or MongoDB run one of the following playbooks:
# MySQL ansible-playbook ansible/playbooks/vagrant/mysql/admin.yml # PostgreSQL ansible-playbook ansible/playbooks/vagrant/postgres/admin.yml # MongoDB ansible-playbook ansible/playbooks/vagrant/mongodb/admin.yml
You will first be prompted for a new username and password for your administrator. Ansible will then install any required software and create the requested user.
To create a new database in one of the services, run the playbook for the required database type:
# MySQL ansible-playbook ansible/playbooks/vagrant/mysql/database.yml # PostgreSQL ansible-playbook ansible/playbooks/vagrant/postgres/database.yml # MongoDB ansible-playbook ansible/playbooks/vagrant/mongodb/database.yml
Ansible will prompt you for the database name, followed by a username and password for an "owner" of that database. Owners are dedicated users that have full control over that database, but no access outside of it. Administrator have access to all databases.
In addition, there are several shortcut playbooks for creating a database and a new site with a single command. These are under the
app directory for each type of database. Since not all languages support or are well suited for each database flavor, only a subset of sites are available for a given database service.
# PHP and MySQL App ansible-playbook ansible/playbooks/vagrant/mysql/app/php.yml # Wordpress App (this will create a PHP app and download the latest version of Wordpress into it) ansible-playbook ansible/playbooks/vagrant/mysql/app/wordpress.yml # HipHop VM and MySQL App ansible-playbook ansible/playbooks/vagrant/mysql/app/hhvm.yml # Python 2.7 and MySQL App ansible-playbook ansible/playbooks/vagrant/mysql/app/python2.yml # Python 3.4 and MySQL App ansible-playbook ansible/playbooks/vagrant/mysql/app/python3.yml # Ruby and MySQL App ansible-playbook ansible/playbooks/vagrant/mysql/app/ruby.yml # PHP and PostgreSQL App ansible-playbook ansible/playbooks/vagrant/postgres/app/php.yml # Python 2.7 and PostgreSQL App ansible-playbook ansible/playbooks/vagrant/postgres/app/python2.yml # Python 3.4 and PostgreSQL App ansible-playbook ansible/playbooks/vagrant/postgres/app/python3.yml # Ruby and PostgreSQL App ansible-playbook ansible/playbooks/vagrant/postgres/app/ruby.yml # Node.js and MongoDB App ansible-playbook ansible/playbooks/vagrant/mongodb/app/node.yml
These playbooks will first prompt you for a new domain name, followed by a database name, and then the username and password for that database's owner.
Ansible can be used to manage a production server much in the same way as your Vagrant environment. Our instructions are geared towards Digital Ocean servers, but these playbooks should all work with any server running Ubuntu 14.04 (or later).
Adding your SSH Key
If you used the LAMP Setup Script you should have an SSH key generated for you. You must add that key to your DigitalOcean account in order to connect to your server. To do this, follow these steps
- Copy your public key using
cat ~/.ssh/id_rsa.pub | pbcopy.
- Navigate to the security settings page DigitalOcean.
- Click "Add SSH Key"
- Give your key a name (such as "Codeup SSH Key") and then paste your key data into the form.
- Save your changes
Creating a Droplet
- Click the Create Droplet button
- Give your server a hostname, such as "Codeup-Server"
- Typically, we suggest using the base droplet size ($5 / month)
- We suggest using either the New York or San Fransisco data centers
- Chose Ubuntu 14.04 x64 as the image.
- Make sure to add your SSH key to your new droplet!
- Click create and then wait.
- Make note of your droplet's new IP address
Ansible needs to know what your droplet's IP address is and how to connect to it. Open the file
ansible/hosts/production. The second line in there should initially be commented out. Remove the leading
; to make the line active and replace the
xxx.xxx.xxx.xxx with your droplet's IP address. Everything else in this file should be fine.
You will need to use Ansible to create a user account for you on the server, as well as install our core software and configuration files. This is a one-time process. Run the following playbook:
You will be prompted for a new sudo password, database admin password, and an eMail address for notifications. Ansible will create an admin user on the server with the same username as your local computer. It will also create a MySQL administrator with the same username. If you are unsure what your computer username is, you can run the command
There is also a playbook to re-enable the root user in production. In most cases, this will not ever be needed and is only included for debugging and development purposes.
# Re-enable the root user; you should NOT need to run this ansible-playbook ansible/playbooks/production/enable-root.yml
Because Ansible uses your username to create the production user account, to log in to your server all you need to do is run
ssh xxx.xxx.xxx.xxx where the
xxx.xxx.xxx.xxx is your server's IP address.
Ansible can provision the same types of sites in production as in your Vagrant environment. (Note: Production Python sites use virtualenv, and will use whatever Python binary is included in the environment. Thus, there is no distinction between creating Python 2.7 or 3.4 virtual host.)
# Static PHP Site ansible-playbook ansible/playbooks/production/site/static.yml # Dynamic PHP Site ansible-playbook ansible/playbooks/production/site/php.yml # HipHop VM Site ansible-playbook ansible/playbooks/production/site/hhvm.yml # Node.js Site ansible-playbook ansible/playbooks/production/site/node.yml # Python Site ansible-playbook ansible/playbooks/production/site/python.yml # Ruby Site ansible-playbook ansible/playbooks/production/site/ruby.yml
These playbooks will first prompt you for your Sudo password. This is the password you created when initializing your production site. Next you will be asked for the site's domain name, just like with the Vagrant playbooks. Ansible will then install any necessary software and create the required config files.
Ansible can be used to install and/or manage either MySQL, PostgreSQL, or MongoDB database servers in production. However, unlike the Vagrant environment database services must be expressly installed if needed. By default, MySQL server is installed when your server is first set up, but neither PostgreSQL or MongoDB are.
To install any one of the three supported database servers, run the relevant Ansible playbook:
# Install MySQL Server ansible-playbook ansible/playbooks/production/mysql/install.yml # Install PostgreSQL Server ansible-playbook ansible/playbooks/production/postgres/install.yml # Install MongoDB Server ansible-playbook ansible/playbooks/production/mongodb/install.yml
These playbooks will first prompt you for your sudo password (which you set up when first creating the server itself) followed by a password for the database administrator. In all three cases, Ansible will create an administrator in the database server with the same username as your local computer, and your production server itself.
If you need to create additional database administrators, you can do so with the following playbooks:
# Create MySQL Administrator ansible-playbook ansible/playbooks/production/mysql/admin.yml # Create PostgreSQL Administrator ansible-playbook ansible/playbooks/production/postgres/admin.yml # Create MongoDB Administrator ansible-playbook ansible/playbooks/production/mongodb/admin.yml
These playbooks will prompt you for the database password you created when install the servers, followed by the new administrator username and password.
Ansible can be used to create a database in any one of the three database servers, just like the Vagrant environment
# Create MySQL Database ansible-playbook ansible/playbooks/production/mysql/database.yml # Create PostgreSQL Database ansible-playbook ansible/playbooks/production/postgres/database.yml # Create MongoDB Database ansible-playbook ansible/playbooks/production/mongodb/database.yml
Like with creating administrators, the playbooks will prompt you for your database password, followed by the name of the new database and a username & password for the database owner.
Note: Ansible will not allow you to create database users with blank passwords in production!
Just like the Vagrant playbooks, there are "shortcut" playbooks for creating production sites and databases with a single command:
# PHP and MySQL App ansible-playbook ansible/playbooks/production/mysql/app/php.yml # Wordpress App (this will create a PHP app and download the latest version of Wordpress into it) ansible-playbook ansible/playbooks/production/mysql/app/wordpress.yml # HipHop VM and MySQL App ansible-playbook ansible/playbooks/production/mysql/app/hhvm.yml # Python and MySQL App ansible-playbook ansible/playbooks/production/mysql/app/python.yml # Ruby and MySQL App ansible-playbook ansible/playbooks/production/mysql/app/ruby.yml # PHP and PostgreSQL App ansible-playbook ansible/playbooks/production/postgres/app/php.yml # Python and PostgreSQL App ansible-playbook ansible/playbooks/production/postgres/app/python.yml # Ruby and PostgreSQL App ansible-playbook ansible/playbooks/production/postgres/app/ruby.yml # Node.js and MongoDB App ansible-playbook ansible/playbooks/production/mongodb/app/node.yml
You will be asked for:
- Your server's sudo password
- The new domain name
- Your database administrator password
- The new database name
- A username for the database owner
- The password for the database owner
If you have created a server using Warpspeed some of your server's features can be managed using Ansible. First though, you must tell Ansible that your server uses Warpspeed. Open
ansible/hosts/production. At the end of the file you should see the following:
# ... [warpspeed] ; digital_ocean ansible_ssh_user=warpspeed
Delete the semicolon (
;) from the beginning of the last line. Now, our playbooks will know your server was created with Warpspeed. Ansible requires some additional software be installed in your server to manage it. To do this, run the following playbook:
Ansible will ask for your sudo password. This password was eMailed to you when you first created the server.
If you would like, Ansible can be used to create virtual hosts in your Warpspeed server. The following playbooks can be used to create a site in your Warpspeed server:
# Static Site ansible-playbook ansible/playbooks/warpspeed/site/static.yml # Dynamic PHP Site ansible-playbook ansible/playbooks/warpspeed/site/php.yml # HipHop VM Site ansible-playbook ansible/playbooks/warpspeed/site/hhvm.yml # Node.js Site ansible-playbook ansible/playbooks/warpspeed/site/node.yml # Python Site ansible-playbook ansible/playbooks/warpspeed/site/python.yml # Ruby Site ansible-playbook ansible/playbooks/warpspeed/site/ruby.yml
Like the normal production playbooks, Ansible will ask for your sudo password (from your welcome eMail) followed by your new domain name.
- Unlike servers provisioned by Ansible, static sites in Warpspeed cannot execute PHP code.
- Warpspeed does not support the latest version(s) of Python, only 2.7.
- Warpspeed does not include support for Facebook's HipHop VM.
A subset of our database playbooks are supported in Warpspeed. You can use Ansible to manage either MySQL or PostgreSQL database servers:
# Create a MySQL Administrator ansible-playbook ansible/playbooks/warpspeed/mysql/admin.yml # Create a MySQL Database ansible-playbook ansible/playbooks/warpspeed/mysql/database.yml # Create a PostgreSQL Administrator ansible-playbook ansible/playbooks/warpspeed/postgres/admin.yml # Create a PostgreSQL Database ansible-playbook ansible/playbooks/warpspeed/postgres/database.yml
These playbooks are nearly identical to those for managing production database servers. They will prompt you for the database administrator password. As with the sudo password, this was sent to you via eMail.
- Just like with the other sets of playbooks, there are also Warpspeed app playbooks for creating PHP, Python, or Ruby sites along side a database.
- Because Warpspeed uses an outdated version of MongoDB, Ansible cannot be used to manage it, nor can Warpspeed's MongoDB server be easily locked down.
- The production database playbooks take several steps to secure your servers that are incompatible with Warpspeed, therefore it is not advisable to use the production database playbooks.
When a site is created in production, a remote git repository is also created on your server for pushing code to. Ansible will output a couple of instructions for adding the remote to your local repository and pushing your site to it. The remote URL will look like the following:
When you push your repository to the server, your code will be put in the directory
[production-domain] is your site's domain name. If you need to do any additional steps to manage your application, such as editing config files or migrating databases, you can
ssh to your server,
cd to the site's directory, and manage your application from there.
To simplify common deployment tasks, there are four automated deployment playbooks included. These playbooks are designed to deploy web applications written with most popular web application frameworks, including:
- Laravel (versions 4 or 5)
To use automated deployment, you must first create a "site vars" file. Site vars are stored in
ansible/site_vars and are written in YAML. In that directory you will find a
template.yml. Make a copy of this file and name it after you site (such as
blog.yml). In your new site vars file, you must fill in the local domain, production domain, and site type values. If your application depends on any environment variables (such as API keys or database credentials) you can fill those in under the
env_vars entry. Lastly, if your application is written in Python, you must specify if it uses either version 2.7 or 3.4. Once you are done, save your site vars file. To deploy run one of the four deployment playbooks in
# Deploy an application written in Laravel 4, 5, or Lumen ansible-playbook ansible/playbooks/deploy/php.yml # Deploy an application written in Express.js or Sails.js ansible-playbook ansible/playbooks/deploy/node.yml # Deploy an application written in Django or Flask ansible-playbook ansible/playbooks/deploy/python.yml # Deploy an application written in Rails or Sinatra ansible-playbook ansible/playbooks/deploy/ruby.yml
The playbook will prompt you for your site's name, meaning the site vars file name you created without the
.yml extension. Ansible will read your site vars file, do some basic validation, and then perform the following steps:
- Add the remote to your local git repository
- Push your site to production
- Install any Node or Bower dependencies
- Run the default Gulp and/or Grunt tasks
- Install your framework's dependencies (based on
- Add the environment variables to the site configs
- Migrate the database, if necessary
The goal of these playbooks was to perform as many of the typical application setup steps as possible, while minimizing the risk to existing data. They will not, therefore, do any database seeding even if your framework supports it. You must seed your database by hand.
Vagrant Enhancements (Optional)
The Vagrantfile includes support for some optional Vagrant plugins that can make development quicker and easier. These plugins are not required, but can be useful.
vagrant-vbguest plugin can automatically update VirtualBox's software in the guest OS. To install, run the following on your Mac:
vagrant plugin install vagrant-vbguest
Your Mac can be configured to resolve any domain ending in
.dev to the Vagrant server. To do this, you must install the
vagrant-dns plugin. First, install the plugin itself:
vagrant plugin install vagrant-dns
Then, from the directory containing your vagrant environment, run:
vagrant dns --install
Note: This feature can cause conflicts if two or more Vagrant boxes are running with the same configuration. Use this feature with caution if you have multiple Vagrant environments.
To speed up installation of dependencies and OS packages, you can use the plugin
vagrant-cachier. This plugin is configured to cache downloaded software on your local Mac, so that future requests for those files will be resolved from your computer rather than the internet. To install, just run:
vagrant plugin install vagrant-cachier
Then, if your Vagrant environment is already running restart it with:
Passwordless NFS Export
For optimal performance, your Mac shares files with the Vagrant environment using NFS. Unfortunately, this requires typing in your password each time you start the box. To avoid this, you can edit your
/etc/sudoers file to grant access to Vagrant's NFS commands without prompting for a password.
Run the following and type in your password when prompted
Shift + Gto move to the end of the file
oto create a new line and start editing.
Paste the following lines into the file
Cmnd_Alias VAGRANT_EXPORTS_ADD = /usr/bin/tee -a /etc/exports Cmnd_Alias VAGRANT_NFSD = /sbin/nfsd restart Cmnd_Alias VAGRANT_EXPORTS_REMOVE = /usr/bin/sed -E -e /*/ d -ibak /etc/exports %admin ALL=(root) NOPASSWD: VAGRANT_EXPORTS_ADD, VAGRANT_NFSD, VAGRANT_EXPORTS_REMOVE
Escto leave editing mode
:wqto save the file and exit Vi.
The next time you start your box, you should not need to enter your password.