Panasonic Youth rob sanheim writes about software, business, ruby, music, stuff and things



Posted
10 May 2007 @ 7am

Tagged
Command Line, Macintosh, Rails, Ruby

Discuss

Deploying Locally to Mac OS X with Capistrano

Lately I’ve wanted to deploy locally to my mac using Capistrano. Not for actual deployment locally, but to test some custom tasks I was working on. Its a lot quicker and safer to run custom tasks against a local sandbox then some real server somewhere. Writing real tests for custom tasks is basically too difficult to be worth it, so testing locally is probably the least crummy option right now. Another side benefit of testing locally is the speed and removing the need for a net connection.

So out of the box, this won’t work:

  role :app, "localhost"
  role :web, "localhost"
  role :db, "localhost"

  cap my_custom_task

For one thing, mac’s don’t have sshd (the ssh server) running by default. So first do that - go to System Preferences -> Sharing -> and enable “Remote Login”. That should start the ssh daemon.

Now if you deploy, Capistrano should be able to login but you may run into path issues, especially if you want to use gems in a custom task. If you just want to use a very basic task locally, you might be okay here — but if you see ‘command not found’ or missing libraries, you probably need to keep reading.

Capistrano runs SSH over a non-interactive shell, and by default you have an empty environment when logged into a OS X non-interactively via SSH. To fix that, open up /etc/sshd_config in your favorite text editor. Change the following:

PermitUserEnvironment yes

This will allow you to set the environment in your home .ssh folder. Before you leave that file, also find these directives and make the following changes for security:

PermitRootLogin no
Protocol 2
AllowUsers [username here]

This will turn off root login, allow only the more recent version of ssh, and explicitly allow only the one username you’ll be using. If you want to lock it down even more you should set the port to something much higher then 22, turn off password auth, and setup keys with good pass phrases. My mac is behind a router most of the time anyways, so I’m not going to worry about it. If you have a password of ‘password’ or something similiar for the account you are using, you should definitely make that stronger.

Now, create a file for you local ssh environment.

mate ~/.ssh/environment # or vi, or nano, etc...

Now add a PATH statement to that file like the following:

PATH=/usr/local/bin:/usr/local/sbin:/usr/local/mysql/bin:/usr/local/lib:opt/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
RUBYOPT=rubygems

You’ll probably want the /usr/local and /opt/local (for MacPorts) stuff ahead of /usr/bin so that if you use Ruby or Rubygems in your tasks, the non-broken version you installed yourself will get used. After saving that file, go back to the system preferences and turn off ssh (remote login) and turn it back on again to pick up all changes. Now you can run any custom task against your localhost, and it should work pretty much like a typical linux box, assuming you’ve installed everything locally that your have remote.

If you still have issues, create a simple task like so:

task(:debug_env) { run "env" }

Run that locally and then run it remotely to see the differences in your environment, and hopefully that will reveal something missing from your path or maybe some env variable you need.

This was all done with Capistrano 1.4.1, as I haven’t taken the plunge into the new version 2 yet.


2 Comments

Posted by
Jordan Brough
28 September 2007 @ 5am

Thank you! You saved me! :) The ssh environment was the trick for me.

I decided to take the plunge to capistrano 2.0 *and* try using my own (OS X) machine at the same time, so I wasn’t sure which thing was producing the errors.

First I got a “svn: command not found” error, so I added this to my deploy file:
set :scm_command, “/opt/local/bin/svn”

That made that error go away, but then I got a “rake: command not found” error. So I added this to my deploy file:
set :rake, “/opt/local/bin/rake”

Finally I got “No such file to load — rubygems” and “custom_require.rb:27: command not found” errors, and these seemed like path problems too, so I finally decided that something was really wrong. That’s when I found your post and setting the SSH environment and ‘PermitUserEnvironment yes’ made things work! Thanks for the great tips!

For the record, I’m currently using Capistrano 2.0, Rails 1.2.3, and Ruby 1.8.6 to serve rails on a mongrel cluser (mongrel 1.0.1 and mongrel_cluster 1.0.2). I used MacPorts for installing ruby, mysql and apache2. Here are some of the related file contents:

=== ~/.ssh/environment ===
PATH=/opt/local/bin:/opt/local/lib/mysql5/bin:/opt/local/apache2/bin:/usr/local/bin:/usr/local/sbin:/usr/local/flex/bin:/bin:/usr/bin:/usr/sbin:/sbin
RUBYOPT=rubygems

=== Capfile ===
load ‘deploy’ if respond_to?(:namespace) # cap2 differentiator
load ‘config/deploy’

=== config/deploy.rb ===
set :application, “myapp”
set :user, “myusername”
set :server_hostname, “jordan.broughs.net”
set :server_home_path, “/Users/#{user}”
set :repository, “svn+ssh://#{user}@#{server_hostname}#{server_home_path}/svn/#{application}/trunk”
set :deploy_to, “#{server_home_path}/rails/production/#{application}”
# This fixed frustrating ’sudo: no passwd entry for app’ error when cap was trying
# to run the process start command as ‘app’ for some reason
set :runner, ‘myusername’

role :app, server_hostname
role :web, server_hostname
role :db, server_hostname, :primary => true

# Not storing database.yml in svn for security purposes. Manually uploaded it as
# shared/config/database.yml.production on the server after running ‘cap deploy:setup’
# and this copies it over after each code update
task :copy_database_yml, :roles => :app do
db_config = “#{shared_path}/config/database.yml.production”
run “export PATH=/opt/local/bin:$PATH; gem environment; cp #{db_config} #{release_path}/config/database.yml”
end

after “deploy:update_code”, :copy_database_yml


Posted by
Kuroko Project » Shells at 30,000 Feet
29 November 2007 @ 12am

[…] “command not found”, since they use a non-interactive shell to run commands. There are simple fixes: enable PermitUserEnvironment in your /etc/sshd_conf file. Which works, but 1: it’s a […]


Leave a Comment

Rails Conf Plans - Anyone for a Wed Night Meetup? RailsConf 2007 Google Map