Setting Up and Managing Multiple SSH Accounts for Drush on Mac/Linux

It may be the case, you have multiple ssh connections some for github accounts and some for one or more virtual boxes for Drupal sites. In this post, we cover how to generate, configure and manage multiple SSH accounts for drush. In addition, we go over how to overcome the error ‘ssh-copy-id: command not found ‘ that happens for Mac machines when trying to setup ssh keys via drush command ‘pushkey’

Generating Public/Private SSH Key Pair

For each different ssh account, you would generate ssh public/private key pair as following:

ssh-keygen -t rsa -C "user@hostname.com"

By default, this will store the generated key pairs(two files one with .pub extensions) in the directory you run the command from. We moved it into $HOME/.ssh directory and we will be referring to this directory in this post

Manage SSH Keys

You can manage multiple SSH keys by creating host aliases for each ssh key pair. The host aliases are defined in the $HOME/.ssh/config file and all they do is reference the keys per host alias as following

Host virtual-box-main
        HostName hostdomain.com
        User user-name
        IdentityFile ~/.ssh/id_rsa_virtual_box

Host another-host-alias
        HostName some-remote-box.com
        User ssh-user
        IdentityFile ~/.ssh/private_key_gen_above

Here the host alias is ‘virtual-box-main’. The ‘hostname’ is actual domain name to the server you like to ssh. The ‘user’ is the actual ssh user account that will be used to ssh into the server. At last, the ssh key pair is referenced via ‘IdentityFile’ that was generated in the above step.

So, you can repeat the above steps to generate ssh key pairs for each ssh remote account. Then configure host alias by adding another entry as specified above for each different ssh login you need.

Setup Drush

Once you have the ssh host alias setup, then to configure drush via the alias(one location $HOME/.drush/aliases.drushrc.php) as following:

$aliases['ds.prod'] = array(
	'remote-host' => 'virtual-box-main',
	'remote-user' => 'root',
	'root' => '/home/websites/site',
	'uri' => 'http://site.com',
    );

Here the host alias configure in ssh is specified ‘remote-host’, so when drush makes the ssh connection it will look it up the alias to identify ssh key to use for login

If you try to connect with the current setup:

drush @ds.prod st

You will get following error:
Permission denied (publickey,password).

This is because the remote machine needs to have the ssh public key in order to be able authenticate. Lets push the key:

drush pushkey @ds.prod

This function copies the ssh key into the server for ssh authentication.

For Mac, this will result into the following error because Mac doesn’t have the function ‘ssh-copy-id’
ssh-copy-id: command not found
So, solution is to copy ssh key manually

Copy Public SSh Key Manually

To copy the public ssh key, run the following:

cat id_rsa_virtual_box.pub | ssh user@virtualbox.com 'cat >> .ssh/authorized_keys' 

This pipes the ssh key and then logs into the virtual server and pasts the key into authorized_keys file. You may be missing the .ssh folder on the remote server. In that case, you make it create one as following:

cat id_rsa_virtual_box.pub | ssh user@virtualbox.com 'umask 077; mkdir -p .ssh ; cat >> .ssh/authorized_keys'

Now, running:

drush @some.alias st

It should be displaying the status of the site on remote server

Troubleshooting

1. Test SSH Authentication

To test any of your SSH Aliases setups:

ssh virtual-box-main

Here, we test the alias ‘virtual-box-main’. This will prompt for password if logging in for the first time. All other times it logs you in without password
Note: for ssh services that has turned off interactive mode such as Git, you use -T flag:

ssh -T git-ssh-alias

This will confirm if your ssh is setup correctly or not

2. Permission denied (publickey,password).

You will get this message if you haven’t set up the ssh as described in this post

3. ‘pushkey’ could not be found drush

This is because the push key function is addition and needs to be downloaded as following:

drush dl drush_extras

This will download and install drush_extras module that includes “pushkey” command

4. “sudo: no tty present and no askpass program specified”

This is issue comes up when you open ssh without tty session. It can be solved in 2 ways depending on how much access you have on remote instance or whatever the remote instance has the capability of NOPASSWORD

  1. Turn on NOPASSWORD on remote instance as described here:
    http://askubuntu.com/questions/192050/how-to-run-sudo-command-with-no-password/443071#443071
  2. Configure Drush to pass in credentials at time of ssh-ing. Its being done by editing .drush/drushrc.php and adding following line:
    $options['ssh-options'] = '-o PasswordAuthentication=no -i $HOME/.ssh/id_rsa/lamp_vbox';
    

    Here the lamp_vbox is the private key generated by ssh-keygen

5. WARNING: UNPROTECTED PRIVATE KEY FILE!

The permissions need to be reset:

sudo chmod 600 /path/.ssh/id_rsa/lamp_vbox
sudo chmod 600 /path/.ssh/id_rsa/lamp_vbox.pub
sudo chmod 644 /path/.ssh/known_hosts
sudo chmod 755 /path/.ssh
References

http://mail-archives.apache.org/mod_mbox/hadoop-mapreduce-user/201210.mbox
http://blogs.uoregon.edu/developments/2012/06/21/bash-function-ssh-copy-id-for-mac/
http://www.drush.org/sites/default/files/attachments/DGD7-Drush.pdf
http://stackoverflow.com/questions/3844393/what-to-do-about-pty-allocation-request-failed-on-channel-0

Installing Apache on Mac/Linux

Mac comes with apache pre-installed, however. You may wish to install your own apache instance
http://margotskapacs.com/2013/09/installing-apache-on-mac/
Before start, make sure the default apache server is not running(see troubleshooting section below). To turn off, go to ‘System Preferences->Sharing’ and uncheck ‘Web Sharing’

Step 1. Installing Apache via macport

port selfupdate
sudo port install apache2

This installes Apache in /opt/local/apache2/ directory

Step 2. Configure Apache

Apache comes with sample configurations, lets copy it

sudo cp /opt/local/apache2/conf/httpd.conf.sample /opt/local/apache2/conf/httpd.conf

In the apache configuration file ../conf/httpd.conf change the following lines to specify root folder from where your websites is going to be serviced

...
<Directory "/opt/local/apache2/htdocs">
...
DocumentRoot "/opt/local/apache2/htdocs"

The path /opt[..]/htdocs’ can be anything you wish but in both places it have to point to the same folder

Next, add ‘index.php’ so that Apache grabs index.php file if present

<IfModule dir_module>
    DirectoryIndex index.html index.php
</IfModule>

Afterwards, configure Apache interpret all files ending with .php/.phps by adding these lines:

AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps

Finally, to enable user directories uncomment:

Include conf/extra/httpd-userdir.conf

Step 3. Activate PHP module

After installing and compiling PHP, there is PHP package that Apache needs to load, so here how to activate it

cd /opt/local/apache2/modules
sudo /opt/local/apache2/bin/apxs -a -e -n "php5" libphp5.so
[activating module 'php5' in /opt/local/apache2/conf/httpd.conf] 

Step 4. Start Appache

To start and stop Apache:

sudo /opt/local/apache2/bin/apachectl start
sudo /opt/local/apache2/bin/apachectl stop

After starting, point your browser to ‘locahost’ and it should work. To test php, add the following file to the folder you specified ‘DocumentRoot’ in above:

<?php
phpinfo();
?>

Afterwards point to this file ‘localhost/fileName.php’ and it should display php configurations

Enable Virtual Hosting

To Enable virtual hosting, uncomment the following line in apache configuration file conf/httpd.conf

Include conf/extra/httpd-vhosts.conf

Afterwards, configure you virtual host at conf/extra/httpd-vhosts.conf. Here is an example to get you started:

NameVirtualHost *:80
...
<VirtualHost *:80>
    DocumentRoot "/path/to/your/site"
    ServerName domainName.com
    <Directory /path/to/your/site>
        Options FollowSymLinks
        AllowOverride All
        Allow from all
        Order Deny,Allow
    </Directory>
    ErrorLog "/private/var/log/apache2/domainName.com-error_log"
    CustomLog "/private/var/log/apache2/domainName.com-access_log" common
</VirtualHost>

Troubleshooting

1. To see Apache looaded configs:
httpd -V
//or for Debian servers
apache2ctl -V
2. To see if Apache deamon is running
ps -ef | grep httpd
3./.htaccess: Options not allowed here

This happen after specifying alias in the virtual host but never declaring directive:

     <Directory /path/to/the/alias>
        Options FollowSymLinks
        AllowOverride All
        Order Deny,Allow
        Allow from all
    </Directory>
    Alias /path /path/to/the/alias

So, by including the “<Directory..” gives the permissions for the .htaccess manage the ‘Options’ configuration solving the problem you see in the log

4. Virtual Hosting is Not Working

Make sure you have added "NameVirtualHost *:80" in one of the configurations that is being loaded such apache2.conf, some-v-host.conf,etc

5. client denied by server configuration (PHP FPM)

Make user to have Require all granted part of the Virtual Host configuration Directory section as following:

<Directory "/path/to/serving/dir">
		Options Indexes MultiViews FollowSymLinks
		AllowOverride All
		Order allow,deny
		Require all granted
	</Directory>
6. Forms Will not submit or “AH00128: File does not exist” in logs

The forms could be submitted and the apache logs were showing “AH00128: File does not exist[..]” for Apache 2.4. There issue is that mod_rewrite is not enabled by default. You can check if the mod_rewrite is enabled and loading by looking at phpinfo(). To enable mod_rewrite:

sudo a2enmod rewrite
sudo service apache2 restart

This will load mod_rewrite making the forms to Post for Drupal

caught SIGTERM, shutting down

This error was coming up for Apache 2.4 on Ubuntu after logging into Drupal. I am not sure which exactly fix it but did the following:

  • turn off limit for MaxKeepAliveRequests in the apache2.conf configuration file
  • Increase memory in php.ini by changing memory_limit
  • Increased max_input_time in php.ini
  • Increased max_execution_time in php.ini

In addition, it appears that apache restarts with the above error every time there is php syntax error.

Blank Screen

By default Apache will display blank screen when there is php error. To turn on errors to be displayed in browser instead of blank screen, edit php.ini as following:

display_errors=On
html_errors=On
error_reporting=E_ALL | E_STRICT 
display_startup_errors=On

This will enable error reporting in the browser. In case it doesn’t, then at your application level there must be ErrorHandler defined that hides all the errors. See more info here http://stackoverflow.com/questions/1475297/phps-white-screen-of-death

Troubleshooting Tip

When there is error, turn on max logging by changing ErrorLevel to trace8 in virtual host settings or Apache global settings:

...
 LogLevel trace8
 ErrorLog ${APACHE_LOG_DIR}/dev-virtual/error.log
..

Afterwards, tail the logs specified in ErrorLog from command line to follow real time Apache execution:

tail -f APACHE_LOG_DIR/dev-virtual/error.log

At last, make the requests and follow the logs in command line:

Useful Links

  • http://www.thegeekstuff.com/2008/08/9-tips-to-use-apachectl-and-httpd-like-a-power-user/
  • http://2tbsp.com/content/install_apache_2_and_php_5_macports

Installing MySQL on Mac

Despite the popular virtualization solutions like Vagrant, Micro Cloud Foundry and others all of which are perfect solutions for your development environment that would include mysql, there may be reason you need to install Mysql server locally on your machine. This covers steps how to install mysql via macports packaging distribution.

Environment: MySQL 5.5, Mac 10.7

1- Install MacPorts

http://www.macports.org/install.php

2- Update MacPorts

sudo port selfupdate

3- Install MySQL server and client binaries

sudo port install mysql55

4- Install MySQL server startup scripts

sudo port install mysql55-server

5- Initialize the Database:

sudo /opt/local/lib/mysql55/bin/mysql_install_db --user=mysql

6A- Trick to get root user work

sudo chown -R mysql:admin /opt/local/var/db/mysql55
sudo chmod u+rwx,go= /opt/local/var/db/mysql55

6B- Starting MySQL

sudo /opt/local/share/mysql55/support-files/mysql.server start

7- Setting Root password

/opt/local/lib/mysql55/bin/mysqladmin -u root password 'changepasswordhere'

8- Enable the startup script so mysql starts on boot

sudo launchctl load -w /Library/LaunchDaemons/org.macports.mysql55-server.plist

– or —

sudo port load mysql55-server

9-Creating user that can access DB from any IP address

GRANT ALL PRIVILEGES ON *.* TO db_user@'%' IDENTIFIED BY 'db_passwd';
FLUSH PRIVILEGES;

10 – Verify all working

shell> mysqladmin version
shell> mysqladmin variables
shell> mysqladmin -h `hostname` version variables
shell> mysqladmin -h `hostname` --port=3306 version
shell> mysqladmin -h host_ip version
shell> mysqladmin --protocol=SOCKET --socket=/tmp/mysql.sock version

11-Reinstalling

If you need to uninstall/reinstall for whatever reason, remove the database directory when you do the uninstall

sudo port uninstall mysql55-server
cd /opt/local/var/db/
sudo rm -rf mysql55/

Troubleshooting

1. ERROR 2003 (HY000): Can’t connect to MySQL server on ‘127.0.0.1’ (61)
I wasn’t able to connect via client such as MySQL Workbench. Part of troubleshooting was running:

mysql -u makapacs -p -h localhost
mysql -u makapacs -p -h 127.0.0.1

The last, displayed the error ‘ERROR 2003 (HY000): Can’t connect to MySQL server on ‘127.0.0.1’ (61)’. Next:

○  telnet localhost 3306
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
telnet: connect to address 127.0.0.1: Connection refused
Trying fe80::1...
telnet: connect to address fe80::1: Connection refused
telnet: Unable to connect to remote host

Clearly, something doesn’t let connect via TCP connection
Solution:Make sure ‘skip-networking’ is commented out in configuration file(our case /opt/local/etc/mysql55/my.conf) or when starting mysql server, it does’t start with ‘–skip-networking’

In skip-networking mode, the mysql instance doesn’t “listen for TCP/IP connections at all. All interaction with mysqld must be made using named pipes or shared memory (on Windows) or Unix socket files (on Unix)” from MySql Docs

2. ERROR 2003 (HY000): Can’t connect to MySQL server on ‘127.0.0.1’ (111)
This error was because, mysql server was binded on particular ip as follows (/etc/mysql/my.cnf):

# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address = 173.255.xx.xx

So, when mysql binded on specific ip then it only listens remote connection from localhost or the ip specified. Solutions was to comment out ‘bind-address’ and restart mysql server. Afterwards, any remote connection worked

3. Warning: PDO::__construct() [pdo.–construct]: [2002] No such file or directory (trying to connect via unix:///var/mysql/mysql.sock)
This error came out suddenly one day. It cannot find the mysql socket file. To locate

mysqladmin variables | grep 'socket'

This will display where the mysql.socket is created and placed every time mysql starts. Next, create symbolic link so php can find it

sudo ln -s /opt/local/var/run/mysql55/mysqld.sock mysql.sock

Important to note, to find out where Apache looks for mysql.sock, run in browser and look under ‘pdo_mysql’ section

4. Warning: mysql_connect(): No such file or directory
Solved by changing mysql host from ‘localhost’ to ‘127.0.0.1’. The reason for this error is because the “localhost” is a special name for the mysql driver making it use the unix socket to connect to mysql instead of the a tcp socket.

Fatal error: Uncaught exception ‘PDOException’ with message ‘SQLSTATE[HY000]: General error: 2006 MySQL server has gone away’ /includes/database/database.inc

The solution was to add following line in mysql55/my.conf file:

[mysqld]
max_allowed_packet=100M

This gave the necessary extra space for the communication between db and the app

Useful Links:

 

  • http://jackal.livejournal.com/2160464.html
  • http://stackoverflow.com/questions/4798464/installing-mysql-on-snow-leopard-using-macports
  • http://dev.mysql.com/doc/refman/5.0/en/resetting-permissions.html#resetting-permissions-unix
  • http://dba.stackexchange.com/questions/15004/how-to-initiate-mysql-on-mac-os-x-10-6-8
  • http://dev.mysql.com/doc/refman/5.0/en/flush.html
  • http://www.razorsql.com/docs/mysql_connection_troubleshooting.html