I have found Deployer to be a great tool for deploying PHP applications. However when first setting out to use it I soon came across the error message sudo: sorry, you must have a tty to run sudo. After some investigation I found that the error was triggered when Deployer was running commands via sudo. For those that don't know Deployer works by executing commands on your servers via ssh and depending on your server's configuration there could be issues when sudo is one of those commands.

What is meant by 'sudo: sorry, you must have a tty to run sudo'?

When sudo is executed the file /etc/sudoers is read to determine which users or groups can use sudo and what commands they can run. It actually does a bit more than that and you should read the manual for more information.

If you examine the sudoers file you will find that it contains the setting Defaults requiretty. This means that sudo can only be ran from a real tty. In other words if a user wants to run sudo they must have logged into a terminal before hand. This is normally a security feature so that sudo can't be ran from things such as cron jobs. However, it also means that you will have issues when running sudo from another machine via ssh as you also won't be logged into an actual terminal.

How to resolve the issue?

If you're happy to change the setting for all users simply use visudo to edit /etc/sudoers and change Defaults requiretty to Defaults !requiretty. Alternatively you can remove the tty requirement for a single user. In fact that is what I do when using Deployer. Since it connects to the server using a user called deployer I add the below configuration with visudo.

Defaults:deployer !requiretty
deployer ALL=(ALL) NOPASSWD:/usr/bin/chown, /usr/bin/tee, /usr/sbin/apachectl

This configuration allows the deployer user to execute sudo when not logged into a real terminal and additionally not prompt for a password when executing chown, tee, and apachectl.

Using Pseudo-tty

An alternative is to use the pseudo-tty option when connecting via ssh.

$ ssh -t user@example.com sudo apachectl restart