Dead Simple provisioning for Ruby on Rails & MySQL with Vagrant and Centos 6.6

Dead Simple provisioning for Ruby on Rails & MySQL with Vagrant and Centos 6.6

One of the hardest things about getting started with Vagrant is the time it takes develop a good provisioning system for the virtual machine. Many people reach to Chef or Ansible too quickly and become overwhelmed by complexity. It was recently suggested that one start with a simple provision script.

Here is a provision script that I used recently to config a Centos 6.6 vm.

#!/bin/bash
# Install dependent packages
sudo yum update
sudo yum install -y apr-devel apr-util-devel autoconf automake curl-devel \
g++ gcc gcc-c++ git glibc-headers httpd-devel libxml2 \
libxml2-devl libxslt libxslt-devel libyaml-devel make \
mysql-devel mysql-server openssl-devel patch readline \
readline-devel zlib zlib-devel
if ! [ -d /home/vagrant/.rbenv ]; then
echo "Installing rbenv"
git clone git://github.com/sstephenson/rbenv.git ~/.rbenv
git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
echo "export PATH=\$HOME/.rbenv/bin:\$PATH" >> /home/vagrant/.bash_profile
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
source ~/.bash_profile
rbenv install 2.2.2
rbenv rehash
rbenv global 2.2.2
gem update --system
gem install bundler
fi
echo "Gem home is $GEM_HOME"
echo "Path is $PATH"
MYSQL_RUNNING=$(service mysqld status | egrep "mysql.*running" | wc -l)
if [ "$MYSQL_RUNNING" -ne 1 ]; then
echo 'Starting Mysql'
sudo /sbin/service mysqld start
sudo /sbin/chkconfig mysqld on
fi
DATABASE_YML="/vagrant/config/database.yml"
APP_DB_USERNAME="blog_user"
APP_DB_PASSWORD="blog_user91x91x"
if [ -f $DATABASE_YML ];
then
echo "File $DATABASE_YML exists."
else
echo "File $DATABASE_YML does not exist, creating."
read -r -d '' CREATE_USER_SQL <<_EOF_
CREATE USER '$APP_DB_USERNAME'@'localhost' IDENTIFIED BY '$APP_DB_PASSWORD';
CREATE USER '$APP_DB_USERNAME'@'%' IDENTIFIED BY '$APP_DB_PASSWORD';
GRANT ALL PRIVILEGES ON *.* TO '$APP_DB_USERNAME'@'localhost' WITH GRANT OPTION;
GRANT ALL PRIVILEGES ON *.* TO '$APP_DB_USERNAME'@'%' WITH GRANT OPTION;
_EOF_
echo "Creating mysql user:"
echo $CREATE_USER_SQL
mysql -uroot -e "$CREATE_USER_SQL"
cat > $DATABASE_YML <<_EOF_
default: &default
adapter: mysql2
encoding: utf8
reconnect: false
pool: 5
username: $APP_DB_USERNAME
password: $APP_DB_PASSWORD
host: localhost
development:
<<: *default
database: blog_development
test:
<<: *default
database: blog_test
production:
<<: *default
database: blog_production
_EOF_
fi
echo "Installing gems"
cd /vagrant
bundle install
bundle exec rake db:create:all --trace
bundle exec rake db:migrate --trace
view raw provision.sh hosted with ❤ by GitHub

Here is the Vagrantfile:

# Host => Guest (VM)
FORWARD_PORTS = {
3000 => 3000, # webrick
13_306 => 3306 # MySQL
}
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure(2) do |config|
config.vm.box = 'opscode_centos-6.6'
config.vm.provider :virtualbox do |_f, override|
override.vm.box_url = 'https://s3.amazonaws.com/centos-vagrant/opscode_centos-6.6_chef-provisionerless.box'
end
config.ssh.password = 'vagrant'
config.vm.provision :shell, path: 'provision.sh', privileged: false
config.vm.synced_folder(
'.',
'/vagrant',
type: 'rsync',
rsync__exclude: [
'.git/',
'.vagrant/',
'config/database.yml',
'log/*',
'tmp/'
]
)
FORWARD_PORTS.each do |host, guest|
config.vm.network :forwarded_port, host: host, guest: guest
end
end
view raw Vagrantfile hosted with ❤ by GitHub

You will notice in the Vagrantfile that we forward the MySQL port 3306 to 13306. I still want to connect to the MySQL database on the vm from my local machine so to this I update the my local database.yml.

default: &default
adapter: mysql2
encoding: utf8
reconnect: false
pool: 5
port: 13306
username: blog_user
password: blog_user91x91x
host: localhost
development:
<<: *default
database: blog_development
test:
<<: *default
database: blog_test
production:
<<: *default
database: blog_production
view raw database.yml hosted with ❤ by GitHub

I can now run commands like bundle exec rake db:migrate on my local machine. Since it can modify files, this is preferred. I run the server as well my rspecs on the vagrant box. During development, I have an rsync command running as follows to sync my file changes down to the local machine.

vagrant rsync-auto

Next time, I can show how this same setup can be done with PostgreSQL.

Contents