There are plenty of tools for doing local development, however some of them place some inconvenient limits on what you can do. If you aren’t afraid to edit a few config files then you can have an incredibly flexible local development in just a few steps.
At the end of this tutorial you’ll be able to create a folder, following the simple ~/Sites/MYFOLDERNAME.dev
pattern, and have it just work in the browser.
Setting up Apache
OSX ships with Apache pre-installed, but in it’s default configuration it’s not very useful. Additionally at some point in the near past, Apple removed the ability to toggle Apache’s state from System Preferences, we’ll be solving that as well.
These instructions assume that you’ve never made any changes to the Apache configuration. If you have, your mileage may vary.
Create a Sites directory in your home directory if you don’t already have one.
[ ! -d ~/Sites ] && mkdir ~/Sites
Create a blank httpd-vhosts.conf
file, we’ll come back to this in a bit.
touch ~/Sites/httpd-vhosts.conf
Create a symbolic link for our previously created conf file.
sudo ln -s ~/Sites/httpd-vhosts.conf /etc/apache2/other
Setup the logs directory, and set it’s permissions. These are probably a little too permissive, feel free to adjust as needed.
mkdir ~/Sites/logs && chmod 0777 ~/Sites/logs
Add the following to the previously created httpd-vhosts.conf
file. Make sure to replace USERNAME
with your own user name.
Listen 80 # Use name-based virtual hosting. NameVirtualHost *:80 UseCanonicalName Off LogFormat "%V %h %l %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i"" dynamic_vhosts CustomLog /var/log/apache2/access_log dynamic_vhosts <VirtualHost *:80> ServerName localhost VirtualDocumentRoot /Users/USERNAME/Sites/%0 <Directory "/Users/USERNAME/Sites"> Options Indexes FollowSymLinks MultiViews AllowOverride All Order allow,deny Allow from all </Directory> </VirtualHost>
Obviously feel free to change around the log format to best fit your application. The key to this working is the %0
at the end of VirtualDocumentRoot, acting as a placeholder for the domains you’ll be using locally.
At this point you should restart Apache to the previous configuration changes will be applied.
sudo apachectl stop && sudo apachectl start
Setting up Dnsmasq
You could potentially stop without executing any of the following steps and have dynamic vhosts. However, every time you created a new domain you’ll need to update your hosts file. That’s no fun. Installing Dnsmasq is relatively straightforward.
Install Dnsmasq.
brew install dnsmasq
Copy the default configuration to its new home.
cp /usr/local/opt/dnsmasq/dnsmasq.conf.example /usr/local/etc/dnsmasq.conf
We’re going to be using the .dev domain for all local domains. Add the configuration to the newly created dnsmasq.conf
file. If you want the .dev
domains to point to a different address (i.e. A Vagrant instance), other than your local, just change 127.0.0.1
to your preferred location.
echo 'address=/.dev/127.0.0.1' > $(brew --prefix)/etc/dnsmasq.conf
Now we need a place to let Dnsmasq know about our new resolvers. Additionally we’ll add our first resolver, .dev
. Again, don’t forget to change 127.0.0.1
to the address you specified in the previous step if you intend to use something different.
sudo mkdir -v /etc/resolver && sudo bash -c 'echo "nameserver 127.0.0.1" > /etc/resolver/dev'
Dnsmasq needs to start, and we want it to start at startup.
sudo cp -fv /usr/local/opt/dnsmasq/*.plist /Library/LaunchDaemons sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist
If you need to restart Dnsmasq run the following.
sudo launchctl unload /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist && sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist
Great! You can check to see that resolver is working with scutil --dns
. You should see an additional resolver at the bottom, your exact number might vary.
resolver #8 domain : dev nameserver[0] : 127.0.0.1
Additionally you can ping any domain ending in .dev
and it should resolve to 127.0.0.1
~ : ping -c 1 test.dev PING test.dev (127.0.0.1): 56 data bytes 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.042 ms --- test.dev ping statistics --- 1 packets transmitted, 1 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 0.042/0.042/0.042/0.000 ms
Final setup
You can now create any series of folders ending in .dev
in your sites directory. The contents of those folders will be served on the corresponding domain. If you have a folder called test.dev
then your domain will also be test.dev
Enjoy your new automatic local development environment.
Making the web a better place to teach, learn, and advocate starts here...
When you subscribe to our newsletter!