###Initial installation and configuration Install Git for Windows which includes Git Bash.
Install VirtualBox and Vagrant.
Note: Do not install VirtualBox 5.0 and Vagrant 1.7.4. At the moment these versions are causing problems that I've been unable to solve with this Gist. Use the previous versions instead. VirtualBox 4.3.30 and Vagrant 1.7.3.
In Git Bash (always run as administrator), type cd ~
to get to your "home" directory, ie.C:\Users\David
, and run these commands:
$ vagrant box add laravel/homestead
When prompted: choose option #1: virtualbox. Now clone (and let's do PHP 7):
$ git clone -b php-7 https://github.com/laravel/homestead.git Homestead
Now navigate to the Homestead directory and run the bash init.sh
command to create the Homestead.yaml
configuration file:
$ bash init.sh
Create your SSH keys using Git bash. I like to have the keys (.ssh
folder) in the "home" directory as well. ie. C:\Users\David\.ssh
:
$ ssh-keygen -t rsa -C "david@homestead"
(and then just press [enter] through each prompt)
Note: If you are using PhpStorm, you may already have an ssh key made. You could use that one if you wish. Just update the ssh section of your Homestead.yaml file to point to that key.
Now here is my C:\Users\David\.homestead\Homestead.yaml
file with some adjustments I made, and with things pointing to the ~
home directory:
(You may use the absolute Windows path instead of what I have done with ~/projects/example
here, just make sure you capitalize the drive letter)
---
ip: "192.168.10.10"
memory: 3072
cpus: 1
provider: virtualbox
authorize: ~/.ssh/id_rsa.pub
keys:
- ~/.ssh/id_rsa
folders:
- map: ~/projects/example
to: /home/vagrant/example
sites:
- map: my-homestead-blog.loc
to: /home/vagrant/example/blog/public
databases:
- homestead
variables:
- key: APP_ENV
value: local
This example will look for a folder at C:\Users\David\projects\example
, so ensure you have created that folder there.
(Note: Be careful you don't add Tabs when editing Homestead.yaml)
###Shared mounted folder configuration and Laravel install
Run the guest box additions plugin and the winnfsd plugin (in Git bash):
$ vagrant plugin install vagrant-vbguest
$ vagrant plugin install vagrant-winnfsd
And add/update these parts of your C:\Users\David\Homestead\scripts\homestead.rb
file like this:
# Add this new section
# Reorder folders for winnfsd plugin compatilibty
# see https://github.com/GM-Alex/vagrant-winnfsd/issues/12#issuecomment-78195957
settings["folders"].sort! { |a,b| a["map"].length <=> b["map"].length }
# Configure A Few VirtualBox Settings
config.vm.provider "virtualbox" do |vb|
vb.name = 'homestead'
vb.customize ["modifyvm", :id, "--memory", settings["memory"] ||= "2048"]
vb.customize ["modifyvm", :id, "--cpus", settings["cpus"] ||= "1"]
vb.customize ["modifyvm", :id, "--natdnsproxy1", "on"]
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
vb.customize ["modifyvm", :id, "--ostype", "Ubuntu_64"]
# add this to turn on symlink ability (so we can do 'npm installs')
vb.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/v-root", "1"]
end
# Register All Of The Configured Shared Folders
if settings.include? 'folders'
settings["folders"].each do |folder|
mount_opts = []
if (folder["type"] == "nfs")
mount_opts = folder["mount_opts"] ? folder["mount_opts"] : ['actimeo=1']
end
# config.vm.synced_folder folder["map"], folder["to"], type: folder["type"] ||= nil, mount_options: mount_opts
# add this manual mount option line:
config.vm.synced_folder folder["map"], folder["to"], :nfs => { :mount_options => ["dmode=777","fmode=777"] }
end
end
To fix the issue with long path names in Windows:
- Update
C:\HashiCorp\Vagrant\embedded\gems\gems\vagrant-1.7.3\plugins\providers\virtualbox\driver\version_4_3.rb
near line 499 by replacing the hostpath declaration to look like this now (and notice the if condition below is now commented out):
def share_folders(folders)
folders.each do |folder|
hostpath = '\\\\?\\' + folder[:hostpath].gsub(/[\/\\]/,'\\')
#if Vagrant::Util::Platform.windows?
# hostpath = Vagrant::Util::Platform.windows_unc_path(hostpath)
#end
- Update
C:\HashiCorp\Vagrant\embedded\gems\gems\vagrant-1.7.3\lib\vagrant\util\platform.rb
and comment out a big part of this section starting near line 111, like this:
```
# This expands the path and ensures proper casing of each part
# of the path.
def fs_real_path(path, **opts)
#path = Pathname.new(File.expand_path(path))
#
# if path.exist? && !fs_case_sensitive?
# # Build up all the parts of the path
# original = []
# while !path.root?
# original.unshift(path.basename.to_s)
# path = path.parent
# end
#
# # Traverse each part and join it into the resulting path
# original.each do |single|
# Dir.entries(path).each do |entry|
# if entry.downcase == single.encode('filesystem').downcase
# path = path.join(entry)
# end
# end
# end
#end
#
# if windows?
# # Fix the drive letter to be uppercase.
# path = path.to_s
# if path[1] == ":"
# path[0] = path[0].upcase
# end
#
# path = Pathname.new(path)
#end
path
end
```
Now navigate to your ~/Homestead directory in Git bash and vagrant up
. (if you get a strange error, run vagrant up
once more and you should be good. I'll look into this strange behavior later.)
Note: you won't be able to manage the homestead box using the VirtualBox manager GUI since you'll need this 'vagrant up' configuration each time. Use vagrant halt
to power-down and vagrant up
to restart. If you need to destroy it and start all over, do vagrant destroy --force
followed by another vagrant up
.
Then vagrant ssh
and go into your example folder and install Laravel or Lumen (I'm installing Lumen here):
$ composer global require "laravel/lumen-installer=~1.0"
$ lumen new blog
Now navigate to: http://localhost:8000. You should update your C:\Windows\System32\drivers\etc\hosts
file to use the site name like you specificed in your Homestead.yaml file:
192.168.10.10 www.my-homestead-blog.loc
Note: If you see "no input file specified", then nginx can't find any file for your site. Probably your Homestead.yaml sites "to" path is not matching were your actual public folder is for Laravel or Lumen.
###NPM Install problems
You will most surely have problems with sudo npm install
on the ubuntu guest machine, in the shared folder. You may get problems like:
- symlink input/output error
- Cannot find module 'laravel-elixir'
- and more
Here's what to do:
- Before you do these steps, you need to ensure you have opened Git Bash with 'run as administrator'.
- Now create a folder outside of the shared folder (just create some folder one level up from the shared folder), and manually create a
package.json
file there (just manually re-type the file, don't perform acp
command), and runsudo npm install
there. - If you mess up for some reason and need to remove the node_modules folder with a
sudo rm -rf node_modules
, it may fail on first try, but try running the command again. - Then change directories to your Laravel/Lumen project folder (that has the
composer.json
file in it) and now run the symlink command (you must be inside the shared folder for symlinking command to work):
sudo ln -s /home/vagrant/some-folder/node_modules node_modules
- Now you can run
gulp
(run it withoutsudo
):
gulp --production
You'll need to perform all npm installs in the folder you created above (ie. /home/vagrant/some-folder/). Here's some useful gulp plugins you might want to install:
sudo npm install gulp-less
sudo npm install gulp-minify-css
sudo npm install gulp-uglify
sudo npm install gulp-concat
sudo npm install gulp-add-src
sudo npm install gulp-sourcemaps
###How can I also get a public IP Address on the network?
- Just go to your command prompt (cmd.exe) in Windows and do:
ipconfig
to get your host's IP (ie. 192.168.x.x). Then, from any other pc on the network, enter the host IP address followed by a:8000
to access the VM/site (ie. 192.168.x.x:8000/foo/bar).
###Caching issues
-
Update
/etc/nginx/nginx.conf
to havesendfile off;
-
Then find the location of opcache.so:
$ sudo find / -name 'opcache.so' /usr/lib/php5/20131226/opcache.so`
-
Add the following to opcache.ini:
$ sudo nano /etc/php5/mods-available/opcache.ini zend_extension=/usr/lib/php5/20131226/opcache.so opcache.memory_consumption=128 opcache.interned_strings_buffer=8 opcache.max_accelerated_files=4000 opcache.revalidate_freq=0 opcache.validate_timestamps=on opcache.fast_shutdown=1
-
Update the timezone:
sudo dpkg-reconfigure tzdata
-
Update the time so it's older than the host OS. You will have to do this each time you
vagrant up
your box if your box's time loses sync (I'm currently not experiencing this issue on Windows 8.1.). If your Host OS is at 11:01:00, then set your VM to:$ sudo date --set 11:00:50 $ sudo service nginx restart // You can set the full date with: // $ sudo date --set "Thu, 4 Jun 2015 11:00:50"
-
For local/developing environment, you can add/update your lumen
.env
file on your local machine to cache usingarray
like so:APP_ENV=local APP_DEBUG=true ... CACHE_DRIVER=array ...
-
In Laravel, you can run
php artisan clear-compiled
(the opposite of optimize) to clear vendor/compiled.php and other things. You can also runphp artisan cache:clear
in Lumen and Laravel. -
If you are using HHVM, I've not confirmed if HHVM caches anything that would be problematic for developer working local, but try without it (re-serve your site).
Note: For Lumen, in your bootstrap file, make sure you have Dotenv::load(__DIR__.'/../');
uncommented in the file so you can use your .env settings
###HHVM
####Changing a site to HHVM
$ cd /etc/nginx/sites-enabled
$ sudo rm your-site.app
$ cd /etc/nginx/sites-available
$ sudo rm your-site.app
$ sudo service nginx restart
$ cd /vagrant/scripts
$ sudo sh serve-hhvm.sh your-hhvm-site.app /home/vagrant/example/blog/public 80
$ sudo service nginx restart
You can confirm the site is using HHVM in php with:
die(defined('HHVM_VERSION'));
####Some errors not showing?
Make sure you have these settings in your php.ini:
/etc/hhvm/php.ini
hhvm.server.implicit_flush = true
hhvm.error_handling.call_user_handler_on_fatals = true
You can of course also tail errors at /var/log/hhvm/error.log
##PDO::FETCH_ASSOC
To change the 'fetch' => PDO::FETCH_CLASS,
setting in vendor/laravel/lumen-framework/config/databse.php just create a folder config just under your main project folder (ie. same level as your boostrap folder) and copy the file database.php file into it. Then change the line to: 'fetch' => PDO::FETCH_ASSOC,
and you'll get arrays returned from queries. Then do a php artisan cache:clear
.
##Bower
Create bower.json
in project folder (same folder where composer.json & package.json are):
{
"name": "laravel"
}
Create .bowerrc
in project folder:
{
"directory": "resources/assets/bower"
}
Install dependencies:
$ sudo bower install jquery --save --allow-root
$ sudo bower install bootstrap --save --allow-root
Update Less
Change:
@import "bootstrap/bootstrap";
to:
@import "../bower/bootstrap/less/bootstrap";
Update gulpfile.js
, update all references in the blade templates, remove old resources/assets/less/bootstrap
folder, and then run gulp
or gulp --production
(to minify).
(note: you may need to clear bower cache from time to time: bower cache clean some-package --force --allow-root
)
##Publishing Assets from Packages
You can use the artisan publish command to publish your assets from packages. For Lumen, you just need to add your own artisan command (look at Laravel's) or use the one found here: https://github.com/irazasyed/larasupport.
However, I prefer to avoid using artisan for this since I'm already maintaining a Less file and a Gulpfile. I simply update my gulpfile.js to have paths that pull directly from the vendor's package. See my gulpfile below.
Note: I don't use Laravel elixir.
In gulpfile.js
var gulp = require('gulp'),
less = require('gulp-less'),
minifyCSS = require('gulp-minify-css'),
uglify = require('gulp-uglify'),
concat = require('gulp-concat'),
addsrc = require('gulp-add-src'),
sourcemaps = require('gulp-sourcemaps');
var paths = {
'assets': 'resources/assets/',
'bower': 'resources/assets/bower/',
'vendor': 'vendor/',
'public': 'public/'
};
// CSS & Less
gulp.task('css', function(){
gulp.src(paths.assets + 'less/core.less')
.pipe(sourcemaps.init())
.pipe(less())
.pipe(minifyCSS())
.pipe(sourcemaps.write('source-maps'))
.pipe(gulp.dest('public/css'));
});
// Javascript
gulp.task('js', function() {
gulp.src(paths.bower + 'selectize-extended/dist/js/standalone/selectize.js')
.pipe(addsrc.append(paths.bower + 'smalot-bootstrap-datetimepicker/js/bootstrap-datetimepicker.js'))
.pipe(addsrc.append(paths.bower + 'bootstrap-table/dist/bootstrap-table.js'))
.pipe(addsrc.append(paths.bower + 'bootstrap-table/locale/bootstrap-table-en-US.min.js'))
.pipe(addsrc.append(paths.assets + 'js/core.js'))
.pipe(sourcemaps.init())
.pipe(concat('core.js'))
.pipe(uglify({mangle: false}))
.pipe(sourcemaps.write('source-maps'))
.pipe(gulp.dest('public/js'));
});
gulp.task('default',['css','js']);
You'll need to do a chmod -R 777 public
so Gulp can write files to your public directory.
##Leave feedback
I will continue to add to this guide, keep it up-to-date, and improve on its readability. If you have any suggestions/comments please don't hesitate to post them below.