For about a year now we've been working on a Drush-based server management tool called Seed. I've become quite accustomed to it. A few weeks ago, I decided that I wanted to install it on my home development environment which runs on OSX. Since it was developed originally for a Linux system I knew it should be *fairly* easy to modify it to work on OSX. Here's how to do it:
I wrote this tutorial specifically for OSX Mountain Lion (10.8.x). I imagine it will be pretty much exactly the same for Lion (10.7.x) but I can't say for sure. As far as a preliminary knowledge base, you'll need to be familiar with the command line and drush. Additionally, knowing a bit about apache and apache configuration will be helpful in case you need to debug anything along the way.
The Development Environment
Not everyone is going to have their development environment set up exactly as I set mine up. A lot of these components could be installed through any number of means. Additionally, you may be using a packaged solution like XAMPP or MAMP. It doesn't necessarily matter how you've set up your dev environment, but you do need to know where everything is installed. I've set up my local development environment using as many of the components that come bundled with OSX (Mountain Lion) as I can. For missing pieces I've installed homebrew. I'll give a quick rundown of what I've done to get my dev environment up and running.
Git
You'll need git installed to leverage some of seed's project repo management features. You also need git for homebrew to work. By default, Mountain Lion doesn't come with git installed. Apple recommends installing XCode and enabling their "Command Line Tools" from there to get git. Which is exactly what I did. Although, I'm sure you could just run brew install git
and get roughly the same results.
Homebrew
Installing homebrew is pretty straightforward. There are instructions on their site: http://brew.sh. Homebrew also requires ruby, but that also comes pre-installed on Mountain Lion.
One thing to note about Homebrew is that it installs everything into /usr/local/Cellar/
and typically uses a folder structure of /usr/local/Cellar/[package-name]/[version-number]
PHP & Apache
PHP and Apache come with Mountain Lion so I didn't have to do anything to install these.
- PHP: Should just work. Type
php --version
to be sure. - Apache is installed in:
/etc/apache2
MYSQL
Homebrew makes it pretty easy to install mysql.
For a more detailed explanation of installing mysql using homebrew, read this post. Also, you may need to symlink the required socket file. It should be either at /tmp/mysql.sock or /var/mysql/mysql.sock. Whichever one is missing the mysql.sock file, just create a symlink to the existing one. On my machine, I was missing the socket file in /var/mysql so I had to do the following from the command line:
Drush
There's a few ways to install drush. I chose to use homebrew. It doesn't really matter how it's installed. All that matters is that you know where it's installed.
When installing drush with homebrew, the files will end up here: /usr/local/Cellar/drush/[version-number]/libexec/
where [version-number] is the drush version. On my system it's /usr/local/Cellar/drush/6.0.0/libexec/
DNSmasq
This last tool is optional. When we add new projects with seed, we'll be creating virtual host entries for each one with a domain along the lines of project.username.localdev
(I'm using the top-level-domain .localdev
because we already use .dev
internally on our central dev environment). For each one of these virtual hosts, we would usually need to add a new entry to our /etc/hosts
file so that the domain resolves to our localhost server (since the hosts file doesn't understand wildcards). However, with dnsmasq, we can set it up to resolve all requests to the top-level domain .localdev
to our localhost ip (127.0.0.1). To install dnsmasq, we'll just turn to our trusty homebrew once again:
For installation instructions for dnsmasq, check out this concise post.
A note about dnsmasq on OSX: You should be able to use any top-level-domain except for .local
. "local" is reserved by OS X for mDNS. If you run scutil --dns
you'll see it near the top of the list
Installing Seed
Seed comes with some installation instructions in an INSTALL.txt file. These instructions are technically for a linux server, but some of the things in it will apply to our OSX installation as well.
Firstly, we'll need to setup our .drush folder (located in your home folder ~/.drush). The following is a list of commands to run from the command line. Lines beginning with '#' are comments and are there just to explain the following line(s) of code:
Next, we're going to install seed into our .drush folder and symlink it to our drush installation:
Setting up Seed
The next thing we need to do is setup the seed.info file. The seed.info file is just a php configuration file (.ini) where you setup some base variables for seed to work. This is where your knowledge of your development environment setup is needed. One thing to note about the info file is that you will be provided with some tokens to help with the dynamic creation of folders and filenames:
[USER]
: The user calling the seed command[PROJECT]
: The project name the seed command is acting on.[THIS.
: This is a way to reference variables defined within the info file itself. Most notably we use it to reference the defined global_user:] [THIS.global_user]
Here's my seed.info file with some comments added to explain each part. (comments are lines that start with a semi-colon).
A Note about Directories:
I've set up all my project files to be in /Users/username/Sites/drupal
. The only reason I did this is because the /Users/username/Sites
folder gets an special icon in Finder. Alternatively you could do something more linuxy like /home/username/www
for project folders, /home/username/databases
for dbs etc. I've also been toying with the idea of using something like Google Drive or Dropbox as a simple "cloud" storage solution for my databases and files directories.
Configuring Apache
The next thing we need to do is set up our apache httpd configuration. If you've already started apache using sudo apachectl start
, run sudo apachectl stop
to kill it. We're going to be conceding control of apache over to seed. When we're done you'll start/stop/restart your server using seed start/stop/restart
.
When you start your server using seed start
, seed starts apache using it's own httpd.conf file instead of the one in /etc/apache2/
. The configuration file it uses is generated from a template file kept in ~/.drush/seed/templates/httpd.tpl.php
. We're going to need to modify this a little to work with our Mac's apache setup. Here's the modified file with some extra comments to highlight the changes.
NOTE: Don't forget to comment out "Listen 80" from your original /etc/apache2/httpd.conf
file since it's already being declared in seed's httpd.conf file!
The Virtualhost Templat
Additionally, seed comes with a vhost template (~/.drush/seed/templates/vhost.tpl.php
) that you could alter depending on your needs. For the purposes of this demo (and probably for most setups), we're going to leave this template in it's stock form. However, the template does have a block for ssl support which means you may need to create a dummy ssl certificate. It's specifically looking for /etc/apache2/dev.crt
and /etc/apache2/dev.key
. Here's an uncommented set of commands you can run from the command line to generate the necessary files. There are some prompts. It's up to you if you want to use passphrases. I didn't.
$ cd /etc/apache2 $ sudo ssh-keygen -f dev.key $ sudo openssl req -new -key dev.key -out dev.csr $ sudo openssl x509 -req -days 365 -in dev.csr -signkey dev.key -out dev.crt
Start Using Seed!
And that's it! Seed is set up. Open your command line and start seed:
your-mac:~ username$ seed start
Now create a new project with seed init:
your-mac:~ username$ seed init Project name: d7sandbox Enter a number. [0] : Cancel [1] : Clone an existing project repository [2] : Create a new project [3] : Copy project from another user 2 [Project] Successfully created directory /Users/chriseastwood/Sites/drupal/www/d7sandbox Use git? (y/n): y Initialize new remote: git@bitbucket.org:git_fuseinteractive/d7sandbox.git ? (y/n): y [Project] Initialized git repository [Project] Initialized git remote [Project] Added remote git@bitbucket.org:git_fuseinteractive/d7sandbox.git Symlink the files directory? (y/n): n [Database] MySQL user chris already exists. [Database] Created MySQL database d7sandbox for user chris Create database d7sandbox_chriseastwood? (y/n): n Create a settings.php file with the database d7sandbox? (y/n): n Create Drush alias? (y/n): y User [chriseastwood]: Web root path [/Users/chriseastwood/Sites/drupal/www/d7sandbox]: Files path [/Users/chriseastwood/Sites/drupal/www/d7sandbox/sites/default/files]: Database dump path [/Users/chriseastwood/Sites/drupal/databases/d7sandbox]: URI [d7sandbox.chriseastwood.localdev]: [Alias] Could not read the alias file /Users/chriseastwood/.drush/aliases/d7sandbox.aliases.drushrc.php. This is not a fatal error however it may result in aliases not being created. [Alias] Created new alias: @d7sandbox.dev.chriseastwood Host name [d7sandbox.chriseastwood.localdev]: Document root [/Users/chriseastwood/Sites/drupal/www/d7sandbox]: [Added] d7sandbox.chriseastwood.localdev -> /Users/chriseastwood/Sites/drupal/www/d7sandbox Server stopped. No errors found in the server configuration. Server started with the following virtual hosts: d7sandbox.chriseastwood.localdev -> /Users/chriseastwood/Sites/drupal/www/d7sandbox Server restarted.
Note the non-fatal error when creating the alias. This is because seed tries to read the alias file (presumably to check for existence) before creating it. In this case the error can be ignored. Our alias is created correctly.
Also, don't forget to add an entry in you /etc/hosts
file for each virtual host you create if you decided not to install dnsmasq.
Here's another example of using seed init to initialize an existing project that's already in version control.
your-mac:~ username$ seed init Project name: existingproject Enter a number. [0] : Cancel [1] : Clone an existing project repository [2] : Create a new project [3] : Copy project from another user 1 [Project] Successfully created directory /Users/chriseastwood/Sites/drupal/www/existingproject Repository URL [git@bitbucket.org:git_fuseinteractive/existingproject.git]: [Project] Cloning repository git@bitbucket.org:git_fuseinteractive/existingproject.git [Project] This could take awhile depending on the size of the repository... Cloning into '/Users/chriseastwood/Sites/drupal/www/existingproject'... remote: Counting objects: 5799, done. remote: Compressing objects: 100% (4444/4444), done. remote: Total 5799 (delta 1119), reused 5799 (delta 1119) Receiving objects: 100% (5799/5799), 15.90 MiB | 1.55 MiB/s, done. Resolving deltas: 100% (1119/1119), done. Checking out files: 100% (4224/4224), done. [Project] Cloning repository complete Symlink the files directory? (y/n): y Target directory [/Users/chriseastwood/Sites/drupal/files/existingproject]: Symlink the files directory for existingproject (user chriseastwood) to the files directory /Users/chriseastwood/Sites/drupal/files/existingproject? (y/n): y [Project] Symlinked /Users/chriseastwood/Sites/drupal/www/existingproject/sites/default/files to /Users/chriseastwood/Sites/drupal/files/existingproject [Database] MySQL user chris already exists. [Database] Created MySQL database existingproject for user chris Create database existingproject_chriseastwood? (y/n): n Create a settings.php file with the database existingproject? (y/n): y MySQL username to connect to this database [chris]: MySQL password to connect to this database: chris Create Drush alias? (y/n): y User [chriseastwood]: Web root path [/Users/chriseastwood/Sites/drupal/www/existingproject]: Files path [/Users/chriseastwood/Sites/drupal/www/existingproject/sites/default/files]: Database dump path [/Users/chriseastwood/Sites/drupal/databases/existingproject]: URI [existingproject.chriseastwood.localdev]: [Alias] Could not read the alias file /Users/chriseastwood/.drush/aliases/existingproject.aliases.drushrc.php. This is not a fatal error however it may result in aliases not being created. [Alias] Could not read the alias file /Users/chriseastwood/.drush/aliases/existingproject.aliases.drushrc.php. This is not a fatal error however it may result in aliases not being created. Password: [Alias] Created new alias: @existingproject.dev.chriseastwood Host name [existingproject.chriseastwood.localdev]: Document root [/Users/chriseastwood/Sites/drupal/www/existingproject]: [Added] existingproject.chriseastwood.localdev -> /Users/chriseastwood/Sites/drupal/www/existingproject Server stopped. No errors found in the server configuration. Server started with the following virtual hosts: existingproject.chriseastwood.localdev -> /Users/chriseastwood/Sites/drupal/www/existingproject taymor.chriseastwood.localdev -> /Users/chriseastwood/Sites/drupal/www/taymor Server restarted.
Next we're going to load the database (which we've put into our databases folder - /Users/chriseastwood/Sites/drupal/databases/existingproject/
)
your-mac:~ username$ seed db-load Project name: existingproject User name [chriseastwood]: Load in to database [existingproject_chriseastwood]: existingproject Backup the database first? (y/n): n Which DB should be loaded? [0] : Cancel [1] : existingproject.sql 1 [Database] Deleted MySQL database existingproject [Database] Created MySQL database existingproject for user chriseastwood [Database] Back up /Users/chriseastwood/Sites/drupal/databases/existingproject/existingproject.sql loaded in to database existingproject
And I'm up and running and ready to go!
Upgrading Seed
There is one caveat with the way I've set up Seed on my local system. I've edited core files of seed so when I go to upgrade, my configurations will be overwritten. For now the simplest solution is to move my customizations out of the seed folder, and then create symlinks to them. This way when I upgrade seed, at least my files will still be safe
$ mkdir ~/.seed $ mv ~/.drush/seed/seed.info ~/.seed/ $ mv ~/.drush/seed/templates/httpd.tpl.php ~/.seed/ $ ln -s ~/.seed/seed.info ~/.drush/seed/seed.info $ ln -s ~/.seed/httpd.tpl.php ~/.drush/seed/templates/httpd.tpl.php
In the future, however, we're working on setting up a way to supply your own seed overrides without having to create symlinks. Keep an eye out for that in future releases!
Conclusion
So there it is: Seed. On your Mac. Your one stop shop for all your drupal server management needs. And somehow I managed to get through the whole tutorial without a single horticultural pun (except for the title). Now go forth and let Seed form the roots that helps your projects grow bigger, stronger, and faster!