passwordless sudo still requires password in capistrano - ruby

In capistrano script
set :stage, :production
set :branch, 'master'
server 'lion.example.jp', user: 'ubuntu', roles: %w(app),
set :user, "ubuntu"
namespace :deploy do
desc 'Collec Static Files'
task :collectImg do
on roles(:app) do
execute :sudo,"curl -X GET --unix-socket /run/control.unit.sock http://localhost/control/applications/myapp/restart"
end
end
after :publishing, :collectImg
end
it shows error below
DEBUG [7fade908] sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
However I set passwordless sudo for user ubuntu
Why does it still require password?
Or can I solve this?

I think you need to set the "ubuntu" user in capistrano, like so.
I see that it's in the server block, but maybe give this a try as well.
set :user, "ubuntu"

Related

Exec systemctl after deployment by capistrano

I want to restart Nginx-unit after deployment by Capistrano
namespace :deploy do
desc 'Collec Static Files'
task :collectImg do
on roles(:app) do
execute "sudo systemctl restart unit"
end
end
after :publishing, :collectImg
end
After above code, there comes error log like this.
Is there any good way to use systemctl in deployment script???
DEBUG [08ce969a] Command: sudo systemctl restart unit
DEBUG [08ce969a] sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
First - Great you are using NGINX Unit with Capistrano!
This problem is related to a couple of issues at a time.
1. Enable tty mode
Add this to your deployment configuration deploy.rb. Capistrano 3.
set :pty, true
More Information about PTY
2. Modify your sudoers file on the App Server
You have to allow the deployment user to execute sudo commands without the need of entering a password. You can / should limit this power to specific resources. I have added restart and status as examples.
deploy ALL=NOPASSWD:/bin/systemctl restart unit.serivce, /bin/systemctl status unit.serivce
As a reference see Capistrano Auth
Would like to chat about your capistrano configuration on our Community NGINX channel.

Capifony forward_agent not working. Asks for GitHub password and fails

I am using capifony to deploy a symfony2 web app onto Ubuntu. I have the following in my deploy.rb:
set :repository, "git#github.com:Username/Repo.git"
set :branch, "develop"
set :scm_verbose, true
set :deploy_via, :remote_cache
default_run_options[:pty] = true
set :ssh_options, {:forward_agent => true}
ssh_options[:keys] = ["/Users/myuser/Sites/file.pem"]
ssh_options[:auth_methods] = ["publickey"]
Capifony is able to ssh in but then asks for a GitHub password during the deploy. I enter the password correctly but it then give me the following authentication fail error:
remote: Invalid username or password
fatal: Authentication failed for 'https://UserName#github.com/UserName/Repo.git/'
I don't know why it is asking for my Github password, and why it doesn't use agent forwarding to ssh to github?
I have added my public key from the server to GitHub but I am a bit confused about these keys, and my local keys? does it forward my local key or does it use the server one? What permissions do I need to set etc?
I am using capifony v2.8.6
I recently had to reinstall ruby and capifony die to upgrading to El Capitan which stopped capifony from working altogether. This is when my problems started.
I am deploying to Ubuntu 14.04
I have tried editing /etc/ssh/ssh_config on the server and adding
ForwardAgent yes
Then restarting ssh, but this has no effect.
Thanks
I do not use Capifony anymore and cannot comment yet so I try to answer :)
First, if you deploy from your local machine (your Mac), check :
your ssh-agent is started,
you can git clone one of your github repo
you can ssh to your Ubuntu server
Then you could just set this two line below.
default_run_options[:pty] = true
ssh_options[:forward_agent] = true
No need to set other ssh_options nor to tweak you ssh server config , it might be very confusing.
Second, you can test if ssh forwarding is working for the selected environment by creating a simple rake tasks inside your project :
namespace :ssh do
desc "Check if agent forwarding is working"
task :forwarding do
on roles(:all) do |h|
if test("env | grep SSH_AUTH_SOCK")
info "Agent forwarding is up to #{h}"
else
error "Agent forwarding is NOT up to #{h}"
end
end
end
end
And test with a cap [env] ssh:forwarding
Finally, if you reinstalled ruby/capifony recently, try to make the switch to Capistrano v3 and its Symfony gem instead, it really worth a try.

Adding local ssh option to Capistrano task

I have a Capistrano deployment script that exports my local database to a remote server and vice versa.
Here is one such task...
desc "Imports the remote database into your local environment"
task :pull do
# Create dump of remote db
invoke 'db:backup'
on roles(:app) do
run_locally do
# Create dump of current local db
execute "mysqldump -u #{fetch(:local_db_user)} -p#{fetch(:local_db_password)} #{fetch(:local_db_name)} > #{fetch(:local_backup_file)}"
# Import remote db into local
execute "mysql -u #{fetch(:local_db_user)} -p#{fetch(:local_db_password)} #{fetch(:local_db_name)} < db_backups/#{fetch(:curr_stage)}/#{fetch(:backup_filename)}.sql"
end
end
Rake::Task['db:cleanup_local'].execute
end
However I'm running a virtual host (Vagrant box) locally so to do local database tasks need to SSH into it.
What I want to do is add an option in the Capistrano options that if present will add something like ssh vagrant#192.168.10.10 to the start of the mysqldump and mysql commands and if it's not defined not add anything.
So I would want my local database connection details to look something like
set :local_db_host, "127.0.0.1"
set :local_db_name, "database_dev"
set :local_db_user, "homestead"
set :local_db_password, "secret"
set :local_ssh, "vagrant#192.168.10.10"
How could I add this option within the Capistrano task in a tidy way? Much thanks for any help.

Capistrano error : could not connect to ssh-agent

I'm using Bedrock with Capistrano deploys.
When I use command bundle exec cap staging deploy:check I get an authentication error :
...
D, [2015-05-09T15:39:53.878464 #15636] DEBUG -- net.ssh.authentication.session[1e34a58]: trying publickey
D, [2015-05-09T15:39:53.878464 #15636] DEBUG -- net.ssh.authentication.agent[1e30d2c]: connecting to ssh-agent
E, [2015-05-09T15:39:53.879447 #15636] ERROR -- net.ssh.authentication.agent[1e30d2c]: could not connect to ssh-agent
E, [2015-05-09T15:39:53.879447 #15636] ERROR -- net.ssh.authentication.session[1e34a58]: all authorization methods failed (tried publickey)
cap aborted!
SSHKit::Runner::ExecuteError: Exception while executing as deploy#SERVER_IP: Authentication failed for user deploy#SERVER_IP
Tasks: TOP => git:check => git:wrapper
Capistrano could not connect to ssh-agent on my server.
But I can log in on my server via SSH like this ssh deploy#SERVER_IP without password. I dit all the instructions in Capistrano Authentication & Authorisation Docs page, so I can use command like me#localhost $ ssh deploy#one-of-my-servers.com 'hostname; uptime'.
If I enter command ssh -A deploy#SERVER_IP 'env | grep SSH_AUTH_SOCK' I get result
SSH_AUTH_SOCK=/tmp/ssh-UweQkw7578/agent.7578
Here is my deploy.rb file :
set :application, 'APP'
set :repo_url, 'URL'
set :branch, :master
set :tmp_dir, '~/tmp'
set :log_level, :info
set :linked_files, fetch(:linked_files, []).push('.env')
set :linked_dirs, fetch(:linked_dirs, []).push('web/app/uploads')
Here is my staging.rb file :
set :stage, :staging
set :deploy_to, -> { "/var/www/vhosts/project/dev" }
server 'SERVER_IP', user: 'deploy', roles: %w{web app}
set :ssh_options, {
user: 'deploy',
keys: %w('/c/Users/alexander/.ssh/id_rsa'),
forward_agent: true,
auth_methods: %w(publickey),
verbose: :debug
}
fetch(:default_env).merge!(wp_env: :staging)
Apache's agent forwarding agent instruction is enabled in sshd_config file : AllowAgentForwarding yes
What should do with my config files to make my deploy work?
Windows 8.1
Ruby 2.2.0
Capistrano 3.2.1
Git Bash
OK so I had the same issue, and I spent way too long working out exactly what is happening here, and the upshot is -
for ruby on windows, you must run pagent, not ssh-agent, for Capistrano and agent forwarding to work - in fact pretty much any tool that uses the Ruby net-ssh library on Windows.
And I dont think that will change, at least not for a while.
Agent Forwarding
See An Illustrated Guide to SSH Agent Forwarding for more about agent forwarding, and how the key challenge ends back up on our workstation.
Terminology
workstation - the machine (Windowa server/desktop/laptop) our SSH
client software is running from, and, most importantly, our PKI
private key is stored on (with or without a passphrase)
deployment node - the target of our Capistrano deployment task, most
like defined in the 'server' key in our config/deploy.rb, or
config/deploy/.rb file
git repo - where we will pull the code from, first queried via "git
ls-remote" - we will access this git repo via SSH, and the deployment
node will use agent forwarding to pass the key challenge back to the
workstation
SSH client software - how we reach out to sshd on remote servers, and
which has access to our private key. Might be putty, an OpenSSH ssh
client or the net-ssh library in Ruby.
Setup
I have a Windows 7 workstation box, with Git-Bash, and its OpenSSH ssh client, plus the script from Joe Reagle that sets up some environmental variables that say which port and pid the ssh-agent is operating on.
I also have Putty and Pageant, but I focussed, initially, on just the OpenSSH/Git-Bash tools.
I have set up passwordless ssh from the workstation to the deployment node, I have the ssh-agent running, I have my key added through ssh-add, and I have my public key registered as a read-only access key to the git repo.
Basics
So we are trying to use SSH agent forwarding to have Capistrano pull from our Git repo onto our deployment node.
Now we can test this all ourselves by setting up our public SSH key on the deployment node and using, say, the OpenSSH ssh client, to confirm we have passwordless ssh working. Then we can setup ssh-agent by
starting ssh-agent and setting the SSH_AUTH_SOCK and SSH_AGENT_PID as required.
adding our private key to the ssh-agent via ssh-add
add our public key as an authorised key to the git repo
ssh to the deployment node, and from there do a "git ls-remote git#" (or a ssh -T git#)
If everything is setup correctly, this will all work, and so we will think "ok I can do a 'cap deploy:check'" - and it will fail.
What Went Wrong
We will get an error
"Error reading response length from authentication socket"
Who is telling us this ? It isnt immediately clear, but it
isn't the git repo
it isnt the git client on the deployment node
it isnt the sshd daemon on the deployment node, that wants to pass the key challenge back to the workstation.
Its the Ruby ssh client library on the workstation.
How do we know this
In the ssh_options hash in the deploy.rb file, we add the following :
verbose: :debug
When we do this we see this message
Pageant not running.
Why is Capistrano trying to use Pageant instead of ssh-agent
When running via Capistrano, the ssh client is different to the one you used when verifying things by hand.
When verifying by hand, it was an OpenSSH ssh client. Now it is the net-ssh library in Ruby.
And on Windows, net-ssh has these lines
if Net::SSH::Authentication::PLATFORM == :win32
require 'net/ssh/authentication/pageant'
end
or
case Net::SSH::Authentication::PLATFORM
when :java_win32
require 'net/ssh/authentication/agent/java_pageant'
else
require 'net/ssh/authentication/agent/socket'
So loading pageant is hard-coded into net-ssh. It doesnt even try to see if you are running under a unix-like shell (like git-bash or cygwin), and to then use the unix-domain ssh-agent SSH_AUTH_SOCK
At present net-ssh doesnt try to open a unix-domain named socket. In theory I think it could, through the UNIXSocket class in the stdlib. But I haven't experimented with that on a Windows machine yet.

Capistrano, Firewalls and Tunnel

We're using Capistrano to automate pushing new versions of a PHP application to a production server. The production server (we'll call it production) is public, while our repository server (we'll call it repo) sits behind our corporate firewall, along with our own machines.
Capistrano, as configured by default, won't work, as production can't talk to repo.
I was wondering if there was someway I could setup capistrano to SSH to repo first, then SSH to production opening a tunnel on a port that I can then use to SSH from production back to repo to pull the changes from SCM.
I just can't figure out how to set this up or figure out a better solution. Ideas?
Edit:
I've tried this:
role :web, "deploy.com"
namespace :deploy do
task :remote_tunnel do
run 'Creating SSH tunnel...' do |channel, stream, data|
ssh = channel.connection
ssh.forward.remote(22, 'server.com', 10000, '127.0.0.1')
ssh.loop {!ssh.forward.active_remotes.include?([10000, '127.0.0.1'])}
end
end
end
before "deploy:update_code", "deploy:remote_tunnel"
But I keep getting this error:
failed: "sh -c 'Creating SSH tunnel...'" on deploy.com
Here's are 2 ways to accomplish it.
1st way
not sure if you've seen this thread?
https://groups.google.com/forum/?fromgroups=#!topic/capistrano/RVwMim-qnMg
It makes use of the net-ssh-gateway library, but creates copies of the local forwarding methods but they're geared for remote access.
class Net::SSH::Gateway
# Opens a SSH tunnel from a port on a remote host to a given host and port
# on the local side
# (equivalent to openssh -R parameter)
def open_remote(port, host, remote_port, remote_host = "127.0.0.1")
ensure_open!
#session_mutex.synchronize do
#session.forward.remote(port, host, remote_port, remote_host)
end
if block_given?
begin
yield [remote_port, remote_host]
ensure
close_remote(remote_port, remote_host)
end
else
return [remote_port, remote_host]
end
rescue Errno::EADDRINUSE
retry
end
# Cancels port-forwarding over an open port that was previously opened via
# open_remote.
def close_remote(port, host = "127.0.0.1")
ensure_open!
#session_mutex.synchronize do
#session.forward.cancel_remote(port, host)
end
end
end
2nd way
Outlined in an answer to this SO question:
Is it possible to do have Capistrano do a checkout over a reverse SSH tunnel?
This technique is very similar to the 1st way. First you need to create 2 paths to the repository:
# deploy.rb
set :local_repository, "ssh://git#serverbehindfirewall/path/to/project.git"
set :repository, "ssh://git#localhost:9000/path/to/project.git"
Then before you deploy you'll need to setup the remote forward:
% ssh -R 9000:serverbehindfirewall:22 deploybot#deployserver.com
# CTRL + C + A (Screen) or ⌘ + T (Terminal.app) to open new tab
Followed by your deploy:
% cap HOSTFILTER=deployserver.com deploy # HOSTFILTER reduces set to specified host. Only useful if you have multiple servers.
See this answer to that SO question for more details:
https://stackoverflow.com/a/3953351/33204
Using Capistrano 3.x, the following works for me:
namespace :deploy do
desc "Open SSH Tunnel to GitLab"
task :open_tunnel do
on roles(:app) do
info "Opening SSH Remote Tunnel..."
self.send(:with_ssh) do |ssh|
# ssh -R 9000:192.168.1.123:22
ssh.forward.remote(22, "192.168.1.123", 9000)
end
end
end
before "deploy:check", "deploy:open_tunnel"
end
Please note that ssh.forward.remote expects parameters in a different order than ssh -R, the above is equivalent to ssh -R 9000:192.168.1.123:22
This task calls a private method, if anyone knows an official way to get the access Capistrano's ssh connection, please comment or edit.
Edit: Also see the section Tunneling and other related SSH themes of SSHKit's README

Resources