29

So I want to be able to cap:deploy without having to type any passwords. I have setup all private keys so I can get to the remote servers fine, and am now using svn over ssh, so no passwords there.

I have one last problem, I need to be able to restart nginx. Right now I have sudo /etc/init.d/nginx reload. That is a problem b/c it uses the capistrano password, the one I just removed b/c I am using keys. Any ideas on how to restart nginx w\out a password?

steve
  • 3,878
  • 7
  • 34
  • 49
tesserakt
  • 3,231
  • 4
  • 27
  • 40
  • This type of question would be better address on http://www.serverfault.com. Also, take a look at http://courtesan.com/sudo/man/sudoers.html#nopasswd_and_passwd to learn how to remove passwords for certain commands using sudo. – randombits Jun 10 '10 at 01:24
  • Do you definitely need to restart Nginx? If you're using Passenger to serve a Rack app such as Rails, running `touch tmp/restart.txt` in the release directory should let Passenger know it needs to restart. – Leo Oct 27 '13 at 12:42

4 Answers4

46

I just spent a good hour looking at sudoer wildcards and the like trying to solve this exact problem. In truth, all you really need is a root executable script that restarts nginx.

Add this to the /etc/sudoers file

username hostname ALL=NOPASSWD: /path/to/script

Write script as root

#! /bin/bash
/bin/kill -HUP `cat /var/run/nginx.pid`

Make the script executable

Test.

sudo /path/to/script
phoolish
  • 581
  • 4
  • 6
  • 1
    That's ... beautiful! What an amazing solution! I've been using capistrano for two years, and didn't realize this was possible. – ndbroadbent Jun 15 '12 at 11:08
  • @nathan.f77 that is exactly what I needed it for. – phoolish Oct 22 '12 at 07:54
  • 4
    If someone compromised the account running the app, would they be able to edit this script and run arbitrary commands as root? – John Fawcett Apr 16 '13 at 00:33
  • 3
    You would need to set the script to be executable by an appropriate group containing the app user, but not to be writable by anyone but root. Probably wouldn't want it world-executable either. – Leo Oct 27 '13 at 12:41
  • @Leo - I'm late to the game, but why do you need it to be executable by a group instead of just the app user? – Tyler DeWitt Feb 21 '15 at 15:40
  • Can’t really remember why I wrote that... but doesn’t the script have to be owned by root for this to work? So the only way to have it executable by the app user is either to have it world-executable, or have the app user in a group that can run the script. But maybe the line in /etc/sudoers means you don’t need that? – Leo Feb 21 '15 at 19:19
39

There is a better answer on Stack Overflow that does not involve writing a custom script:

The best practice is to use /etc/sudoers.d/myusername

The /etc/sudoers.d/ folder can contain multiple files that allow users to call stuff using sudo without being root.

The file usually contains a user and a list of commands that the user can run without having to specify a password.

Instructions:

In all commands, replace myusername with the name of your user that you want to use to restart nginx without sudo.

  1. Open sudoers file for your user:

     $ sudo visudo -f /etc/sudoers.d/myusername
    
  2. Editor will open. There you paste the following line. This will allow that user to run nginx start, restart, and stop:

     myusername ALL=(ALL) NOPASSWD: /usr/sbin/service nginx start,/usr/sbin/service nginx stop,/usr/sbin/service nginx restart
    
  3. Save by hitting ctrl+o. It will ask where you want to save, simply press enter to confirm the default. Then exit out of the editor with ctrl+x.

Now you can restart (and start and stop) nginx without password. Let's try it.

  1. Open new session (otherwise, you might simply not be asked for your sudo password because it has not timed out):

     $ ssh myusername@myserver
    
  2. Stop nginx

     $ sudo /usr/sbin/service nginx stop
    
  3. Confirm that nginx has stopped by checking your website or running ps aux | grep nginx

  4. Start nginx

     $ sudo /usr/sbin/service nginx start
    
  5. Confirm that nginx has started by checking your website or running ps aux | grep nginx

PS: Make sure to use sudo /usr/sbin/service nginx start|restart|stop, and not sudo service nginx start|restart|stop.

Finn
  • 1,510
  • 13
  • 22
2

Run sudo visudo

Append with below lines (in this example you can add multiple scripts and services after comma)

# Run scripts without asking for pass
<your-user> ALL=(root) NOPASSWD: /opt/fixdns.sh,/usr/sbin/service nginx *,/usr/sbin/service docker *

Save and exit with :wq

mati kepa
  • 2,543
  • 19
  • 24
0

Create a rake task in Rails_App/lib/capistrano/tasks/nginx.rake and paste below code.

namespace :nginx do
  %w(start stop restart reload).each do |command|
    desc "#{command.capitalize} Nginx"
    task command do
      on roles(:app) do
        execute :sudo, "service nginx #{command}"
      end
    end
  end
end

Then ssh to your remote server and open file

  sudo vi /etc/sudoers

and the paste this line (after line %sudo ALL=(ALL:ALL) ALL)

  deploy ALL=(ALL:ALL) NOPASSWD: /usr/sbin/service nginx *

Or, as in your case,

  deploy ALL=(ALL:ALL) NOPASSWD: /etc/init.d/nginx *

Here I am assuming your deployment user is deploy.

You can add here other commands too for which you dont require to enter password. For example

  deploy ALL=(ALL:ALL) NOPASSWD: /usr/sbin/service nginx *, /etc/init.d/mysqld, /etc/init.d/apache2
Neeraj Kumar
  • 6,045
  • 2
  • 31
  • 23