I’ve been meaning to move my local development stack to a VM for sometime now. The hardware has come a long way and running a Linux server as a Virtual Machine with 1-2 GB of RAM allocated to it doesn’t break any sweat today. Setting up the development stack inside a VM has many advantages like you can mimic the production environment of your website/app, have more than one type of server environment on a single computer & OS, etc. I’m not going into details of it, everyone has their own preferences, running the setup directly on your computer has worked well so far & still works, so if you don’t feel like going the VM way then that’s cool too! 🙂
UPDATE: A quicker & less fussy guide to set up php development environment in a virtual machine.
There are many tutorials out there on how to go about it, this is my step by step guide, the way I did it. This guide is based on the excellent step-by-step guide written by Juan Treminio. Following are the main ingredients:
- A computer, ofcourse. I used a MacBook Pro running OS-X Lion.
- Oracle’s VirtualBox VM software – get it from here.
- A linux distro. We’ll use Ubuntu Server here. Current version is 12.04 LTS. Download the 32 bit ISO from here. Remember to download 32 bit version, the 64 bit version is kinda sluggish on less than 4GB of RAM. 32 bit version is good enough for running web development stack unless you have specific needs.
STEP 1: Install the Virtual Box and then fire it up. In the window that opens, click on the “New” icon in the toolbar.
STEP 2: When it asks for VM name & type, give a name to your VM & select Linux as Operating System & Ubuntu as version. Click Continue.
STEP 3: Allot the VM 1GB of RAM. If your computer has less than 8GB of RAM then 512MB to the VM should be fine. (You should consider increasing the RAM on your computer)
STEP 4: On the Virtual Disk Creation Wizard window, VDI should be selected by default. If it isn’t then select it & click Continue.
STEP 5: On the next screen titled “Virtual disk storage details”, select “Fixed Size” & click Continue.
STEP 6: On the next screen, allocate 20GB to your virtual disk. If you don’t have much space on HDD then 10GB should be fine. This much space has been allocated so that script files can be kept in the VM on VDI itself. If you’ll be storing them outside VDI and configuring your VM to work with them then its fine, you probably won’t need the VDI of more than 5GB in that case.
STEP 7: Now you’ll be presented with a summary of the virtual disk & Virtual Box will set it up on your HDD. It’ll take a few minutes, took about 4-5 minutes on my MacBook. You can put the coffee in the coffee maker if you want while Virtual Box is working. After its done, click the Create button & it’ll all be setup.
STEP 8: In the menu bar on top, go to Virtual Box -> Preferences and click the icon labelled “Network” in the window that opens. If you don’t see anything in the “Host-only Networks” box then click the first icon on the right which has a green plus (+) symbol, it’ll be the only one click-able. This will add a network adaptor for VMs to talk to the host OS, Mac OSX in my case. If the “Host-only Networks” box already has one or more items then you don’t need to do anything except move to next step. 🙂 Click OK to close this window.
STEP 9: So now that the VM has been created, we’ll proceed to install the Ubuntu Server operating system on it. In the Virtual Box manager window, your Ubuntu VM should already be selected, click start to launch it.
STEP 10: A new window will open and after the launch sequence, you’ll see the First Run Wizard window. Click Continue.
STEP 11: On the next window you’ll be asked to select installation media. Click the folder icon next to the drop down and browse to the folder where you downloaded the Ubuntu Server ISO. Select that ISO. Click Continue.
STEP 12: On the next window you’ll be asked to choose a language for the installation procedure. I chose English, you’re free to choose any other if you so wish. Hit the Enter key to proceed.
STEP 13: Now it’ll ask what you want to do. Default selection will be “Install Ubuntu Server”, hit Enter key to proceed. On the next screen it again asks for language, choose yours & hit Enter key.
STEP 14: Now it asks for keyboard type. If you know yours then select “No”, using your TAB key to move the selection & hit Enter key.
STEP 15: If you selected “No” in previous step then you’ll now see a list of keyboard options. Mine is “English (US)” so I selected that.
STEP 16: Now it’ll start loading up stuff. After a few seconds it’ll ask for hostname. Now this hostname is important as you’ll be using this to SSH into your VM and also to access its virtual disk for files. So enter a hostname & note it down somewhere. I gave it “ubuntu-vm” so that its easy to remember.
STEP 17: After that it’ll ask for username & password. Set those up & then it asks whether you want to have Ubuntu encrypt your home directory. We don’t need this here so select “No” & hit ENTER.
STEP 18: On the next screen it’ll ask about disk partitioning, select “Guided – use entire disk and setup LVM”.
STEP 19: On the next screen it’ll ask if you want to write partitioning scheme to disk. Select Yes to proceed. On the next screen it’ll ask the size of volume to be used, don’t change the default value & hit ENTER to proceed. On the next screen it shows the partitioning summary & will ask if you want to write the changes. Select “Yes” to proceed.
STEP 20: On the next screen it will show update options for operating system. Select “No automatic updates” & hit ENTER key.
STEP 21: Next on software installation screen, select OpenSSH server, Mail server & Samba file server. Use arrow keys to move up and down & spacebar to select/unselect an option. Hit the ENTER key to proceed. Do not select LAMP server, we’ll install Apache, PHP & MySQL later manually.
STEP 22: On the next screen it’ll ask for mail configuration. “Internet Site” will be default selection, don’t change it & hit ENTER key to proceed. Next it’ll ask if you want to install GRUB boot loader. Select “Yes” to proceed. Now it’ll install the Ubuntu Server operating system, it’ll take a while. You can go & get that coffee you left on the pot & make yourself a sandwich as well while you’re at it.
STEP 23: After several minutes the installation will be done and Ubuntu will reboot and present you with a login prompt. Login using the username & password you chose during installation and then open the network interfaces file via the following command:
[bash gutter=”no”]
sudo nano /etc/network/interfaces
[/bash]
When you have the file open, add following to the end of the file:
[text file=”/etc/network/interfaces”]
auto eth1
iface eth1 inet static
address 192.168.56.101
netmask 255.255.255.0
[/text]
and then press ^X (Control + X ) and then Y and then press ENTER key to save the file.
Here we assigned a static IP to Ubuntu so that we won’t have to check on every boot what IP has been assigned to it. Virtual Box assigns IPs in range 192.168.56.1xx, so unless you have another VM using 192.168.56.101, you should be fine with this IP here.
Now shut down the VM using following command:
[bash gutter=”no”]
sudo shutdown -h now
[/bash]
STEP 24: Now we need to setup Virtual Box network so that our VM can talk to native OS without any issues. For this we added the “Host-only network” in STEP 8 above. In the Virtual Box VM Manager, click on Settings to open our VM’s settings, then click the Network icon in toolbar and switch to Adapter 2 tab. Click the checkbox to enable it, select “Host-only Adapter” in the first drop down list. In the second drop down the adapter you added in STEP 8 should be selected by default. Click Ok.
STEP 25: Now we need to add this VM’s IP to our hosts file so that we don’t have to use the IP every time we want to connect to it. Open the Terminal & run the following:
[bash gutter=”no”]
sudo nano /private/etc/hosts
[/bash]
Add the following in the file:
[text gutter=”no” file=”/private/etc/hosts”]
192.168.56.101
[/text]
Replace <vm_hostname> with the hostname you gave when installing Ubuntu in STEP 16. Press ^X (Control + X ) and then Y and then press ENTER key to save the file. Use the following command to flush your local DNS cache:
[bash gutter=”no”]
sudo killall -HUP mDNSResponder
[/bash]
STEP 26: Now that Ubuntu is installed & we have a hosts file entry on our native OS, we can SSH into Ubuntu VM to install & configure PHP, Apache & MySQL. Start the Ubuntu VM but don’t login there. In the terminal issue the following command:
[bash gutter=”no”]
ssh
[/bash]
Replace <username> with the username you chose in Ubuntu installation in STEP 17. Replace <vm_hostname> with your hostname. You’ll be told that the server is not recognized & if you would like to continue. Select Yes and then enter the password you chose in STEP 17.
STEP 27: Now we install the basic stuff like make, curl, wget, libxml, libzip, openssl, Git, Subversion and Apache webserver. Run the following command:
[bash gutter=”no”]
sudo apt-get install gcc make wget cron curl libxml2 libxml2-dev libzip-dev libbz2-dev curl libcurl4-openssl-dev libcurl3 libcurl3-gnutls libjpeg62 libjpeg62-dev libpng12-0 libpng12-dev libmcrypt-dev libmcrypt4 libxslt1-dev libxml2-dev apache2 apache2-mpm-prefork apache2-prefork-dev apache2-utils apache2.2-common git subversion
[/bash]
After its done installing all these, issue the following command to open Apache configuration:
[bash gutter=”no”]
sudo nano /etc/apache2/httpd.conf
[/bash]
and add the following line to it:
[text gutter=”no” file=”/etc/apache2/httpd.conf”]
ServerName localhost
[/text]
Press ^X (Control + X ) and then Y and then press ENTER key to save the file. Then run the following to enable mod_rewrite in Apache and restart Apache.
[bash]
sudo a2enmod rewrite
sudo service apache2 restart
[/bash]
STEP 28: Time to install MySQL. We’ll install the latest MySQL 5.5. If you wish to install any other version please feel free.
[bash gutter=”no”]
sudo apt-get install mysql-client-5.5 mysql-server-5.5
[/bash]
It’ll ask you to set a root password, its a good idea to do so, if you don’t then that’s ok as well since this is just your development stack.
We need to setup our IP address in MySQL config so that it knows on which IP its listening for connections. Open the config file using following:
[bash gutter=”no”]
sudo nano /etc/mysql/my.cnf
[/bash]
Press ^W (Control + W) & search for “bind-address”. It’s IP will be 127.0.0.1, change the IP to 192.168.56.101. Press ^X (Control + X ) and then Y and then press ENTER key to save the file. Now login to MySQL and run the following SQL:
[mysql]
GRANT ALL ON *.* TO ‘root’@’%’;
FLUSH PRIVILEGES;
[/mysql]
Exit MySQL & restart it using the following command:
[bash gutter=”no”]
sudo service mysql restart
[/bash]
STEP 29: Now we’ll compile PHP from source. I installed PHP 5.3.x, you can install 5.4.x if you so wish. Run the following commands:
[bash]
sudo apt-get build-dep php5
wget http://us3.php.net/get/php-5.3.15.tar.gz/from/this/mirror -O php-5.3.15.tar.gz
tar -xzf php-5.3.15.tar.gz
cd php-5.3.15
./configure –with-apxs2=/usr/bin/apxs2 –with-config-file-path=/etc/php5 –with-mysql=mysqlnd –enable-inline-optimization –disable-debug –enable-bcmath –enable-calendar –enable-ctype –enable-ftp –with-gd –disable-sigchild –with-jpeg-dir=/usr –with-png-dir=/usr –with-zlib=yes –with-zlib-dir=/usr –with-openssl –with-xsl=/usr –with-mcrypt=/usr –with-mhash=/usr –enable-mbstring=all –with-curl=/usr/bin –with-curlwrappers –enable-mbregex –enable-zend-multibyte –with-bz2=/usr –with-iconv –with-pdo-mysql=mysqlnd –enable-fileinfo –with-pear –enable-exif –enable-soap –with-regex –enable-zip –with-tidy –sysconfdir=/etc –with-gettext –with-freetype-dir=/usr/include/freetype2/freetype –with-libxml-dir
make
sudo make -i install
sudo ln -s /usr/local/bin/php /usr/bin/php
[/bash]
Now run the following to create a PHP conf for Apache:
[bash gutter=”no”]
sudo nano /etc/apache2/mods-available/php5.conf
[/bash]
Add following to the file:
[ini file=”/etc/apache2/mods-available/php5.conf”]
AddType application/x-httpd-php .php .phtml .php3
AddType application/x-httpd-php-source .phps
[/ini]
Press ^X (Control + X ) and then Y and then press ENTER key to save the file. Now run the following commands to enable PHP as Apache module, copy php.ini and restart Apache.
[bash]
sudo a2enmod php5
sudo mkdir /etc/php5/
sudo cp ~/php-5.3.15/php.ini-development /etc/php5/php.ini
sudo service apache2 restart
[/bash]
Now we’ll create a folder with symlinks to Apache & PHP conf files for easy access. Run the following commands:
[bash]
cd
mkdir _lamp && cd _lamp
sudo ln -s /etc/apache2/httpd.conf
sudo ln -s /etc/apache2/sites-available/default
sudo ln -s /etc/php5/php.ini
[/bash]
Now “/home/<username>/_lamp” is the folder to go to whenever you need to edit Apache or PHP config files.
STEP 30: Now we’ll install Xdebug & configure it with PHP. Run the following commands:
[bash]
cd
git clone git://github.com/derickr/xdebug.git
cd xdebug*
phpize
./configure –enable-xdebug
make
sudo make install
[/bash]
After the installation is done, which will take a bit, issue the following commands to open php.ini:
[bash]
cd ~/_lamp
sudo nano php.ini
[/bash]
Use ^W (Control + W) to search for “error reporting” & make sure it is set to “E_ALL | E_STRICT”. Then search for “display errors”, it should be “On”. Next search for “date.timezone” and set it to your preferred time zone. You can look up list of supported time zones here. Above “date.timezone”, add the following:
[ini file=”php.ini”]
[xdebug]
zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20090626/xdebug.so
xdebug.remote_enable=1
xdebug.remote_connect_back=1
xdebug.remote_port=9000
xdebug.show_local_vars=0
xdebug.var_display_max_data=10000
xdebug.var_display_max_depth=20
xdebug.show_exception_trace=0
[/ini]
Press ^X (Control + X ) and then Y and then press ENTER key to save the file. Now run the following commands to restart Apache and to add give your user permissions to edit web root.
[bash]
sudo service apache2 restart
sudo adduser www-data
sudo usermod -a -G www-data
sudo chown -R
sudo chgrp www-data /var/www
sudo chmod –R 775 /var/www
sudo chmod g+s /var/www
[/bash]
Replace <USERNAME> with your username in the VM that you chose in STEP 17.
STEP 31: Now we’ll configure Samba File Server so that we can mount the web root in our VM in our native OS as a network folder for easy access to files. Run the following command to open Samba config file for editing:
[bash gutter=”no”]
sudo nano /etc/samba/smb.conf
[/bash]
and add the following at the end:
[ini file=”/etc/samba/smb.conf”]
[www]
comment = www
path = /var/www
public = yes
writable = yes
valid users =
create mask = 0775
directory mask = 0775
force user =
force group = www-data
follow symlinks = yes
wide links = yes
[/ini]
Replace <USERNAME> with your username in the VM that you chose in STEP 17. Press ^X (Control + X ) and then Y and then press ENTER key to save the file.
Now setup a password using the following command:
[bash gutter=”no”]
sudo smbpasswd -a
[/bash]
Replace <USERNAME> with your username in the VM that you chose in STEP 17. Run the following command to restart Samba.
[bash gutter=”no”]
sudo service smbd restart
[/bash]
In the Finder, on the menu bar click Go -> Connect to Server and in the window that opens, enter the server address smb://<vm_hostname>. Replace <vm_hostname> with the hostname of your VM that you chose in STEP 16. Click the plus (+) icon next to the box and then click Connect.
You’ll be asked which volume you’d like to mount, since we enabled only the webroot with the label “www”, that’s the only one you’ll be shown.
Now you can setup your websites/apps in Apache in the file at “~/_lamp/default”, keep your files in “/var/www”, import your databases in MySQL and start using the PHP development stack you just installed in your VM. One of the good things about mounting the webroot of the VM as a network folder in the native OS is that if you use an IDE or have a favourite code editor then you can keep it in your native OS and still use it to write code and files will be saved in the VM’s webroot. :tup: And same goes for the Git/Subversion client you might already have on your native OS. 🙂
I prefer using sshfs instead of samba though. This way there is no need for extra samba server and all communications are encrypted.
Hmm, nice, never tried it. Gotta try that. :tup:
I use SSHFS instead of Samba too. I also use vhost_alias and VirtualDocumentRoot to map subdomains to subdirectories … so creating a new project is as easy as making a new folder.
http://otaqui.com/blog/1652/setting-up-a-virtualbox-virtual-machine-for-web-development-with-multiple-sites-using-mod_vhost_alias-and-virtualdocumentroot/
Interesting trick with the vhost_alias but a bit un-practical in the sense that local dev env should be completely “local”. A dependency on external DNS defeats that purpose (for situations when you don’t have access to internet, yes that has happened to all of us at one point or another).
As for SSHFS, you actually don’t need to do it since you’re mounting a folder present on your host machine into the VM – VirtualBox will do it for you if you just specify the folder in your VM settings. See my updated guide – no Samba or SSHFS needed in there. 🙂
Thanks for the how-to, another solution is to use turnkey lamp stack, then just do the network part, however, this gets you whatever PHP version you want / need 🙂
Never tried TurnKey LAMP Stack but I think using PHP version of choice would be possible there as well since its just a linux VM, so you should be able to upgrade/downgrade to any PHP version. :tup:
Nice detailed writeup. looking forward to using this with my WordPress development.
Hey, great step by step tutorial. So far I have always programmed under windows before deploying to production, so sometimes it was rather difficult to adapt tutorials written for linux to windows.
maybe you’d like to integrate your tutorial for windows users on the specific step of hooking up the samba share.
for windows, open up a cmd interface and type
net use z: \\ubuntu-vm\www [user password you entered in step 17] /USER:[username entered in step 17]
There are 2 items I was unable to get to work.
Most important, php does not speak to mysql. I can connect to mysql server via CLI with mysql -uroot with no problem, but php does not connect to mysql. Error reported is “Connect Error (2002) No such file or directory”.
Googling, it seems to involve mysql.sock, but I don’t seem to be able to make it work.
I followed your tutorial step by step … any suggestions on where to look? ❓ much appreciated!
This is one issue that a number of people reported, compiling PHP & installing MySQL on your own, the MySQL socket file needs to be found & either symlink needs to be created where PHP is looking for it or PHP config needs to be modified to look for the sock file in right place. For this & some other reasons (apache user config, dir permissions become a bitch) I wrote another step by step which is much easier & works smoothly. Perhaps you should check that out. 🙂
The new step by step I mentioned above doesn’t require you to setup samba share at all. You use shared folders for your web apps you want to run in apache & for accessing any system files in host OS, just use ssh. So thats one less daemon to run & worry about. 😉
But if you do want to run samba then map it as a network drive in Windows, its pretty easy. 🙂
Hey Amit, thanks for the quick feedback. Checking your new tut now (if connection stabilizes)
BTW, I am not really proficient with apache and stuff – the other “issues” I encountered with the old tutorial that maybe the new tut addressed are:
1) found no way to make xdebug run
2) a problem with installing the Laravel framework through Composer – it seems curl wrappers get in the way of a proper install. so I recompiled php without the curlwrappers and was able to proceed with the install. Just wanted to give a heads-up that maybe has already been addressed.
3) question – did I get something wrong or old tutorial seemed to be running mysql instead of mysqli?
Thanks again .. trying to make a new VM right now! 😎
You mean you weren’t able to install it or use it to debug your app? Installing it is quite straight forward; clone the git repo, compile it & then load it up in php.ini (with correct path to xdebug.so).
In the new version of the tut, LAMP stack is installed as default when installing ubuntu, so it works out of the box. Curl is installed afterwards & you will need to enable it for PHP yourself. 😉