mirror of
https://github.com/capistrano/capistrano
synced 2023-03-27 23:21:18 -04:00
More Docs!
This commit is contained in:
parent
0e1bf5d13a
commit
94b8564296
18 changed files with 1835 additions and 120 deletions
30
_includes/metrics.html
Normal file
30
_includes/metrics.html
Normal file
|
@ -0,0 +1,30 @@
|
|||
<script type="text/javascript">
|
||||
var _gauges = _gauges || [];
|
||||
(function() {
|
||||
var t = document.createElement('script');
|
||||
t.type = 'text/javascript';
|
||||
t.async = true;
|
||||
t.id = 'gauges-tracker';
|
||||
t.setAttribute('data-site-id', '51c83c32613f5d7df70000bc');
|
||||
t.src = '//secure.gaug.es/track.js';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(t, s);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
setTimeout(function(){var a=document.createElement("script");
|
||||
var b=document.getElementsByTagName("script")[0];
|
||||
a.src=document.location.protocol+"//dnn506yrbagrg.cloudfront.net/pages/scripts/0017/6418.js?"+Math.floor(new Date().getTime()/3600000);
|
||||
a.async=true;a.type="text/javascript";b.parentNode.insertBefore(a,b)}, 1);
|
||||
</script>
|
||||
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-41970098-1', 'capistranorb.com');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
|
@ -8,7 +8,7 @@
|
|||
<h5>Getting Started</h5>
|
||||
<li><a href="/documentation/getting-started/installation/">Installation</a></li>
|
||||
<li><a href="/documentation/getting-started/preparing-your-application/">Preparing Your Application</a></li>
|
||||
<li><aj href="/documentation/getting-started/authentication-and-authorisation/">Authentication & Authorisation</a></li>
|
||||
<li><a href="/documentation/getting-started/authentication-and-authorisation/">Authentication & Authorisation</a></li>
|
||||
<li><a href="/documentation/getting-started/cold-start/">Cold Start</a></li>
|
||||
<li><a href="/documentation/getting-started/rollbacks/">Rollbacks</a></li>
|
||||
<li class="divider"></li>
|
||||
|
|
|
@ -16,6 +16,36 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var _gauges = _gauges || [];
|
||||
(function() {
|
||||
var t = document.createElement('script');
|
||||
t.type = 'text/javascript';
|
||||
t.async = true;
|
||||
t.id = 'gauges-tracker';
|
||||
t.setAttribute('data-site-id', '51c83c32613f5d7df70000bc');
|
||||
t.src = '//secure.gaug.es/track.js';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(t, s);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
setTimeout(function(){var a=document.createElement("script");
|
||||
var b=document.getElementsByTagName("script")[0];
|
||||
a.src=document.location.protocol+"//dnn506yrbagrg.cloudfront.net/pages/scripts/0017/6418.js?"+Math.floor(new Date().getTime()/3600000);
|
||||
a.async=true;a.type="text/javascript";b.parentNode.insertBefore(a,b)}, 1);
|
||||
</script>
|
||||
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-41970098-1', 'capistranorb.com');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
{% include header.html %}
|
||||
|
||||
<div class="row">
|
||||
|
|
|
@ -16,6 +16,36 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var _gauges = _gauges || [];
|
||||
(function() {
|
||||
var t = document.createElement('script');
|
||||
t.type = 'text/javascript';
|
||||
t.async = true;
|
||||
t.id = 'gauges-tracker';
|
||||
t.setAttribute('data-site-id', '51c83c32613f5d7df70000bc');
|
||||
t.src = '//secure.gaug.es/track.js';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(t, s);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
setTimeout(function(){var a=document.createElement("script");
|
||||
var b=document.getElementsByTagName("script")[0];
|
||||
a.src=document.location.protocol+"//dnn506yrbagrg.cloudfront.net/pages/scripts/0017/6418.js?"+Math.floor(new Date().getTime()/3600000);
|
||||
a.async=true;a.type="text/javascript";b.parentNode.insertBefore(a,b)}, 1);
|
||||
</script>
|
||||
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-41970098-1', 'capistranorb.com');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
<div class="top-bar">
|
||||
<a href="/" class="brand">
|
||||
<img src="/images/CapistranoLogo.png" />
|
||||
|
@ -33,28 +63,28 @@
|
|||
<li><a href="/documentation/overview/introductory-demo-video/">Introductory Demo Video</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Getting Started</h5>
|
||||
<li><a href="/documentation/getting-started/installation/index.html">Installation</a></li>
|
||||
<li><a href="/documentation/getting-started/preparing-your-application/index.html">Preparing Your Application</a></li>
|
||||
<li><aj href="/documentation/getting-started/authentication-and-authorisation/index.html">Authentication & Authorisation</a></li>
|
||||
<li><a href="/documentation/getting-started/cold-start/index.html">Cold Start</a></li>
|
||||
<li><a href="/documentation/getting-started/rollbacks/index.html">Rollbacks</a></li>
|
||||
<li><a href="/documentation/getting-started/installation/">Installation</a></li>
|
||||
<li><a href="/documentation/getting-started/preparing-your-application/">Preparing Your Application</a></li>
|
||||
<li><a href="/documentation/getting-started/authentication-and-authorisation/">Authentication & Authorisation</a></li>
|
||||
<li><a href="/documentation/getting-started/cold-start/">Cold Start</a></li>
|
||||
<li><a href="/documentation/getting-started/rollbacks/">Rollbacks</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Troubleshooting</h5>
|
||||
<li><a href="/documentation/troubleshooting/authentication/index.html">SCM (Git) Authentication</a></li>
|
||||
<li><a href="/documentation/troubleshooting/connectivity/index.html">Connectivity</a></li>
|
||||
<!--<li><a href="/documentation/troubleshooting/gateway-servers/index.html">Gateway Servers</a></li>-->
|
||||
<li><a href="/documentation/troubleshooting/agent-forwarding/index.html">Agent Forwarding</a></li>
|
||||
<li><a href="/documentation/troubleshooting/sudo-password/index.html">`sudo` Password</a></li>
|
||||
<li><a href="/documentation/troubleshooting/rvm-rbenv-nvm/index.html">RVM, `rbenv` And `nvm`</a></li>
|
||||
<li><a href="/documentation/troubleshooting/authentication/">SCM (Git) Authentication</a></li>
|
||||
<li><a href="/documentation/troubleshooting/connectivity/">Connectivity</a></li>
|
||||
<!--<li><a href="/documentation/troubleshooting/gateway-servers/">Gateway Servers</a></li>-->
|
||||
<li><a href="/documentation/troubleshooting/agent-forwarding/">Agent Forwarding</a></li>
|
||||
<li><a href="/documentation/troubleshooting/sudo-password/">`sudo` Password</a></li>
|
||||
<li><a href="/documentation/troubleshooting/rvm-rbenv-nvm/">RVM, `rbenv` And `nvm`</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>FAQ</h5>
|
||||
<li><a
|
||||
href="/documentation/faq/why-does-something-work-in-my-ssh-session-but-not-in-capistrano/index.html">Why Does Something Work In An SSH Session, But Not In Capistrano?</a></li>
|
||||
<li><a href="/documentation/faq/should-i-use-capistrano-to-provision-my-servers/index.html">Should I Use Capistrano To Provision My Servers?</a></li>
|
||||
href="/documentation/faq/why-does-something-work-in-my-ssh-session-but-not-in-capistrano/">Why Does Something Work In An SSH Session, But Not In Capistrano?</a></li>
|
||||
<li><a href="/documentation/faq/should-i-use-capistrano-to-provision-my-servers/">Should I Use Capistrano To Provision My Servers?</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Power Use-Cases</h5>
|
||||
<li><a href="/documentation/power-use-cases/integration-with-rake/index.html">Integration With Rake</a></li>
|
||||
<li><a href="/documentation/power-use-cases/driving-tools-such-as-chef-solo/index.html">Driving Tools Such As <em>Chef Solo</em></a></li>
|
||||
<li><a href="/documentation/power-use-cases/integration-with-rake/">Integration With Rake</a></li>
|
||||
<li><a href="/documentation/power-use-cases/driving-tools-such-as-chef-solo/">Driving Tools Such As <em>Chef Solo</em></a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Recent Announcements</h5>
|
||||
|
||||
|
|
|
@ -16,6 +16,36 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var _gauges = _gauges || [];
|
||||
(function() {
|
||||
var t = document.createElement('script');
|
||||
t.type = 'text/javascript';
|
||||
t.async = true;
|
||||
t.id = 'gauges-tracker';
|
||||
t.setAttribute('data-site-id', '51c83c32613f5d7df70000bc');
|
||||
t.src = '//secure.gaug.es/track.js';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(t, s);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
setTimeout(function(){var a=document.createElement("script");
|
||||
var b=document.getElementsByTagName("script")[0];
|
||||
a.src=document.location.protocol+"//dnn506yrbagrg.cloudfront.net/pages/scripts/0017/6418.js?"+Math.floor(new Date().getTime()/3600000);
|
||||
a.async=true;a.type="text/javascript";b.parentNode.insertBefore(a,b)}, 1);
|
||||
</script>
|
||||
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-41970098-1', 'capistranorb.com');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
<div class="top-bar">
|
||||
<a href="/" class="brand">
|
||||
<img src="/images/CapistranoLogo.png" />
|
||||
|
@ -33,28 +63,28 @@
|
|||
<li><a href="/documentation/overview/introductory-demo-video/">Introductory Demo Video</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Getting Started</h5>
|
||||
<li><a href="/documentation/getting-started/installation/index.html">Installation</a></li>
|
||||
<li><a href="/documentation/getting-started/preparing-your-application/index.html">Preparing Your Application</a></li>
|
||||
<li><aj href="/documentation/getting-started/authentication-and-authorisation/index.html">Authentication & Authorisation</a></li>
|
||||
<li><a href="/documentation/getting-started/cold-start/index.html">Cold Start</a></li>
|
||||
<li><a href="/documentation/getting-started/rollbacks/index.html">Rollbacks</a></li>
|
||||
<li><a href="/documentation/getting-started/installation/">Installation</a></li>
|
||||
<li><a href="/documentation/getting-started/preparing-your-application/">Preparing Your Application</a></li>
|
||||
<li><a href="/documentation/getting-started/authentication-and-authorisation/">Authentication & Authorisation</a></li>
|
||||
<li><a href="/documentation/getting-started/cold-start/">Cold Start</a></li>
|
||||
<li><a href="/documentation/getting-started/rollbacks/">Rollbacks</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Troubleshooting</h5>
|
||||
<li><a href="/documentation/troubleshooting/authentication/index.html">SCM (Git) Authentication</a></li>
|
||||
<li><a href="/documentation/troubleshooting/connectivity/index.html">Connectivity</a></li>
|
||||
<!--<li><a href="/documentation/troubleshooting/gateway-servers/index.html">Gateway Servers</a></li>-->
|
||||
<li><a href="/documentation/troubleshooting/agent-forwarding/index.html">Agent Forwarding</a></li>
|
||||
<li><a href="/documentation/troubleshooting/sudo-password/index.html">`sudo` Password</a></li>
|
||||
<li><a href="/documentation/troubleshooting/rvm-rbenv-nvm/index.html">RVM, `rbenv` And `nvm`</a></li>
|
||||
<li><a href="/documentation/troubleshooting/authentication/">SCM (Git) Authentication</a></li>
|
||||
<li><a href="/documentation/troubleshooting/connectivity/">Connectivity</a></li>
|
||||
<!--<li><a href="/documentation/troubleshooting/gateway-servers/">Gateway Servers</a></li>-->
|
||||
<li><a href="/documentation/troubleshooting/agent-forwarding/">Agent Forwarding</a></li>
|
||||
<li><a href="/documentation/troubleshooting/sudo-password/">`sudo` Password</a></li>
|
||||
<li><a href="/documentation/troubleshooting/rvm-rbenv-nvm/">RVM, `rbenv` And `nvm`</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>FAQ</h5>
|
||||
<li><a
|
||||
href="/documentation/faq/why-does-something-work-in-my-ssh-session-but-not-in-capistrano/index.html">Why Does Something Work In An SSH Session, But Not In Capistrano?</a></li>
|
||||
<li><a href="/documentation/faq/should-i-use-capistrano-to-provision-my-servers/index.html">Should I Use Capistrano To Provision My Servers?</a></li>
|
||||
href="/documentation/faq/why-does-something-work-in-my-ssh-session-but-not-in-capistrano/">Why Does Something Work In An SSH Session, But Not In Capistrano?</a></li>
|
||||
<li><a href="/documentation/faq/should-i-use-capistrano-to-provision-my-servers/">Should I Use Capistrano To Provision My Servers?</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Power Use-Cases</h5>
|
||||
<li><a href="/documentation/power-use-cases/integration-with-rake/index.html">Integration With Rake</a></li>
|
||||
<li><a href="/documentation/power-use-cases/driving-tools-such-as-chef-solo/index.html">Driving Tools Such As <em>Chef Solo</em></a></li>
|
||||
<li><a href="/documentation/power-use-cases/integration-with-rake/">Integration With Rake</a></li>
|
||||
<li><a href="/documentation/power-use-cases/driving-tools-such-as-chef-solo/">Driving Tools Such As <em>Chef Solo</em></a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Recent Announcements</h5>
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ body {
|
|||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: 400;
|
||||
font-family: 'Enriqueta', serif;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,36 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var _gauges = _gauges || [];
|
||||
(function() {
|
||||
var t = document.createElement('script');
|
||||
t.type = 'text/javascript';
|
||||
t.async = true;
|
||||
t.id = 'gauges-tracker';
|
||||
t.setAttribute('data-site-id', '51c83c32613f5d7df70000bc');
|
||||
t.src = '//secure.gaug.es/track.js';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(t, s);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
setTimeout(function(){var a=document.createElement("script");
|
||||
var b=document.getElementsByTagName("script")[0];
|
||||
a.src=document.location.protocol+"//dnn506yrbagrg.cloudfront.net/pages/scripts/0017/6418.js?"+Math.floor(new Date().getTime()/3600000);
|
||||
a.async=true;a.type="text/javascript";b.parentNode.insertBefore(a,b)}, 1);
|
||||
</script>
|
||||
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-41970098-1', 'capistranorb.com');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
<div class="top-bar">
|
||||
<a href="/" class="brand">
|
||||
<img src="/images/CapistranoLogo.png" />
|
||||
|
@ -33,28 +63,28 @@
|
|||
<li><a href="/documentation/overview/introductory-demo-video/">Introductory Demo Video</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Getting Started</h5>
|
||||
<li><a href="/documentation/getting-started/installation/index.html">Installation</a></li>
|
||||
<li><a href="/documentation/getting-started/preparing-your-application/index.html">Preparing Your Application</a></li>
|
||||
<li><aj href="/documentation/getting-started/authentication-and-authorisation/index.html">Authentication & Authorisation</a></li>
|
||||
<li><a href="/documentation/getting-started/cold-start/index.html">Cold Start</a></li>
|
||||
<li><a href="/documentation/getting-started/rollbacks/index.html">Rollbacks</a></li>
|
||||
<li><a href="/documentation/getting-started/installation/">Installation</a></li>
|
||||
<li><a href="/documentation/getting-started/preparing-your-application/">Preparing Your Application</a></li>
|
||||
<li><a href="/documentation/getting-started/authentication-and-authorisation/">Authentication & Authorisation</a></li>
|
||||
<li><a href="/documentation/getting-started/cold-start/">Cold Start</a></li>
|
||||
<li><a href="/documentation/getting-started/rollbacks/">Rollbacks</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Troubleshooting</h5>
|
||||
<li><a href="/documentation/troubleshooting/authentication/index.html">SCM (Git) Authentication</a></li>
|
||||
<li><a href="/documentation/troubleshooting/connectivity/index.html">Connectivity</a></li>
|
||||
<!--<li><a href="/documentation/troubleshooting/gateway-servers/index.html">Gateway Servers</a></li>-->
|
||||
<li><a href="/documentation/troubleshooting/agent-forwarding/index.html">Agent Forwarding</a></li>
|
||||
<li><a href="/documentation/troubleshooting/sudo-password/index.html">`sudo` Password</a></li>
|
||||
<li><a href="/documentation/troubleshooting/rvm-rbenv-nvm/index.html">RVM, `rbenv` And `nvm`</a></li>
|
||||
<li><a href="/documentation/troubleshooting/authentication/">SCM (Git) Authentication</a></li>
|
||||
<li><a href="/documentation/troubleshooting/connectivity/">Connectivity</a></li>
|
||||
<!--<li><a href="/documentation/troubleshooting/gateway-servers/">Gateway Servers</a></li>-->
|
||||
<li><a href="/documentation/troubleshooting/agent-forwarding/">Agent Forwarding</a></li>
|
||||
<li><a href="/documentation/troubleshooting/sudo-password/">`sudo` Password</a></li>
|
||||
<li><a href="/documentation/troubleshooting/rvm-rbenv-nvm/">RVM, `rbenv` And `nvm`</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>FAQ</h5>
|
||||
<li><a
|
||||
href="/documentation/faq/why-does-something-work-in-my-ssh-session-but-not-in-capistrano/index.html">Why Does Something Work In An SSH Session, But Not In Capistrano?</a></li>
|
||||
<li><a href="/documentation/faq/should-i-use-capistrano-to-provision-my-servers/index.html">Should I Use Capistrano To Provision My Servers?</a></li>
|
||||
href="/documentation/faq/why-does-something-work-in-my-ssh-session-but-not-in-capistrano/">Why Does Something Work In An SSH Session, But Not In Capistrano?</a></li>
|
||||
<li><a href="/documentation/faq/should-i-use-capistrano-to-provision-my-servers/">Should I Use Capistrano To Provision My Servers?</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Power Use-Cases</h5>
|
||||
<li><a href="/documentation/power-use-cases/integration-with-rake/index.html">Integration With Rake</a></li>
|
||||
<li><a href="/documentation/power-use-cases/driving-tools-such-as-chef-solo/index.html">Driving Tools Such As <em>Chef Solo</em></a></li>
|
||||
<li><a href="/documentation/power-use-cases/integration-with-rake/">Integration With Rake</a></li>
|
||||
<li><a href="/documentation/power-use-cases/driving-tools-such-as-chef-solo/">Driving Tools Such As <em>Chef Solo</em></a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Recent Announcements</h5>
|
||||
|
||||
|
|
|
@ -0,0 +1,774 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Authentication & Authorisation</title>
|
||||
<link href='http://fonts.googleapis.com/css?family=Enriqueta' rel='stylesheet' type='text/css'>
|
||||
<script type="text/javascript" src="//use.typekit.net/itm5ubu.js"></script>
|
||||
<script type="text/javascript">try{Typekit.load();}catch(e){}</script>
|
||||
<link rel="stylesheet" href="/css/foundation.css" />
|
||||
<link rel="stylesheet" href="/css/capistrano.css">
|
||||
<link rel="stylesheet" href="/css/social_foundicons.css" />
|
||||
<link rel="stylesheet" href="/css/okaidia.css">
|
||||
<script src="/js/vendor/custom.modernizr.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var _gauges = _gauges || [];
|
||||
(function() {
|
||||
var t = document.createElement('script');
|
||||
t.type = 'text/javascript';
|
||||
t.async = true;
|
||||
t.id = 'gauges-tracker';
|
||||
t.setAttribute('data-site-id', '51c83c32613f5d7df70000bc');
|
||||
t.src = '//secure.gaug.es/track.js';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(t, s);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
setTimeout(function(){var a=document.createElement("script");
|
||||
var b=document.getElementsByTagName("script")[0];
|
||||
a.src=document.location.protocol+"//dnn506yrbagrg.cloudfront.net/pages/scripts/0017/6418.js?"+Math.floor(new Date().getTime()/3600000);
|
||||
a.async=true;a.type="text/javascript";b.parentNode.insertBefore(a,b)}, 1);
|
||||
</script>
|
||||
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-41970098-1', 'capistranorb.com');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
<div class="top-bar">
|
||||
<a href="/" class="brand">
|
||||
<img src="/images/CapistranoLogo.png" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="large-4 columns">
|
||||
<ul class="side-nav">
|
||||
<li><a href="http://www.harrow.io/" class="advertisment"><span class="label label-important">New</span> Hosted Capistrano for Teams</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Overview</h5>
|
||||
<li><a href="/documentation/overview/what-is-capistrano/">What is Capistrano?</a></li>
|
||||
<li><a href="/documentation/overview/introductory-demo-video/">Introductory Demo Video</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Getting Started</h5>
|
||||
<li><a href="/documentation/getting-started/installation/">Installation</a></li>
|
||||
<li><a href="/documentation/getting-started/preparing-your-application/">Preparing Your Application</a></li>
|
||||
<li><a href="/documentation/getting-started/authentication-and-authorisation/">Authentication & Authorisation</a></li>
|
||||
<li><a href="/documentation/getting-started/cold-start/">Cold Start</a></li>
|
||||
<li><a href="/documentation/getting-started/rollbacks/">Rollbacks</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Troubleshooting</h5>
|
||||
<li><a href="/documentation/troubleshooting/authentication/">SCM (Git) Authentication</a></li>
|
||||
<li><a href="/documentation/troubleshooting/connectivity/">Connectivity</a></li>
|
||||
<!--<li><a href="/documentation/troubleshooting/gateway-servers/">Gateway Servers</a></li>-->
|
||||
<li><a href="/documentation/troubleshooting/agent-forwarding/">Agent Forwarding</a></li>
|
||||
<li><a href="/documentation/troubleshooting/sudo-password/">`sudo` Password</a></li>
|
||||
<li><a href="/documentation/troubleshooting/rvm-rbenv-nvm/">RVM, `rbenv` And `nvm`</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>FAQ</h5>
|
||||
<li><a
|
||||
href="/documentation/faq/why-does-something-work-in-my-ssh-session-but-not-in-capistrano/">Why Does Something Work In An SSH Session, But Not In Capistrano?</a></li>
|
||||
<li><a href="/documentation/faq/should-i-use-capistrano-to-provision-my-servers/">Should I Use Capistrano To Provision My Servers?</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Power Use-Cases</h5>
|
||||
<li><a href="/documentation/power-use-cases/integration-with-rake/">Integration With Rake</a></li>
|
||||
<li><a href="/documentation/power-use-cases/driving-tools-such-as-chef-solo/">Driving Tools Such As <em>Chef Solo</em></a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Recent Announcements</h5>
|
||||
|
||||
<li><a href="/2013/06/01/release-announcement.html"><span class="post-date">01 Jun 2013</span> Capistrano Version 3 Release Announcement</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<div class="large-8 column">
|
||||
<div class="content">
|
||||
<h2>Authentication & Authorisation</h2>
|
||||
<p><strong>Note:</strong> In the documentation we simply recommend creating a single deployment user,
|
||||
and sharing it between team members. If you know why this is a bad idea (or
|
||||
why this may be against regulations in your jurisdiction in some cases, we
|
||||
assume that you know well enough how to use groups, umasking and setgid bits
|
||||
to make this work reliably for unique logins across team members)</p>
|
||||
|
||||
<p>To create this deploy user we'll assume something like the following has been
|
||||
done:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>root@remote $ adduser deploy
|
||||
root@remote $ passwd -l deploy</code></pre>
|
||||
</div>
|
||||
|
||||
<p>The first line creates a completely standard user, it has a home directory,
|
||||
which we'll need in a moment, and has a shell, so it may log in. This needs to
|
||||
be done <strong>on every server in your environment</strong>.</p>
|
||||
|
||||
<p>The second line <em>locks</em> the user, it changes the user's password to an
|
||||
untypable string, guaranteeing that the user has no password which can be used
|
||||
to log in.</p>
|
||||
|
||||
<h3 id="toc_0">Authentication</h3>
|
||||
|
||||
<p>There are two places that we need automated, promptless authentication:</p>
|
||||
|
||||
<ol>
|
||||
<li><strong>From our workstation/notebook/etc to our servers.</strong> We do this with <strong>SSH
|
||||
keys</strong>, passphrase protected, ideally, using a <strong>key agent</strong>.</li>
|
||||
<li><strong>From our servers to the repository host</strong>. We do this so that our servers
|
||||
can check out our application code from Github, or similar and install it
|
||||
to the servers. This is usually done using <strong>SSH agent forwarding</strong>, HTTP
|
||||
authentication, or with deploy keys.</li>
|
||||
</ol>
|
||||
|
||||
<h4 id="toc_1">1.1 SSH keys from workstation to servers</h4>
|
||||
|
||||
<p><strong>Note:</strong> If you are on Windows, all bets are off, I'd love it if someone
|
||||
could contribute a Windows guide to this, so we can include it here.</p>
|
||||
|
||||
<p>An SSH key is a mechanism that allows a <em>public</em> half one key to be placed on
|
||||
a server, when we want to authenticate with that server, our SSH client uses
|
||||
the <strong>private</strong> part of that key to negotiate with the server, if the keys are
|
||||
correct, then we need to create the key.</p>
|
||||
|
||||
<p><strong>Hint:</strong> If you have more than one developer in your team, they should all add their
|
||||
public key to the <code>deploy</code> user's <code>authorized_keys</code> file, that way if someone
|
||||
quits or gets fired, you can remove their key from that file, and the rest of
|
||||
you can keep on shipping!</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh-keygen -t rsa -C 'me@my_email_address.com'</code></pre>
|
||||
</div>
|
||||
|
||||
<p>You'll be prompted for a passphrase, that's fine. Type one and keep it safe.
|
||||
This passphrase ensures that if your computer is stolen, people still need a
|
||||
passphrase to access your keys, in order to access your servers.</p>
|
||||
|
||||
<p>To avoid having to type this passphrase every time you need to use a key, most
|
||||
operating systems have a concept of a <em>key agent</em>. This <em>key agent</em> stores SSH
|
||||
keys securely between uses, typically the first time a key is needed in a
|
||||
given time period, the SSH agent will load the key, prompt you for your
|
||||
passphrase and then the key agent will remember the key for a certain amount
|
||||
of time (on OSX it tends to be indefinite, on linux this can vary from 15
|
||||
minutes updwards.)</p>
|
||||
|
||||
<p>We can see which keys are loaded in the SSH agent by running <code>ssh-add -l</code></p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh-add -l
|
||||
2048 af:ce:7e:c5:93:18:39:ff:54:20:7a:2d:ec:05:7c:a5 /Users/me/.ssh/id_rsa (RSA)</code></pre>
|
||||
</div>
|
||||
|
||||
<p>If you don't see any keys listed, you can simply run <code>ssh-add</code>:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhsot $ ssh-add
|
||||
Identity added: /Users/me/.ssh/id_rsa (/Users/me/.ssh/id_rsa)</code></pre>
|
||||
</div>
|
||||
|
||||
<p>Typically, ssh-add will ask you for the passphrase when you add a key.</p>
|
||||
|
||||
<p><strong>Note:</strong> Although it's not mandatory to use an SSH agent (one could simply
|
||||
use an unpassphrased key, and rely on SSH to find the key and exchange it).
|
||||
Using an SSH agent makes things more secure, because we can use a passphrased
|
||||
key without being prompts every time it is used. It <strong>also</strong> allows us to use
|
||||
this same key to access the repository <em>via</em> the server without creating an
|
||||
additional identity.</p>
|
||||
|
||||
<p>At this point with the key loaded into the agent, we need to put the
|
||||
<strong>public</strong> part of the key into a file on each remote server called
|
||||
<code>/home/users/deploy/.ssh/authorized_keys</code>, to get the contents of that file,
|
||||
we can ask our local key agent for the public parts of the keys it has loaded:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh-add -L
|
||||
ssh-rsa jccXJ/JRfGxnkh/8iL........dbfCH/9cDiKa0Dw8XGAo01mU/w== /Users/me/.ssh/id_rsa</code></pre>
|
||||
</div>
|
||||
|
||||
<p>This will be a lot longer when you run it, I snipped the output because it
|
||||
looked bad.</p>
|
||||
|
||||
<p>This line, as one line, needs to make it to the remote server and be added <em>to
|
||||
it's own line</em> of the <code>deploy</code> user's <code>~/.ssh/authorized_keys</code> file. This file
|
||||
then needs to be changed to permission mode <code>0600</code> (owner read/write, group
|
||||
none, other none), in the <code>~/.ssh</code> directory which needs the permissions
|
||||
<code>0700</code> (owner read/write/execute, group none, other none).</p>
|
||||
|
||||
<p>If you are on linux there often exists a command
|
||||
<a href="http://linux.die.net/man/1/ssh-copy-id"><code>ssh-copy-id</code></a> which streamlines this
|
||||
process, otherwise the worlflow is something like:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh root@remote
|
||||
root@remote $ su - deploy
|
||||
deploy@remote $ cd ~
|
||||
deploy@remote $ mkdir .ssh
|
||||
deploy@remote $ echo "ssh-rsa jccXJ/JRfGxnkh/8iL........dbfCH/9cDiKa0Dw8XGAo01mU/w== /Users/me/.ssh/id_rsa" >> .ssh/authorized_keys
|
||||
deploy@remote $ chmod 700 .ssh
|
||||
deploy@remote $ chmod 600 .ssh/authorized_keys</code></pre>
|
||||
</div>
|
||||
|
||||
<p><strong>Remember:</strong> This needs to be done on every server you want to use, you can
|
||||
use the same key for each one, but only one key per developer is recommended.
|
||||
<em>Private</em> keys are named as such for a reason!</p>
|
||||
|
||||
<p>If we did all that correctly, we should now be able to do something like this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh deploy@one-of-my-servers.com 'hostname; uptime'
|
||||
one-of-my-servers.com
|
||||
19:23:32 up 62 days, 44 min, 1 user, load average: 0.00, 0.01, 0.05</code></pre>
|
||||
</div>
|
||||
|
||||
<p>That should happen without having to enter a passphrase for your SSH key, or
|
||||
promoting you for an SSH password (which the deploy user doesn't have anyway).</p>
|
||||
|
||||
<p>Verify that this works for all of your servers, and put your private key
|
||||
somewhere safe. If you're working with multiple team members, it often pays to
|
||||
collect everyone's public keys, indeed if your team is already using SSH keys
|
||||
to access Github, you can reach any user's SSH keys at the following URL:</p>
|
||||
|
||||
<ul>
|
||||
<li><code>https://github.com/theirusername.keys</code></li>
|
||||
</ul>
|
||||
|
||||
<p>This can make getting user's keys onto servers much easier, as you can simply
|
||||
<code>curl</code>/<code>wget</code> each user's key into the authorized keys file on the server
|
||||
directly from Github.</p>
|
||||
|
||||
<blockquote class="twitter-tweet"><p>TIL <a
|
||||
href="https://twitter.com/github">@github</a> exposes the ssh public keys for
|
||||
users. <a href="https://t.co/Wo9g8nxI">https://t.co/Wo9g8nxI</a> Handy for
|
||||
adding devs to servers/repos.</p>— Postmodern (@postmodern_mod3) <a
|
||||
href="https://twitter.com/postmodern_mod3/statuses/300438256200339456">February
|
||||
10, 2013</a></blockquote>
|
||||
|
||||
<script async src="//platform.twitter.com/widgets.js"
|
||||
charset="utf-8"></script>
|
||||
|
||||
<h4 id="toc_2">1.2 From our servers to the repository host</h4>
|
||||
|
||||
<p>With access from workstations to the servers settled, there is another hop to
|
||||
contend with, which is letting the deploy user get access to the code
|
||||
repository automatically. The options in order of preference:</p>
|
||||
|
||||
<h5 id="toc_3">1.2.1 SSH Agent Forwarding</h5>
|
||||
|
||||
<p>As we've already set up an SSH agent, we can use the <em>agent forwarding</em>
|
||||
feature of SSH to make this key agent available to further <em>hops</em>. In short,
|
||||
we can use <strong>our own ssh key</strong> to authenticate ourselves from the server, to
|
||||
Github.</p>
|
||||
|
||||
<p>Here's how we can check if that works, first get the URL of the repository:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ git config remote.origin.url
|
||||
git@github.com:capistrano/rails3-bootstrap-devise-cancan.git</code></pre>
|
||||
</div>
|
||||
|
||||
<p>Here we're listing our private (for testing purposes) fork of the
|
||||
rails3-bootstrap-devise-cancan repository forked from the Rails Examples and
|
||||
Tutorials project.</p>
|
||||
|
||||
<p>We can try to access the repository via our server by doing the following:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'># List SSH keys that are loaded into the agent
|
||||
me@localhost $ ssh-add -l
|
||||
# Make sure they key is loaded if 'ssh-add -l' didn't show anything
|
||||
me@localhost $ ssh-add
|
||||
me@localhost $ ssh -A deploy@one-of-my-servers.com 'git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git</code></pre>
|
||||
</div>
|
||||
|
||||
<p>We first check that the agent has the keys loaded, if not we simply load it,
|
||||
and enter the passphrase when prompted.</p>
|
||||
|
||||
<p>Finally we use <code>ls-remote</code> from Git to list the remote objects, this is the
|
||||
exact same check that Capistrano does internally before attempting to deploy.
|
||||
The <code>-A</code> option may, or may not be required on your system, it's worth trying
|
||||
it both ways just to know how your system treats agent forwarding by default.</p>
|
||||
|
||||
<p>From the SSH documentation:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>-A Enables forwarding of the authentication agent connection. This can also be
|
||||
specified on a per-host basis in a configuration file.
|
||||
|
||||
Agent forwarding should be enabled with caution. Users with the ability to
|
||||
bypass file permissions on the remote host (for the agent's UNIX-domain
|
||||
socket) can access the local agent through the forwarded connection. An
|
||||
attacker cannot obtain key material from the agent, however they can perform
|
||||
operations on the keys that enable them to authenticate using the identities
|
||||
loaded into the agent.</code></pre>
|
||||
</div>
|
||||
|
||||
<p>In laymans terms, you should't use SSH agent forwarding to machines where you
|
||||
don't trust the administrators, as they can can override the permissions on
|
||||
the system and use your keys as if they were you. That said, if you can't
|
||||
trust your server administrators, perhaps they shouldn't have access to your
|
||||
servers!</p>
|
||||
|
||||
<h5 id="toc_4">1.2.2 HTTP Authentication</h5>
|
||||
|
||||
<p>In the case of HTTP authentication <strong>be sure to use HTTPS</strong>, otherwise your
|
||||
password will be sent in cleartext over the network, depending what your hosts
|
||||
network infratructure looks like that might be <em>very</em> bad news.</p>
|
||||
|
||||
<p>Typically when we try and list our remote objects, using the https method from
|
||||
Github, we'll be prompted for a username and password:</p>
|
||||
|
||||
<h5 id="toc_5">1.2.2.1 With a regular username/password</h5>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ git ls-remote https://github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
Username for 'https://github.com': myownusername
|
||||
Password for 'https://capistrano@github.com':</code></pre>
|
||||
</div>
|
||||
|
||||
<p>This challenge response prompt doesn't work well for automating things, so
|
||||
there are two ways to get around this depending on your server's host
|
||||
operating system, the first is to use a <code>netrc</code> file, we won't talk about that
|
||||
because the netrc is a global file that doesn't lend itself well to security.</p>
|
||||
|
||||
<p>The other mechanism, and the reason that its <strong>very</strong> important to always use
|
||||
HTTPS not plain ol' HTTP is to embed the username and password in the URL,
|
||||
note this won't work well if your password has special characters:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ git ls-remote https://capistrano:ourverysecretpassword@github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEAD
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEADrefs/heads/master</code></pre>
|
||||
</div>
|
||||
|
||||
<p>The bigger problem with passwords, whether inlined into the URL, or entered
|
||||
into a <code>netrc</code> file, is that the password gives access to <strong>your entire Github
|
||||
Account</strong> not just to one single repository.</p>
|
||||
|
||||
<h5 id="toc_6">1.2.2.2 With an OAuth Personal API Token</h5>
|
||||
|
||||
<p>This mechanism still gives access to <strong>every repository</strong> you can access, but
|
||||
at Github, they recently rolled out a feature called <a href="https://github.com/blog/1509-personal-api-tokens">Personal API
|
||||
Tokens</a> which allow you to
|
||||
do something like this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ git ls-remote https://.....................@github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEAD
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEADrefs/heads/master</code></pre>
|
||||
</div>
|
||||
|
||||
<p>Where <code>....</code> is a personal API token, as such:</p>
|
||||
|
||||
<p><img src="/images/github-personal-api-token-page.png" alt="Github Personal API Token Page"></p>
|
||||
|
||||
<h5 id="toc_7">1.2.3 Deploy Keys</h5>
|
||||
|
||||
<p>Deploy keys, a feature of Github, and some other platforms allow you to
|
||||
generate a <strong>second</strong> set of SSH keys for the connection between Github and
|
||||
the servers themselves.</p>
|
||||
|
||||
<p>Slightly perversely in this case the public key is uploaded to the repository
|
||||
host, and the private key must be copied to each server that you want to
|
||||
deploy to.</p>
|
||||
|
||||
<p>Github has a quite excellent guide on this, much of which (unsurprisingly)
|
||||
overlaps with the SSH key instructions above.</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="https://help.github.com/articles/managing-deploy-keys">Github Help: Managing Deploy Keys</a></li>
|
||||
</ul>
|
||||
|
||||
<h3 id="toc_8">Authorisation</h3>
|
||||
|
||||
<p>The second part of this topic is that our deploy user needs to be authorised
|
||||
to work in the deployment directory, on the server. That means we need to be
|
||||
able to work, ideally without <code>sudo</code> (none of the default Capistrano recipes
|
||||
expect <code>sudo</code> to be available), or for your custom recipes, you will need to
|
||||
have configured <em>passwordless</em> <code>sudo</code>. Configuring <code>sudo</code> to give some users
|
||||
access to come commands under some circumstances is beyond the scope of this
|
||||
documentation, but sufficed to say something like:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>deploy ALL=NOPASSWD:/etc/init.d/mysqld, /etc/init.d/apache2</code></pre>
|
||||
</div>
|
||||
|
||||
<p>This example would give the user named <code>deploy</code> access to call <code>sudo
|
||||
/etc/init.d/mysql _________</code> and the same for the <code>apache2</code> control script.</p>
|
||||
|
||||
<p><strong>Granting passwordless sudo should not be done lightly.</strong> It can be dangerous.
|
||||
For example if an unprivilidged user can <em>edit</em> the script that they can run
|
||||
as root, they can easily edit it to do anything they want that is evil. Use
|
||||
this carefully, and ideally architect your systems so that non-privlidged
|
||||
users can restart services, or that services restart <em>themselves</em> when they
|
||||
notice change.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--<div class="container"> -->
|
||||
<!-- <h1 class="title"><a href="/">Capistrano</a></h1>-->
|
||||
<!-- <a class="extra" href="/">home</a> -->
|
||||
<!-- </div> -->
|
||||
|
||||
<!-- <p><strong>Note:</strong> In the documentation we simply recommend creating a single deployment user,
|
||||
and sharing it between team members. If you know why this is a bad idea (or
|
||||
why this may be against regulations in your jurisdiction in some cases, we
|
||||
assume that you know well enough how to use groups, umasking and setgid bits
|
||||
to make this work reliably for unique logins across team members)</p>
|
||||
|
||||
<p>To create this deploy user we'll assume something like the following has been
|
||||
done:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>root@remote $ adduser deploy
|
||||
root@remote $ passwd -l deploy</code></pre>
|
||||
</div>
|
||||
|
||||
<p>The first line creates a completely standard user, it has a home directory,
|
||||
which we'll need in a moment, and has a shell, so it may log in. This needs to
|
||||
be done <strong>on every server in your environment</strong>.</p>
|
||||
|
||||
<p>The second line <em>locks</em> the user, it changes the user's password to an
|
||||
untypable string, guaranteeing that the user has no password which can be used
|
||||
to log in.</p>
|
||||
|
||||
<h3 id="toc_0">Authentication</h3>
|
||||
|
||||
<p>There are two places that we need automated, promptless authentication:</p>
|
||||
|
||||
<ol>
|
||||
<li><strong>From our workstation/notebook/etc to our servers.</strong> We do this with <strong>SSH
|
||||
keys</strong>, passphrase protected, ideally, using a <strong>key agent</strong>.</li>
|
||||
<li><strong>From our servers to the repository host</strong>. We do this so that our servers
|
||||
can check out our application code from Github, or similar and install it
|
||||
to the servers. This is usually done using <strong>SSH agent forwarding</strong>, HTTP
|
||||
authentication, or with deploy keys.</li>
|
||||
</ol>
|
||||
|
||||
<h4 id="toc_1">1.1 SSH keys from workstation to servers</h4>
|
||||
|
||||
<p><strong>Note:</strong> If you are on Windows, all bets are off, I'd love it if someone
|
||||
could contribute a Windows guide to this, so we can include it here.</p>
|
||||
|
||||
<p>An SSH key is a mechanism that allows a <em>public</em> half one key to be placed on
|
||||
a server, when we want to authenticate with that server, our SSH client uses
|
||||
the <strong>private</strong> part of that key to negotiate with the server, if the keys are
|
||||
correct, then we need to create the key.</p>
|
||||
|
||||
<p><strong>Hint:</strong> If you have more than one developer in your team, they should all add their
|
||||
public key to the <code>deploy</code> user's <code>authorized_keys</code> file, that way if someone
|
||||
quits or gets fired, you can remove their key from that file, and the rest of
|
||||
you can keep on shipping!</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh-keygen -t rsa -C 'me@my_email_address.com'</code></pre>
|
||||
</div>
|
||||
|
||||
<p>You'll be prompted for a passphrase, that's fine. Type one and keep it safe.
|
||||
This passphrase ensures that if your computer is stolen, people still need a
|
||||
passphrase to access your keys, in order to access your servers.</p>
|
||||
|
||||
<p>To avoid having to type this passphrase every time you need to use a key, most
|
||||
operating systems have a concept of a <em>key agent</em>. This <em>key agent</em> stores SSH
|
||||
keys securely between uses, typically the first time a key is needed in a
|
||||
given time period, the SSH agent will load the key, prompt you for your
|
||||
passphrase and then the key agent will remember the key for a certain amount
|
||||
of time (on OSX it tends to be indefinite, on linux this can vary from 15
|
||||
minutes updwards.)</p>
|
||||
|
||||
<p>We can see which keys are loaded in the SSH agent by running <code>ssh-add -l</code></p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh-add -l
|
||||
2048 af:ce:7e:c5:93:18:39:ff:54:20:7a:2d:ec:05:7c:a5 /Users/me/.ssh/id_rsa (RSA)</code></pre>
|
||||
</div>
|
||||
|
||||
<p>If you don't see any keys listed, you can simply run <code>ssh-add</code>:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhsot $ ssh-add
|
||||
Identity added: /Users/me/.ssh/id_rsa (/Users/me/.ssh/id_rsa)</code></pre>
|
||||
</div>
|
||||
|
||||
<p>Typically, ssh-add will ask you for the passphrase when you add a key.</p>
|
||||
|
||||
<p><strong>Note:</strong> Although it's not mandatory to use an SSH agent (one could simply
|
||||
use an unpassphrased key, and rely on SSH to find the key and exchange it).
|
||||
Using an SSH agent makes things more secure, because we can use a passphrased
|
||||
key without being prompts every time it is used. It <strong>also</strong> allows us to use
|
||||
this same key to access the repository <em>via</em> the server without creating an
|
||||
additional identity.</p>
|
||||
|
||||
<p>At this point with the key loaded into the agent, we need to put the
|
||||
<strong>public</strong> part of the key into a file on each remote server called
|
||||
<code>/home/users/deploy/.ssh/authorized_keys</code>, to get the contents of that file,
|
||||
we can ask our local key agent for the public parts of the keys it has loaded:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh-add -L
|
||||
ssh-rsa jccXJ/JRfGxnkh/8iL........dbfCH/9cDiKa0Dw8XGAo01mU/w== /Users/me/.ssh/id_rsa</code></pre>
|
||||
</div>
|
||||
|
||||
<p>This will be a lot longer when you run it, I snipped the output because it
|
||||
looked bad.</p>
|
||||
|
||||
<p>This line, as one line, needs to make it to the remote server and be added <em>to
|
||||
it's own line</em> of the <code>deploy</code> user's <code>~/.ssh/authorized_keys</code> file. This file
|
||||
then needs to be changed to permission mode <code>0600</code> (owner read/write, group
|
||||
none, other none), in the <code>~/.ssh</code> directory which needs the permissions
|
||||
<code>0700</code> (owner read/write/execute, group none, other none).</p>
|
||||
|
||||
<p>If you are on linux there often exists a command
|
||||
<a href="http://linux.die.net/man/1/ssh-copy-id"><code>ssh-copy-id</code></a> which streamlines this
|
||||
process, otherwise the worlflow is something like:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh root@remote
|
||||
root@remote $ su - deploy
|
||||
deploy@remote $ cd ~
|
||||
deploy@remote $ mkdir .ssh
|
||||
deploy@remote $ echo "ssh-rsa jccXJ/JRfGxnkh/8iL........dbfCH/9cDiKa0Dw8XGAo01mU/w== /Users/me/.ssh/id_rsa" >> .ssh/authorized_keys
|
||||
deploy@remote $ chmod 700 .ssh
|
||||
deploy@remote $ chmod 600 .ssh/authorized_keys</code></pre>
|
||||
</div>
|
||||
|
||||
<p><strong>Remember:</strong> This needs to be done on every server you want to use, you can
|
||||
use the same key for each one, but only one key per developer is recommended.
|
||||
<em>Private</em> keys are named as such for a reason!</p>
|
||||
|
||||
<p>If we did all that correctly, we should now be able to do something like this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ ssh deploy@one-of-my-servers.com 'hostname; uptime'
|
||||
one-of-my-servers.com
|
||||
19:23:32 up 62 days, 44 min, 1 user, load average: 0.00, 0.01, 0.05</code></pre>
|
||||
</div>
|
||||
|
||||
<p>That should happen without having to enter a passphrase for your SSH key, or
|
||||
promoting you for an SSH password (which the deploy user doesn't have anyway).</p>
|
||||
|
||||
<p>Verify that this works for all of your servers, and put your private key
|
||||
somewhere safe. If you're working with multiple team members, it often pays to
|
||||
collect everyone's public keys, indeed if your team is already using SSH keys
|
||||
to access Github, you can reach any user's SSH keys at the following URL:</p>
|
||||
|
||||
<ul>
|
||||
<li><code>https://github.com/theirusername.keys</code></li>
|
||||
</ul>
|
||||
|
||||
<p>This can make getting user's keys onto servers much easier, as you can simply
|
||||
<code>curl</code>/<code>wget</code> each user's key into the authorized keys file on the server
|
||||
directly from Github.</p>
|
||||
|
||||
<blockquote class="twitter-tweet"><p>TIL <a
|
||||
href="https://twitter.com/github">@github</a> exposes the ssh public keys for
|
||||
users. <a href="https://t.co/Wo9g8nxI">https://t.co/Wo9g8nxI</a> Handy for
|
||||
adding devs to servers/repos.</p>— Postmodern (@postmodern_mod3) <a
|
||||
href="https://twitter.com/postmodern_mod3/statuses/300438256200339456">February
|
||||
10, 2013</a></blockquote>
|
||||
|
||||
<script async src="//platform.twitter.com/widgets.js"
|
||||
charset="utf-8"></script>
|
||||
|
||||
<h4 id="toc_2">1.2 From our servers to the repository host</h4>
|
||||
|
||||
<p>With access from workstations to the servers settled, there is another hop to
|
||||
contend with, which is letting the deploy user get access to the code
|
||||
repository automatically. The options in order of preference:</p>
|
||||
|
||||
<h5 id="toc_3">1.2.1 SSH Agent Forwarding</h5>
|
||||
|
||||
<p>As we've already set up an SSH agent, we can use the <em>agent forwarding</em>
|
||||
feature of SSH to make this key agent available to further <em>hops</em>. In short,
|
||||
we can use <strong>our own ssh key</strong> to authenticate ourselves from the server, to
|
||||
Github.</p>
|
||||
|
||||
<p>Here's how we can check if that works, first get the URL of the repository:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ git config remote.origin.url
|
||||
git@github.com:capistrano/rails3-bootstrap-devise-cancan.git</code></pre>
|
||||
</div>
|
||||
|
||||
<p>Here we're listing our private (for testing purposes) fork of the
|
||||
rails3-bootstrap-devise-cancan repository forked from the Rails Examples and
|
||||
Tutorials project.</p>
|
||||
|
||||
<p>We can try to access the repository via our server by doing the following:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'># List SSH keys that are loaded into the agent
|
||||
me@localhost $ ssh-add -l
|
||||
# Make sure they key is loaded if 'ssh-add -l' didn't show anything
|
||||
me@localhost $ ssh-add
|
||||
me@localhost $ ssh -A deploy@one-of-my-servers.com 'git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git</code></pre>
|
||||
</div>
|
||||
|
||||
<p>We first check that the agent has the keys loaded, if not we simply load it,
|
||||
and enter the passphrase when prompted.</p>
|
||||
|
||||
<p>Finally we use <code>ls-remote</code> from Git to list the remote objects, this is the
|
||||
exact same check that Capistrano does internally before attempting to deploy.
|
||||
The <code>-A</code> option may, or may not be required on your system, it's worth trying
|
||||
it both ways just to know how your system treats agent forwarding by default.</p>
|
||||
|
||||
<p>From the SSH documentation:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>-A Enables forwarding of the authentication agent connection. This can also be
|
||||
specified on a per-host basis in a configuration file.
|
||||
|
||||
Agent forwarding should be enabled with caution. Users with the ability to
|
||||
bypass file permissions on the remote host (for the agent's UNIX-domain
|
||||
socket) can access the local agent through the forwarded connection. An
|
||||
attacker cannot obtain key material from the agent, however they can perform
|
||||
operations on the keys that enable them to authenticate using the identities
|
||||
loaded into the agent.</code></pre>
|
||||
</div>
|
||||
|
||||
<p>In laymans terms, you should't use SSH agent forwarding to machines where you
|
||||
don't trust the administrators, as they can can override the permissions on
|
||||
the system and use your keys as if they were you. That said, if you can't
|
||||
trust your server administrators, perhaps they shouldn't have access to your
|
||||
servers!</p>
|
||||
|
||||
<h5 id="toc_4">1.2.2 HTTP Authentication</h5>
|
||||
|
||||
<p>In the case of HTTP authentication <strong>be sure to use HTTPS</strong>, otherwise your
|
||||
password will be sent in cleartext over the network, depending what your hosts
|
||||
network infratructure looks like that might be <em>very</em> bad news.</p>
|
||||
|
||||
<p>Typically when we try and list our remote objects, using the https method from
|
||||
Github, we'll be prompted for a username and password:</p>
|
||||
|
||||
<h5 id="toc_5">1.2.2.1 With a regular username/password</h5>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ git ls-remote https://github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
Username for 'https://github.com': myownusername
|
||||
Password for 'https://capistrano@github.com':</code></pre>
|
||||
</div>
|
||||
|
||||
<p>This challenge response prompt doesn't work well for automating things, so
|
||||
there are two ways to get around this depending on your server's host
|
||||
operating system, the first is to use a <code>netrc</code> file, we won't talk about that
|
||||
because the netrc is a global file that doesn't lend itself well to security.</p>
|
||||
|
||||
<p>The other mechanism, and the reason that its <strong>very</strong> important to always use
|
||||
HTTPS not plain ol' HTTP is to embed the username and password in the URL,
|
||||
note this won't work well if your password has special characters:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ git ls-remote https://capistrano:ourverysecretpassword@github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEAD
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEADrefs/heads/master</code></pre>
|
||||
</div>
|
||||
|
||||
<p>The bigger problem with passwords, whether inlined into the URL, or entered
|
||||
into a <code>netrc</code> file, is that the password gives access to <strong>your entire Github
|
||||
Account</strong> not just to one single repository.</p>
|
||||
|
||||
<h5 id="toc_6">1.2.2.2 With an OAuth Personal API Token</h5>
|
||||
|
||||
<p>This mechanism still gives access to <strong>every repository</strong> you can access, but
|
||||
at Github, they recently rolled out a feature called <a href="https://github.com/blog/1509-personal-api-tokens">Personal API
|
||||
Tokens</a> which allow you to
|
||||
do something like this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>me@localhost $ git ls-remote https://.....................@github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEAD
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEADrefs/heads/master</code></pre>
|
||||
</div>
|
||||
|
||||
<p>Where <code>....</code> is a personal API token, as such:</p>
|
||||
|
||||
<p><img src="/images/github-personal-api-token-page.png" alt="Github Personal API Token Page"></p>
|
||||
|
||||
<h5 id="toc_7">1.2.3 Deploy Keys</h5>
|
||||
|
||||
<p>Deploy keys, a feature of Github, and some other platforms allow you to
|
||||
generate a <strong>second</strong> set of SSH keys for the connection between Github and
|
||||
the servers themselves.</p>
|
||||
|
||||
<p>Slightly perversely in this case the public key is uploaded to the repository
|
||||
host, and the private key must be copied to each server that you want to
|
||||
deploy to.</p>
|
||||
|
||||
<p>Github has a quite excellent guide on this, much of which (unsurprisingly)
|
||||
overlaps with the SSH key instructions above.</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="https://help.github.com/articles/managing-deploy-keys">Github Help: Managing Deploy Keys</a></li>
|
||||
</ul>
|
||||
|
||||
<h3 id="toc_8">Authorisation</h3>
|
||||
|
||||
<p>The second part of this topic is that our deploy user needs to be authorised
|
||||
to work in the deployment directory, on the server. That means we need to be
|
||||
able to work, ideally without <code>sudo</code> (none of the default Capistrano recipes
|
||||
expect <code>sudo</code> to be available), or for your custom recipes, you will need to
|
||||
have configured <em>passwordless</em> <code>sudo</code>. Configuring <code>sudo</code> to give some users
|
||||
access to come commands under some circumstances is beyond the scope of this
|
||||
documentation, but sufficed to say something like:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>deploy ALL=NOPASSWD:/etc/init.d/mysqld, /etc/init.d/apache2</code></pre>
|
||||
</div>
|
||||
|
||||
<p>This example would give the user named <code>deploy</code> access to call <code>sudo
|
||||
/etc/init.d/mysql _________</code> and the same for the <code>apache2</code> control script.</p>
|
||||
|
||||
<p><strong>Granting passwordless sudo should not be done lightly.</strong> It can be dangerous.
|
||||
For example if an unprivilidged user can <em>edit</em> the script that they can run
|
||||
as root, they can easily edit it to do anything they want that is evil. Use
|
||||
this carefully, and ideally architect your systems so that non-privlidged
|
||||
users can restart services, or that services restart <em>themselves</em> when they
|
||||
notice change.</p>
|
||||
-->
|
||||
|
||||
<!--</div> [> /container <] -->
|
||||
|
||||
<div class="row">
|
||||
<div class="large-4 columns">
|
||||
<ul>
|
||||
<li><a href="/about">About Capistrano</a></li>
|
||||
<li><a href="https://github.com/capistrano/capistrano/blob/master/CONTRIBUTING">Contributing</a></li>
|
||||
<li><a href="https://rubygems.org/gems/capistrano/versions">Releases</a></li>
|
||||
<li><a href="/upgrading">Upgrading</a></li>
|
||||
<li><a href="/security">Security</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="large-4 columns">
|
||||
<ul>
|
||||
<li><a href="http://stackoverflow.com/questions/tagged/capistrano">StackOverflow</a></li>
|
||||
<li><a href="https://groups.google.com/forum/#!forum/capistrano">Mailing List</a></li>
|
||||
<li><a href=".... ">Commercial Support</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="large-4 columns">
|
||||
<ul>
|
||||
<li><a href="//twitter.com/capistranorb"><i class="foundicon-twitter"></i></a></li>
|
||||
<li><a href="//github.com/capistrano"><i class="foundicon-github"></i></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="/js/prism.js"></script>
|
||||
<script src="/js/prism.ruby.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -16,6 +16,36 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var _gauges = _gauges || [];
|
||||
(function() {
|
||||
var t = document.createElement('script');
|
||||
t.type = 'text/javascript';
|
||||
t.async = true;
|
||||
t.id = 'gauges-tracker';
|
||||
t.setAttribute('data-site-id', '51c83c32613f5d7df70000bc');
|
||||
t.src = '//secure.gaug.es/track.js';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(t, s);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
setTimeout(function(){var a=document.createElement("script");
|
||||
var b=document.getElementsByTagName("script")[0];
|
||||
a.src=document.location.protocol+"//dnn506yrbagrg.cloudfront.net/pages/scripts/0017/6418.js?"+Math.floor(new Date().getTime()/3600000);
|
||||
a.async=true;a.type="text/javascript";b.parentNode.insertBefore(a,b)}, 1);
|
||||
</script>
|
||||
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-41970098-1', 'capistranorb.com');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
<div class="top-bar">
|
||||
<a href="/" class="brand">
|
||||
<img src="/images/CapistranoLogo.png" />
|
||||
|
@ -33,28 +63,28 @@
|
|||
<li><a href="/documentation/overview/introductory-demo-video/">Introductory Demo Video</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Getting Started</h5>
|
||||
<li><a href="/documentation/getting-started/installation/index.html">Installation</a></li>
|
||||
<li><a href="/documentation/getting-started/preparing-your-application/index.html">Preparing Your Application</a></li>
|
||||
<li><aj href="/documentation/getting-started/authentication-and-authorisation/index.html">Authentication & Authorisation</a></li>
|
||||
<li><a href="/documentation/getting-started/cold-start/index.html">Cold Start</a></li>
|
||||
<li><a href="/documentation/getting-started/rollbacks/index.html">Rollbacks</a></li>
|
||||
<li><a href="/documentation/getting-started/installation/">Installation</a></li>
|
||||
<li><a href="/documentation/getting-started/preparing-your-application/">Preparing Your Application</a></li>
|
||||
<li><a href="/documentation/getting-started/authentication-and-authorisation/">Authentication & Authorisation</a></li>
|
||||
<li><a href="/documentation/getting-started/cold-start/">Cold Start</a></li>
|
||||
<li><a href="/documentation/getting-started/rollbacks/">Rollbacks</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Troubleshooting</h5>
|
||||
<li><a href="/documentation/troubleshooting/authentication/index.html">SCM (Git) Authentication</a></li>
|
||||
<li><a href="/documentation/troubleshooting/connectivity/index.html">Connectivity</a></li>
|
||||
<!--<li><a href="/documentation/troubleshooting/gateway-servers/index.html">Gateway Servers</a></li>-->
|
||||
<li><a href="/documentation/troubleshooting/agent-forwarding/index.html">Agent Forwarding</a></li>
|
||||
<li><a href="/documentation/troubleshooting/sudo-password/index.html">`sudo` Password</a></li>
|
||||
<li><a href="/documentation/troubleshooting/rvm-rbenv-nvm/index.html">RVM, `rbenv` And `nvm`</a></li>
|
||||
<li><a href="/documentation/troubleshooting/authentication/">SCM (Git) Authentication</a></li>
|
||||
<li><a href="/documentation/troubleshooting/connectivity/">Connectivity</a></li>
|
||||
<!--<li><a href="/documentation/troubleshooting/gateway-servers/">Gateway Servers</a></li>-->
|
||||
<li><a href="/documentation/troubleshooting/agent-forwarding/">Agent Forwarding</a></li>
|
||||
<li><a href="/documentation/troubleshooting/sudo-password/">`sudo` Password</a></li>
|
||||
<li><a href="/documentation/troubleshooting/rvm-rbenv-nvm/">RVM, `rbenv` And `nvm`</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>FAQ</h5>
|
||||
<li><a
|
||||
href="/documentation/faq/why-does-something-work-in-my-ssh-session-but-not-in-capistrano/index.html">Why Does Something Work In An SSH Session, But Not In Capistrano?</a></li>
|
||||
<li><a href="/documentation/faq/should-i-use-capistrano-to-provision-my-servers/index.html">Should I Use Capistrano To Provision My Servers?</a></li>
|
||||
href="/documentation/faq/why-does-something-work-in-my-ssh-session-but-not-in-capistrano/">Why Does Something Work In An SSH Session, But Not In Capistrano?</a></li>
|
||||
<li><a href="/documentation/faq/should-i-use-capistrano-to-provision-my-servers/">Should I Use Capistrano To Provision My Servers?</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Power Use-Cases</h5>
|
||||
<li><a href="/documentation/power-use-cases/integration-with-rake/index.html">Integration With Rake</a></li>
|
||||
<li><a href="/documentation/power-use-cases/driving-tools-such-as-chef-solo/index.html">Driving Tools Such As <em>Chef Solo</em></a></li>
|
||||
<li><a href="/documentation/power-use-cases/integration-with-rake/">Integration With Rake</a></li>
|
||||
<li><a href="/documentation/power-use-cases/driving-tools-such-as-chef-solo/">Driving Tools Such As <em>Chef Solo</em></a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Recent Announcements</h5>
|
||||
|
||||
|
|
|
@ -16,6 +16,36 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var _gauges = _gauges || [];
|
||||
(function() {
|
||||
var t = document.createElement('script');
|
||||
t.type = 'text/javascript';
|
||||
t.async = true;
|
||||
t.id = 'gauges-tracker';
|
||||
t.setAttribute('data-site-id', '51c83c32613f5d7df70000bc');
|
||||
t.src = '//secure.gaug.es/track.js';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(t, s);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
setTimeout(function(){var a=document.createElement("script");
|
||||
var b=document.getElementsByTagName("script")[0];
|
||||
a.src=document.location.protocol+"//dnn506yrbagrg.cloudfront.net/pages/scripts/0017/6418.js?"+Math.floor(new Date().getTime()/3600000);
|
||||
a.async=true;a.type="text/javascript";b.parentNode.insertBefore(a,b)}, 1);
|
||||
</script>
|
||||
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-41970098-1', 'capistranorb.com');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
<div class="top-bar">
|
||||
<a href="/" class="brand">
|
||||
<img src="/images/CapistranoLogo.png" />
|
||||
|
@ -33,28 +63,28 @@
|
|||
<li><a href="/documentation/overview/introductory-demo-video/">Introductory Demo Video</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Getting Started</h5>
|
||||
<li><a href="/documentation/getting-started/installation/index.html">Installation</a></li>
|
||||
<li><a href="/documentation/getting-started/preparing-your-application/index.html">Preparing Your Application</a></li>
|
||||
<li><aj href="/documentation/getting-started/authentication-and-authorisation/index.html">Authentication & Authorisation</a></li>
|
||||
<li><a href="/documentation/getting-started/cold-start/index.html">Cold Start</a></li>
|
||||
<li><a href="/documentation/getting-started/rollbacks/index.html">Rollbacks</a></li>
|
||||
<li><a href="/documentation/getting-started/installation/">Installation</a></li>
|
||||
<li><a href="/documentation/getting-started/preparing-your-application/">Preparing Your Application</a></li>
|
||||
<li><a href="/documentation/getting-started/authentication-and-authorisation/">Authentication & Authorisation</a></li>
|
||||
<li><a href="/documentation/getting-started/cold-start/">Cold Start</a></li>
|
||||
<li><a href="/documentation/getting-started/rollbacks/">Rollbacks</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Troubleshooting</h5>
|
||||
<li><a href="/documentation/troubleshooting/authentication/index.html">SCM (Git) Authentication</a></li>
|
||||
<li><a href="/documentation/troubleshooting/connectivity/index.html">Connectivity</a></li>
|
||||
<!--<li><a href="/documentation/troubleshooting/gateway-servers/index.html">Gateway Servers</a></li>-->
|
||||
<li><a href="/documentation/troubleshooting/agent-forwarding/index.html">Agent Forwarding</a></li>
|
||||
<li><a href="/documentation/troubleshooting/sudo-password/index.html">`sudo` Password</a></li>
|
||||
<li><a href="/documentation/troubleshooting/rvm-rbenv-nvm/index.html">RVM, `rbenv` And `nvm`</a></li>
|
||||
<li><a href="/documentation/troubleshooting/authentication/">SCM (Git) Authentication</a></li>
|
||||
<li><a href="/documentation/troubleshooting/connectivity/">Connectivity</a></li>
|
||||
<!--<li><a href="/documentation/troubleshooting/gateway-servers/">Gateway Servers</a></li>-->
|
||||
<li><a href="/documentation/troubleshooting/agent-forwarding/">Agent Forwarding</a></li>
|
||||
<li><a href="/documentation/troubleshooting/sudo-password/">`sudo` Password</a></li>
|
||||
<li><a href="/documentation/troubleshooting/rvm-rbenv-nvm/">RVM, `rbenv` And `nvm`</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>FAQ</h5>
|
||||
<li><a
|
||||
href="/documentation/faq/why-does-something-work-in-my-ssh-session-but-not-in-capistrano/index.html">Why Does Something Work In An SSH Session, But Not In Capistrano?</a></li>
|
||||
<li><a href="/documentation/faq/should-i-use-capistrano-to-provision-my-servers/index.html">Should I Use Capistrano To Provision My Servers?</a></li>
|
||||
href="/documentation/faq/why-does-something-work-in-my-ssh-session-but-not-in-capistrano/">Why Does Something Work In An SSH Session, But Not In Capistrano?</a></li>
|
||||
<li><a href="/documentation/faq/should-i-use-capistrano-to-provision-my-servers/">Should I Use Capistrano To Provision My Servers?</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Power Use-Cases</h5>
|
||||
<li><a href="/documentation/power-use-cases/integration-with-rake/index.html">Integration With Rake</a></li>
|
||||
<li><a href="/documentation/power-use-cases/driving-tools-such-as-chef-solo/index.html">Driving Tools Such As <em>Chef Solo</em></a></li>
|
||||
<li><a href="/documentation/power-use-cases/integration-with-rake/">Integration With Rake</a></li>
|
||||
<li><a href="/documentation/power-use-cases/driving-tools-such-as-chef-solo/">Driving Tools Such As <em>Chef Solo</em></a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Recent Announcements</h5>
|
||||
|
||||
|
@ -71,7 +101,7 @@
|
|||
here have parallels in Python, or PHP applications
|
||||
</div>
|
||||
|
||||
<h2 id="toc_0">1. Commit your application to some externally available source control hosting provider.</h2>
|
||||
<h3 id="toc_0">1. Commit your application to some externally available source control hosting provider.</h3>
|
||||
|
||||
<p>If you are not doing already, you should host your code somewhere with a
|
||||
provuder such as Github, BitBucket, Codeplane, or repositoryhosting.com.</p>
|
||||
|
@ -83,7 +113,7 @@ contribute if you know these tools well, we don't and don't want to force our
|
|||
miscomprehended notions upon anyone.
|
||||
</div>
|
||||
|
||||
<h2 id="toc_1">2. Move secrets out of the repository.</h2>
|
||||
<h3 id="toc_1">2. Move secrets out of the repository.</h3>
|
||||
|
||||
<div class="alert-box alert">
|
||||
If you've accidentally committed state secrets to the repository, you might
|
||||
|
@ -109,7 +139,7 @@ $ echo config/database.yml >> .gitignore</code></pre>
|
|||
<p>This should be done for any other secret files, we'll create the production
|
||||
version of the file when we deploy, and symlink it into place.</p>
|
||||
|
||||
<h2 id="toc_2">3. Initialize Capistrano in your application.</h2>
|
||||
<h3 id="toc_2">3. Initialize Capistrano in your application.</h3>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>$ cd my-project
|
||||
|
@ -130,6 +160,125 @@ $ cap install</code></pre>
|
|||
└── tasks</code></pre>
|
||||
</div>
|
||||
|
||||
<h3 id="toc_3">4. Configure your server addresses in the generated files.</h3>
|
||||
|
||||
<p>We'll just work with the staging environment here, so you can pretend that
|
||||
<code>config/deploy/production.rb</code> doesn't exist, for the most part that's yoru
|
||||
business.</p>
|
||||
|
||||
<p>Capistrano breaks down common tasks into a notion of <em>roles</em>, that is, taking
|
||||
a typical Rails application that we have roughly speaking three roles, <code>web</code>,
|
||||
<code>app</code>, and <code>db</code>.</p>
|
||||
|
||||
<p>It can be confusing, as the boundary of web and app servers is a bit blurry if
|
||||
using <a href="">Passenger</a> with Apache, which in effect embeds your app server in the
|
||||
web server (embeds Passenger in the Apache process itself), confusingly
|
||||
Passenger can also be used in modes where this isn't true, so we'll ignore
|
||||
that for the time being, and if you know the difference (i.e you are using
|
||||
nginx as your web server, and puma/unicorn, or similar for your app server,
|
||||
that should be fine) we can assume that they're the same, which is pretty
|
||||
common.</p>
|
||||
|
||||
<p>The example file generated will look something like this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>set :stage, :staging
|
||||
|
||||
# Simple Role Syntax
|
||||
# ==================
|
||||
# Supports bulk-adding hosts to roles, the primary
|
||||
# server in each group is considered to be the first
|
||||
# unless any hosts have the primary property set.
|
||||
role :app, %w{example.com}
|
||||
role :web, %w{example.com}
|
||||
role :db, %w{example.com}
|
||||
|
||||
# Extended Server Syntax
|
||||
# ======================
|
||||
# This can be used to drop a more detailed server
|
||||
# definition into the server list. The second argument
|
||||
# something that quacks like a has can be used to set
|
||||
# extended properties on the server.
|
||||
server 'example.com', roles: %w{web app}, my_property: :my_value
|
||||
|
||||
# set :rails_env, :staging</code></pre>
|
||||
</div>
|
||||
|
||||
<p>Both the simple role, and extended server syntaxes result in one or more
|
||||
servers for each role being defined. The <code>app</code> and <code>db</code> roles are just
|
||||
placeholders, if you are using the <code>capistrano/rails-*</code> addons (more on
|
||||
that later) then they have a meaning, but if you are deploying something
|
||||
simpler, feel free to delete them if they're meaningless to you.</p>
|
||||
|
||||
<p>The extended server syntax exists to allow the definition of arbitrary server
|
||||
properties; it's there incase people want to build the server list more
|
||||
comprehensively from something like the <em>EC2</em> command line tools, and want to
|
||||
use the extended properties for something that makes sense in their
|
||||
environment.</p>
|
||||
|
||||
<p>Servers can be defined in a bunch of ways, the following shows defining two
|
||||
servers, one where we set the username, and another where we set the port.
|
||||
These host strings are parsed and expanded out in to the equivilent of the
|
||||
server line after the comment:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>role :all, %w{hello@world.com example.com:1234}
|
||||
# ...is the same as doing...
|
||||
server 'world.com' roles: [:web], user: 'hello'
|
||||
server 'example.com', roles: [:web], port: 1234</code></pre>
|
||||
</div>
|
||||
|
||||
<h3 id="toc_4">5. Set the shared information in <code>deploy.rb</code>.</h3>
|
||||
|
||||
<p>The <code>deploy.rb</code> is a place where the configuration common to each environment
|
||||
can be specified, normally the <em>repository URL</em> and the <em>user as whom to
|
||||
deploy</em> are specified here.</p>
|
||||
|
||||
<p>The generated sample file starts with the following, and is followed by a few
|
||||
self-documenting, commented-out configuration options, feel free to play with
|
||||
them a little:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>set :application, 'my app name'
|
||||
set :repo, 'git@example.com:me/my_repo.git'
|
||||
ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }</code></pre>
|
||||
</div>
|
||||
|
||||
<p>Here we'd set the name of the application, ideally in a way that's safe for
|
||||
filenames on your target operating system.</p>
|
||||
|
||||
<p>Second we set the repository URL, this <em>MUST</em> be somewhere that the server we
|
||||
are deploying to can reach.</p>
|
||||
|
||||
<p>Here's how this might look in a typical example, note that we'll cover
|
||||
authentication in the next chapter, for now we'll assume this repository is
|
||||
open source, we'll take an example application from the <a href="http://railsapps.github.io/">Rails Examples and
|
||||
Tutorials</a> site; there we'll find maintained a
|
||||
handful of typical Rails apps with typical dependencies.</p>
|
||||
|
||||
<p>The Rails application they host, which uses Devise (for authentication) and
|
||||
Cancan (for authorization) along side Twitter Bootstrap for assets has been
|
||||
forked to the Capistrano repository, but you can find the (unchanged) original
|
||||
<a href="https://github.com/RailsApps/rails3-bootstrap-devise-cancan">here</a>.</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>set :application, 'rails3-bootstrap-devise-cancan-demo'
|
||||
set :repo, 'https://github.com/capistrano/rails3-bootstrap-devise-cancan'
|
||||
set :branch, 'master'</code></pre>
|
||||
</div>
|
||||
|
||||
<p>I've simplified the <code>:branch</code> varaible to simply be a <code>set</code> varaible, not a
|
||||
question prompt, as this repository only has a master branch.</p>
|
||||
|
||||
<h2 id="toc_5">Roundup</h2>
|
||||
|
||||
<p><strong>At this point Capistrano knows where to find our servers, and where to find
|
||||
our code.</strong></p>
|
||||
|
||||
<p>We've not covered how we authorise our servers to check out our code (there
|
||||
are three pretty good ways of doing that with Git), nor have we determined how
|
||||
to authorise Capistrano on our servers yet.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -144,7 +293,7 @@ $ cap install</code></pre>
|
|||
here have parallels in Python, or PHP applications
|
||||
</div>
|
||||
|
||||
<h2 id="toc_0">1. Commit your application to some externally available source control hosting provider.</h2>
|
||||
<h3 id="toc_0">1. Commit your application to some externally available source control hosting provider.</h3>
|
||||
|
||||
<p>If you are not doing already, you should host your code somewhere with a
|
||||
provuder such as Github, BitBucket, Codeplane, or repositoryhosting.com.</p>
|
||||
|
@ -156,7 +305,7 @@ contribute if you know these tools well, we don't and don't want to force our
|
|||
miscomprehended notions upon anyone.
|
||||
</div>
|
||||
|
||||
<h2 id="toc_1">2. Move secrets out of the repository.</h2>
|
||||
<h3 id="toc_1">2. Move secrets out of the repository.</h3>
|
||||
|
||||
<div class="alert-box alert">
|
||||
If you've accidentally committed state secrets to the repository, you might
|
||||
|
@ -182,7 +331,7 @@ $ echo config/database.yml >> .gitignore</code></pre>
|
|||
<p>This should be done for any other secret files, we'll create the production
|
||||
version of the file when we deploy, and symlink it into place.</p>
|
||||
|
||||
<h2 id="toc_2">3. Initialize Capistrano in your application.</h2>
|
||||
<h3 id="toc_2">3. Initialize Capistrano in your application.</h3>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-bash'>$ cd my-project
|
||||
|
@ -202,6 +351,125 @@ $ cap install</code></pre>
|
|||
└── capistrano
|
||||
└── tasks</code></pre>
|
||||
</div>
|
||||
|
||||
<h3 id="toc_3">4. Configure your server addresses in the generated files.</h3>
|
||||
|
||||
<p>We'll just work with the staging environment here, so you can pretend that
|
||||
<code>config/deploy/production.rb</code> doesn't exist, for the most part that's yoru
|
||||
business.</p>
|
||||
|
||||
<p>Capistrano breaks down common tasks into a notion of <em>roles</em>, that is, taking
|
||||
a typical Rails application that we have roughly speaking three roles, <code>web</code>,
|
||||
<code>app</code>, and <code>db</code>.</p>
|
||||
|
||||
<p>It can be confusing, as the boundary of web and app servers is a bit blurry if
|
||||
using <a href="">Passenger</a> with Apache, which in effect embeds your app server in the
|
||||
web server (embeds Passenger in the Apache process itself), confusingly
|
||||
Passenger can also be used in modes where this isn't true, so we'll ignore
|
||||
that for the time being, and if you know the difference (i.e you are using
|
||||
nginx as your web server, and puma/unicorn, or similar for your app server,
|
||||
that should be fine) we can assume that they're the same, which is pretty
|
||||
common.</p>
|
||||
|
||||
<p>The example file generated will look something like this:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>set :stage, :staging
|
||||
|
||||
# Simple Role Syntax
|
||||
# ==================
|
||||
# Supports bulk-adding hosts to roles, the primary
|
||||
# server in each group is considered to be the first
|
||||
# unless any hosts have the primary property set.
|
||||
role :app, %w{example.com}
|
||||
role :web, %w{example.com}
|
||||
role :db, %w{example.com}
|
||||
|
||||
# Extended Server Syntax
|
||||
# ======================
|
||||
# This can be used to drop a more detailed server
|
||||
# definition into the server list. The second argument
|
||||
# something that quacks like a has can be used to set
|
||||
# extended properties on the server.
|
||||
server 'example.com', roles: %w{web app}, my_property: :my_value
|
||||
|
||||
# set :rails_env, :staging</code></pre>
|
||||
</div>
|
||||
|
||||
<p>Both the simple role, and extended server syntaxes result in one or more
|
||||
servers for each role being defined. The <code>app</code> and <code>db</code> roles are just
|
||||
placeholders, if you are using the <code>capistrano/rails-*</code> addons (more on
|
||||
that later) then they have a meaning, but if you are deploying something
|
||||
simpler, feel free to delete them if they're meaningless to you.</p>
|
||||
|
||||
<p>The extended server syntax exists to allow the definition of arbitrary server
|
||||
properties; it's there incase people want to build the server list more
|
||||
comprehensively from something like the <em>EC2</em> command line tools, and want to
|
||||
use the extended properties for something that makes sense in their
|
||||
environment.</p>
|
||||
|
||||
<p>Servers can be defined in a bunch of ways, the following shows defining two
|
||||
servers, one where we set the username, and another where we set the port.
|
||||
These host strings are parsed and expanded out in to the equivilent of the
|
||||
server line after the comment:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>role :all, %w{hello@world.com example.com:1234}
|
||||
# ...is the same as doing...
|
||||
server 'world.com' roles: [:web], user: 'hello'
|
||||
server 'example.com', roles: [:web], port: 1234</code></pre>
|
||||
</div>
|
||||
|
||||
<h3 id="toc_4">5. Set the shared information in <code>deploy.rb</code>.</h3>
|
||||
|
||||
<p>The <code>deploy.rb</code> is a place where the configuration common to each environment
|
||||
can be specified, normally the <em>repository URL</em> and the <em>user as whom to
|
||||
deploy</em> are specified here.</p>
|
||||
|
||||
<p>The generated sample file starts with the following, and is followed by a few
|
||||
self-documenting, commented-out configuration options, feel free to play with
|
||||
them a little:</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>set :application, 'my app name'
|
||||
set :repo, 'git@example.com:me/my_repo.git'
|
||||
ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }</code></pre>
|
||||
</div>
|
||||
|
||||
<p>Here we'd set the name of the application, ideally in a way that's safe for
|
||||
filenames on your target operating system.</p>
|
||||
|
||||
<p>Second we set the repository URL, this <em>MUST</em> be somewhere that the server we
|
||||
are deploying to can reach.</p>
|
||||
|
||||
<p>Here's how this might look in a typical example, note that we'll cover
|
||||
authentication in the next chapter, for now we'll assume this repository is
|
||||
open source, we'll take an example application from the <a href="http://railsapps.github.io/">Rails Examples and
|
||||
Tutorials</a> site; there we'll find maintained a
|
||||
handful of typical Rails apps with typical dependencies.</p>
|
||||
|
||||
<p>The Rails application they host, which uses Devise (for authentication) and
|
||||
Cancan (for authorization) along side Twitter Bootstrap for assets has been
|
||||
forked to the Capistrano repository, but you can find the (unchanged) original
|
||||
<a href="https://github.com/RailsApps/rails3-bootstrap-devise-cancan">here</a>.</p>
|
||||
|
||||
<div>
|
||||
<pre data-line=''><code class='language-ruby'>set :application, 'rails3-bootstrap-devise-cancan-demo'
|
||||
set :repo, 'https://github.com/capistrano/rails3-bootstrap-devise-cancan'
|
||||
set :branch, 'master'</code></pre>
|
||||
</div>
|
||||
|
||||
<p>I've simplified the <code>:branch</code> varaible to simply be a <code>set</code> varaible, not a
|
||||
question prompt, as this repository only has a master branch.</p>
|
||||
|
||||
<h2 id="toc_5">Roundup</h2>
|
||||
|
||||
<p><strong>At this point Capistrano knows where to find our servers, and where to find
|
||||
our code.</strong></p>
|
||||
|
||||
<p>We've not covered how we authorise our servers to check out our code (there
|
||||
are three pretty good ways of doing that with Git), nor have we determined how
|
||||
to authorise Capistrano on our servers yet.</p>
|
||||
-->
|
||||
|
||||
<!--</div> [> /container <] -->
|
||||
|
|
|
@ -16,6 +16,36 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var _gauges = _gauges || [];
|
||||
(function() {
|
||||
var t = document.createElement('script');
|
||||
t.type = 'text/javascript';
|
||||
t.async = true;
|
||||
t.id = 'gauges-tracker';
|
||||
t.setAttribute('data-site-id', '51c83c32613f5d7df70000bc');
|
||||
t.src = '//secure.gaug.es/track.js';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(t, s);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
setTimeout(function(){var a=document.createElement("script");
|
||||
var b=document.getElementsByTagName("script")[0];
|
||||
a.src=document.location.protocol+"//dnn506yrbagrg.cloudfront.net/pages/scripts/0017/6418.js?"+Math.floor(new Date().getTime()/3600000);
|
||||
a.async=true;a.type="text/javascript";b.parentNode.insertBefore(a,b)}, 1);
|
||||
</script>
|
||||
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-41970098-1', 'capistranorb.com');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
<div class="top-bar">
|
||||
<a href="/" class="brand">
|
||||
<img src="/images/CapistranoLogo.png" />
|
||||
|
@ -33,28 +63,28 @@
|
|||
<li><a href="/documentation/overview/introductory-demo-video/">Introductory Demo Video</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Getting Started</h5>
|
||||
<li><a href="/documentation/getting-started/installation/index.html">Installation</a></li>
|
||||
<li><a href="/documentation/getting-started/preparing-your-application/index.html">Preparing Your Application</a></li>
|
||||
<li><aj href="/documentation/getting-started/authentication-and-authorisation/index.html">Authentication & Authorisation</a></li>
|
||||
<li><a href="/documentation/getting-started/cold-start/index.html">Cold Start</a></li>
|
||||
<li><a href="/documentation/getting-started/rollbacks/index.html">Rollbacks</a></li>
|
||||
<li><a href="/documentation/getting-started/installation/">Installation</a></li>
|
||||
<li><a href="/documentation/getting-started/preparing-your-application/">Preparing Your Application</a></li>
|
||||
<li><a href="/documentation/getting-started/authentication-and-authorisation/">Authentication & Authorisation</a></li>
|
||||
<li><a href="/documentation/getting-started/cold-start/">Cold Start</a></li>
|
||||
<li><a href="/documentation/getting-started/rollbacks/">Rollbacks</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Troubleshooting</h5>
|
||||
<li><a href="/documentation/troubleshooting/authentication/index.html">SCM (Git) Authentication</a></li>
|
||||
<li><a href="/documentation/troubleshooting/connectivity/index.html">Connectivity</a></li>
|
||||
<!--<li><a href="/documentation/troubleshooting/gateway-servers/index.html">Gateway Servers</a></li>-->
|
||||
<li><a href="/documentation/troubleshooting/agent-forwarding/index.html">Agent Forwarding</a></li>
|
||||
<li><a href="/documentation/troubleshooting/sudo-password/index.html">`sudo` Password</a></li>
|
||||
<li><a href="/documentation/troubleshooting/rvm-rbenv-nvm/index.html">RVM, `rbenv` And `nvm`</a></li>
|
||||
<li><a href="/documentation/troubleshooting/authentication/">SCM (Git) Authentication</a></li>
|
||||
<li><a href="/documentation/troubleshooting/connectivity/">Connectivity</a></li>
|
||||
<!--<li><a href="/documentation/troubleshooting/gateway-servers/">Gateway Servers</a></li>-->
|
||||
<li><a href="/documentation/troubleshooting/agent-forwarding/">Agent Forwarding</a></li>
|
||||
<li><a href="/documentation/troubleshooting/sudo-password/">`sudo` Password</a></li>
|
||||
<li><a href="/documentation/troubleshooting/rvm-rbenv-nvm/">RVM, `rbenv` And `nvm`</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>FAQ</h5>
|
||||
<li><a
|
||||
href="/documentation/faq/why-does-something-work-in-my-ssh-session-but-not-in-capistrano/index.html">Why Does Something Work In An SSH Session, But Not In Capistrano?</a></li>
|
||||
<li><a href="/documentation/faq/should-i-use-capistrano-to-provision-my-servers/index.html">Should I Use Capistrano To Provision My Servers?</a></li>
|
||||
href="/documentation/faq/why-does-something-work-in-my-ssh-session-but-not-in-capistrano/">Why Does Something Work In An SSH Session, But Not In Capistrano?</a></li>
|
||||
<li><a href="/documentation/faq/should-i-use-capistrano-to-provision-my-servers/">Should I Use Capistrano To Provision My Servers?</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Power Use-Cases</h5>
|
||||
<li><a href="/documentation/power-use-cases/integration-with-rake/index.html">Integration With Rake</a></li>
|
||||
<li><a href="/documentation/power-use-cases/driving-tools-such-as-chef-solo/index.html">Driving Tools Such As <em>Chef Solo</em></a></li>
|
||||
<li><a href="/documentation/power-use-cases/integration-with-rake/">Integration With Rake</a></li>
|
||||
<li><a href="/documentation/power-use-cases/driving-tools-such-as-chef-solo/">Driving Tools Such As <em>Chef Solo</em></a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Recent Announcements</h5>
|
||||
|
||||
|
@ -73,7 +103,7 @@ without much previous setup.</p>
|
|||
unprepared server, covering all aspects of Github access, as well as
|
||||
privisioning the server using <em>Chef Solo</em> and Capistrano with <em>Rake</em>.</p>
|
||||
|
||||
<h4 id="toc_0"> Show Notes</h4>
|
||||
<h4 id="toc_0">Show Notes</h4>
|
||||
|
||||
<p>The <em>Chef Solo</em> recipes can be reached at [this repository at
|
||||
Github][capistrano-chef-solo-example-recipes], they rely on a fairly new
|
||||
|
@ -112,7 +142,7 @@ without much previous setup.</p>
|
|||
unprepared server, covering all aspects of Github access, as well as
|
||||
privisioning the server using <em>Chef Solo</em> and Capistrano with <em>Rake</em>.</p>
|
||||
|
||||
<h4 id="toc_0"> Show Notes</h4>
|
||||
<h4 id="toc_0">Show Notes</h4>
|
||||
|
||||
<p>The <em>Chef Solo</em> recipes can be reached at [this repository at
|
||||
Github][capistrano-chef-solo-example-recipes], they rely on a fairly new
|
||||
|
|
BIN
_site/images/github-personal-api-token-page.png
Normal file
BIN
_site/images/github-personal-api-token-page.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
|
@ -16,6 +16,36 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var _gauges = _gauges || [];
|
||||
(function() {
|
||||
var t = document.createElement('script');
|
||||
t.type = 'text/javascript';
|
||||
t.async = true;
|
||||
t.id = 'gauges-tracker';
|
||||
t.setAttribute('data-site-id', '51c83c32613f5d7df70000bc');
|
||||
t.src = '//secure.gaug.es/track.js';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(t, s);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
setTimeout(function(){var a=document.createElement("script");
|
||||
var b=document.getElementsByTagName("script")[0];
|
||||
a.src=document.location.protocol+"//dnn506yrbagrg.cloudfront.net/pages/scripts/0017/6418.js?"+Math.floor(new Date().getTime()/3600000);
|
||||
a.async=true;a.type="text/javascript";b.parentNode.insertBefore(a,b)}, 1);
|
||||
</script>
|
||||
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-41970098-1', 'capistranorb.com');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
<div class="top-bar">
|
||||
<a href="/" class="brand">
|
||||
<img src="/images/CapistranoLogo.png" />
|
||||
|
@ -33,28 +63,28 @@
|
|||
<li><a href="/documentation/overview/introductory-demo-video/">Introductory Demo Video</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Getting Started</h5>
|
||||
<li><a href="/documentation/getting-started/installation/index.html">Installation</a></li>
|
||||
<li><a href="/documentation/getting-started/preparing-your-application/index.html">Preparing Your Application</a></li>
|
||||
<li><aj href="/documentation/getting-started/authentication-and-authorisation/index.html">Authentication & Authorisation</a></li>
|
||||
<li><a href="/documentation/getting-started/cold-start/index.html">Cold Start</a></li>
|
||||
<li><a href="/documentation/getting-started/rollbacks/index.html">Rollbacks</a></li>
|
||||
<li><a href="/documentation/getting-started/installation/">Installation</a></li>
|
||||
<li><a href="/documentation/getting-started/preparing-your-application/">Preparing Your Application</a></li>
|
||||
<li><a href="/documentation/getting-started/authentication-and-authorisation/">Authentication & Authorisation</a></li>
|
||||
<li><a href="/documentation/getting-started/cold-start/">Cold Start</a></li>
|
||||
<li><a href="/documentation/getting-started/rollbacks/">Rollbacks</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Troubleshooting</h5>
|
||||
<li><a href="/documentation/troubleshooting/authentication/index.html">SCM (Git) Authentication</a></li>
|
||||
<li><a href="/documentation/troubleshooting/connectivity/index.html">Connectivity</a></li>
|
||||
<!--<li><a href="/documentation/troubleshooting/gateway-servers/index.html">Gateway Servers</a></li>-->
|
||||
<li><a href="/documentation/troubleshooting/agent-forwarding/index.html">Agent Forwarding</a></li>
|
||||
<li><a href="/documentation/troubleshooting/sudo-password/index.html">`sudo` Password</a></li>
|
||||
<li><a href="/documentation/troubleshooting/rvm-rbenv-nvm/index.html">RVM, `rbenv` And `nvm`</a></li>
|
||||
<li><a href="/documentation/troubleshooting/authentication/">SCM (Git) Authentication</a></li>
|
||||
<li><a href="/documentation/troubleshooting/connectivity/">Connectivity</a></li>
|
||||
<!--<li><a href="/documentation/troubleshooting/gateway-servers/">Gateway Servers</a></li>-->
|
||||
<li><a href="/documentation/troubleshooting/agent-forwarding/">Agent Forwarding</a></li>
|
||||
<li><a href="/documentation/troubleshooting/sudo-password/">`sudo` Password</a></li>
|
||||
<li><a href="/documentation/troubleshooting/rvm-rbenv-nvm/">RVM, `rbenv` And `nvm`</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>FAQ</h5>
|
||||
<li><a
|
||||
href="/documentation/faq/why-does-something-work-in-my-ssh-session-but-not-in-capistrano/index.html">Why Does Something Work In An SSH Session, But Not In Capistrano?</a></li>
|
||||
<li><a href="/documentation/faq/should-i-use-capistrano-to-provision-my-servers/index.html">Should I Use Capistrano To Provision My Servers?</a></li>
|
||||
href="/documentation/faq/why-does-something-work-in-my-ssh-session-but-not-in-capistrano/">Why Does Something Work In An SSH Session, But Not In Capistrano?</a></li>
|
||||
<li><a href="/documentation/faq/should-i-use-capistrano-to-provision-my-servers/">Should I Use Capistrano To Provision My Servers?</a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Power Use-Cases</h5>
|
||||
<li><a href="/documentation/power-use-cases/integration-with-rake/index.html">Integration With Rake</a></li>
|
||||
<li><a href="/documentation/power-use-cases/driving-tools-such-as-chef-solo/index.html">Driving Tools Such As <em>Chef Solo</em></a></li>
|
||||
<li><a href="/documentation/power-use-cases/integration-with-rake/">Integration With Rake</a></li>
|
||||
<li><a href="/documentation/power-use-cases/driving-tools-such-as-chef-solo/">Driving Tools Such As <em>Chef Solo</em></a></li>
|
||||
<li class="divider"></li>
|
||||
<h5>Recent Announcements</h5>
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ body {
|
|||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: 400;
|
||||
font-family: 'Enriqueta', serif;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,314 @@
|
|||
---
|
||||
title: Authentication & Authorisation
|
||||
layout: default
|
||||
---
|
||||
|
||||
**Note:** In the documentation we simply recommend creating a single deployment user,
|
||||
and sharing it between team members. If you know why this is a bad idea (or
|
||||
why this may be against regulations in your jurisdiction in some cases, we
|
||||
assume that you know well enough how to use groups, umasking and setgid bits
|
||||
to make this work reliably for unique logins across team members)
|
||||
|
||||
To create this deploy user we'll assume something like the following has been
|
||||
done:
|
||||
|
||||
{% prism bash %}
|
||||
root@remote $ adduser deploy
|
||||
root@remote $ passwd -l deploy
|
||||
{% endprism %}
|
||||
|
||||
The first line creates a completely standard user, it has a home directory,
|
||||
which we'll need in a moment, and has a shell, so it may log in. This needs to
|
||||
be done **on every server in your environment**.
|
||||
|
||||
The second line *locks* the user, it changes the user's password to an
|
||||
untypable string, guaranteeing that the user has no password which can be used
|
||||
to log in.
|
||||
|
||||
### Authentication
|
||||
|
||||
There are two places that we need automated, promptless authentication:
|
||||
|
||||
1. **From our workstation/notebook/etc to our servers.** We do this with **SSH
|
||||
keys**, passphrase protected, ideally, using a **key agent**.
|
||||
2. **From our servers to the repository host**. We do this so that our servers
|
||||
can check out our application code from Github, or similar and install it
|
||||
to the servers. This is usually done using **SSH agent forwarding**, HTTP
|
||||
authentication, or with deploy keys.
|
||||
|
||||
#### 1.1 SSH keys from workstation to servers
|
||||
|
||||
**Note:** If you are on Windows, all bets are off, I'd love it if someone
|
||||
could contribute a Windows guide to this, so we can include it here.
|
||||
|
||||
An SSH key is a mechanism that allows a *public* half one key to be placed on
|
||||
a server, when we want to authenticate with that server, our SSH client uses
|
||||
the **private** part of that key to negotiate with the server, if the keys are
|
||||
correct, then we need to create the key.
|
||||
|
||||
**Hint:** If you have more than one developer in your team, they should all add their
|
||||
public key to the `deploy` user's `authorized_keys` file, that way if someone
|
||||
quits or gets fired, you can remove their key from that file, and the rest of
|
||||
you can keep on shipping!
|
||||
|
||||
{% prism bash %}
|
||||
me@localhost $ ssh-keygen -t rsa -C 'me@my_email_address.com'
|
||||
{% endprism %}
|
||||
|
||||
You'll be prompted for a passphrase, that's fine. Type one and keep it safe.
|
||||
This passphrase ensures that if your computer is stolen, people still need a
|
||||
passphrase to access your keys, in order to access your servers.
|
||||
|
||||
To avoid having to type this passphrase every time you need to use a key, most
|
||||
operating systems have a concept of a *key agent*. This *key agent* stores SSH
|
||||
keys securely between uses, typically the first time a key is needed in a
|
||||
given time period, the SSH agent will load the key, prompt you for your
|
||||
passphrase and then the key agent will remember the key for a certain amount
|
||||
of time (on OSX it tends to be indefinite, on linux this can vary from 15
|
||||
minutes updwards.)
|
||||
|
||||
We can see which keys are loaded in the SSH agent by running `ssh-add -l`
|
||||
|
||||
{% prism bash %}
|
||||
me@localhost $ ssh-add -l
|
||||
2048 af:ce:7e:c5:93:18:39:ff:54:20:7a:2d:ec:05:7c:a5 /Users/me/.ssh/id_rsa (RSA)
|
||||
{% endprism %}
|
||||
|
||||
If you don't see any keys listed, you can simply run `ssh-add`:
|
||||
|
||||
{% prism bash %}
|
||||
me@localhsot $ ssh-add
|
||||
Identity added: /Users/me/.ssh/id_rsa (/Users/me/.ssh/id_rsa)
|
||||
{% endprism %}
|
||||
|
||||
Typically, ssh-add will ask you for the passphrase when you add a key.
|
||||
|
||||
**Note:** Although it's not mandatory to use an SSH agent (one could simply
|
||||
use an unpassphrased key, and rely on SSH to find the key and exchange it).
|
||||
Using an SSH agent makes things more secure, because we can use a passphrased
|
||||
key without being prompts every time it is used. It **also** allows us to use
|
||||
this same key to access the repository *via* the server without creating an
|
||||
additional identity.
|
||||
|
||||
At this point with the key loaded into the agent, we need to put the
|
||||
**public** part of the key into a file on each remote server called
|
||||
`/home/users/deploy/.ssh/authorized_keys`, to get the contents of that file,
|
||||
we can ask our local key agent for the public parts of the keys it has loaded:
|
||||
|
||||
{% prism bash %}
|
||||
me@localhost $ ssh-add -L
|
||||
ssh-rsa jccXJ/JRfGxnkh/8iL........dbfCH/9cDiKa0Dw8XGAo01mU/w== /Users/me/.ssh/id_rsa
|
||||
{% endprism %}
|
||||
|
||||
This will be a lot longer when you run it, I snipped the output because it
|
||||
looked bad.
|
||||
|
||||
This line, as one line, needs to make it to the remote server and be added *to
|
||||
it's own line* of the `deploy` user's `~/.ssh/authorized_keys` file. This file
|
||||
then needs to be changed to permission mode `0600` (owner read/write, group
|
||||
none, other none), in the `~/.ssh` directory which needs the permissions
|
||||
`0700` (owner read/write/execute, group none, other none).
|
||||
|
||||
If you are on linux there often exists a command
|
||||
[`ssh-copy-id`](http://linux.die.net/man/1/ssh-copy-id) which streamlines this
|
||||
process, otherwise the worlflow is something like:
|
||||
|
||||
{% prism bash %}
|
||||
me@localhost $ ssh root@remote
|
||||
root@remote $ su - deploy
|
||||
deploy@remote $ cd ~
|
||||
deploy@remote $ mkdir .ssh
|
||||
deploy@remote $ echo "ssh-rsa jccXJ/JRfGxnkh/8iL........dbfCH/9cDiKa0Dw8XGAo01mU/w== /Users/me/.ssh/id_rsa" >> .ssh/authorized_keys
|
||||
deploy@remote $ chmod 700 .ssh
|
||||
deploy@remote $ chmod 600 .ssh/authorized_keys
|
||||
{% endprism %}
|
||||
|
||||
**Remember:** This needs to be done on every server you want to use, you can
|
||||
use the same key for each one, but only one key per developer is recommended.
|
||||
*Private* keys are named as such for a reason!
|
||||
|
||||
If we did all that correctly, we should now be able to do something like this:
|
||||
|
||||
{% prism bash %}
|
||||
me@localhost $ ssh deploy@one-of-my-servers.com 'hostname; uptime'
|
||||
one-of-my-servers.com
|
||||
19:23:32 up 62 days, 44 min, 1 user, load average: 0.00, 0.01, 0.05
|
||||
{% endprism %}
|
||||
|
||||
That should happen without having to enter a passphrase for your SSH key, or
|
||||
promoting you for an SSH password (which the deploy user doesn't have anyway).
|
||||
|
||||
Verify that this works for all of your servers, and put your private key
|
||||
somewhere safe. If you're working with multiple team members, it often pays to
|
||||
collect everyone's public keys, indeed if your team is already using SSH keys
|
||||
to access Github, you can reach any user's SSH keys at the following URL:
|
||||
|
||||
* `https://github.com/theirusername.keys`
|
||||
|
||||
This can make getting user's keys onto servers much easier, as you can simply
|
||||
`curl`/`wget` each user's key into the authorized keys file on the server
|
||||
directly from Github.
|
||||
|
||||
<blockquote class="twitter-tweet"><p>TIL <a
|
||||
href="https://twitter.com/github">@github</a> exposes the ssh public keys for
|
||||
users. <a href="https://t.co/Wo9g8nxI">https://t.co/Wo9g8nxI</a> Handy for
|
||||
adding devs to servers/repos.</p>— Postmodern (@postmodern_mod3) <a
|
||||
href="https://twitter.com/postmodern_mod3/statuses/300438256200339456">February
|
||||
10, 2013</a></blockquote>
|
||||
<script async src="//platform.twitter.com/widgets.js"
|
||||
charset="utf-8"></script>
|
||||
|
||||
#### 1.2 From our servers to the repository host
|
||||
|
||||
With access from workstations to the servers settled, there is another hop to
|
||||
contend with, which is letting the deploy user get access to the code
|
||||
repository automatically. The options in order of preference:
|
||||
|
||||
##### 1.2.1 SSH Agent Forwarding
|
||||
|
||||
As we've already set up an SSH agent, we can use the *agent forwarding*
|
||||
feature of SSH to make this key agent available to further *hops*. In short,
|
||||
we can use **our own ssh key** to authenticate ourselves from the server, to
|
||||
Github.
|
||||
|
||||
Here's how we can check if that works, first get the URL of the repository:
|
||||
|
||||
{% prism bash %}
|
||||
me@localhost $ git config remote.origin.url
|
||||
git@github.com:capistrano/rails3-bootstrap-devise-cancan.git
|
||||
{% endprism %}
|
||||
|
||||
Here we're listing our private (for testing purposes) fork of the
|
||||
rails3-bootstrap-devise-cancan repository forked from the Rails Examples and
|
||||
Tutorials project.
|
||||
|
||||
We can try to access the repository via our server by doing the following:
|
||||
|
||||
{% prism bash %}
|
||||
# List SSH keys that are loaded into the agent
|
||||
me@localhost $ ssh-add -l
|
||||
# Make sure they key is loaded if 'ssh-add -l' didn't show anything
|
||||
me@localhost $ ssh-add
|
||||
me@localhost $ ssh -A deploy@one-of-my-servers.com 'git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git
|
||||
{% endprism %}
|
||||
|
||||
We first check that the agent has the keys loaded, if not we simply load it,
|
||||
and enter the passphrase when prompted.
|
||||
|
||||
Finally we use `ls-remote` from Git to list the remote objects, this is the
|
||||
exact same check that Capistrano does internally before attempting to deploy.
|
||||
The `-A` option may, or may not be required on your system, it's worth trying
|
||||
it both ways just to know how your system treats agent forwarding by default.
|
||||
|
||||
From the SSH documentation:
|
||||
|
||||
{% prism bash %}
|
||||
-A Enables forwarding of the authentication agent connection. This can also be
|
||||
specified on a per-host basis in a configuration file.
|
||||
|
||||
Agent forwarding should be enabled with caution. Users with the ability to
|
||||
bypass file permissions on the remote host (for the agent's UNIX-domain
|
||||
socket) can access the local agent through the forwarded connection. An
|
||||
attacker cannot obtain key material from the agent, however they can perform
|
||||
operations on the keys that enable them to authenticate using the identities
|
||||
loaded into the agent.
|
||||
{% endprism %}
|
||||
|
||||
In laymans terms, you should't use SSH agent forwarding to machines where you
|
||||
don't trust the administrators, as they can can override the permissions on
|
||||
the system and use your keys as if they were you. That said, if you can't
|
||||
trust your server administrators, perhaps they shouldn't have access to your
|
||||
servers!
|
||||
|
||||
##### 1.2.2 HTTP Authentication
|
||||
|
||||
In the case of HTTP authentication **be sure to use HTTPS**, otherwise your
|
||||
password will be sent in cleartext over the network, depending what your hosts
|
||||
network infratructure looks like that might be *very* bad news.
|
||||
|
||||
Typically when we try and list our remote objects, using the https method from
|
||||
Github, we'll be prompted for a username and password:
|
||||
|
||||
##### 1.2.2.1 With a regular username/password
|
||||
|
||||
{% prism bash %}
|
||||
me@localhost $ git ls-remote https://github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
Username for 'https://github.com': myownusername
|
||||
Password for 'https://capistrano@github.com':
|
||||
{% endprism %}
|
||||
|
||||
This challenge response prompt doesn't work well for automating things, so
|
||||
there are two ways to get around this depending on your server's host
|
||||
operating system, the first is to use a `netrc` file, we won't talk about that
|
||||
because the netrc is a global file that doesn't lend itself well to security.
|
||||
|
||||
The other mechanism, and the reason that its **very** important to always use
|
||||
HTTPS not plain ol' HTTP is to embed the username and password in the URL,
|
||||
note this won't work well if your password has special characters:
|
||||
|
||||
{% prism bash %}
|
||||
me@localhost $ git ls-remote https://capistrano:ourverysecretpassword@github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEAD
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEADrefs/heads/master
|
||||
{% endprism %}
|
||||
|
||||
The bigger problem with passwords, whether inlined into the URL, or entered
|
||||
into a `netrc` file, is that the password gives access to **your entire Github
|
||||
Account** not just to one single repository.
|
||||
|
||||
##### 1.2.2.2 With an OAuth Personal API Token
|
||||
|
||||
This mechanism still gives access to **every repository** you can access, but
|
||||
at Github, they recently rolled out a feature called [Personal API
|
||||
Tokens](https://github.com/blog/1509-personal-api-tokens) which allow you to
|
||||
do something like this:
|
||||
|
||||
{% prism bash %}
|
||||
me@localhost $ git ls-remote https://.....................@github.com/capistrano/rails3-bootstrap-devise-cancan.git
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEAD
|
||||
3419812c9f146d9a84b44bcc2c3caef94da54758HEADrefs/heads/master
|
||||
{% endprism %}
|
||||
|
||||
Where `....` is a personal API token, as such:
|
||||
|
||||
![Github Personal API Token Page](/images/github-personal-api-token-page.png)
|
||||
|
||||
##### 1.2.3 Deploy Keys
|
||||
|
||||
Deploy keys, a feature of Github, and some other platforms allow you to
|
||||
generate a **second** set of SSH keys for the connection between Github and
|
||||
the servers themselves.
|
||||
|
||||
Slightly perversely in this case the public key is uploaded to the repository
|
||||
host, and the private key must be copied to each server that you want to
|
||||
deploy to.
|
||||
|
||||
Github has a quite excellent guide on this, much of which (unsurprisingly)
|
||||
overlaps with the SSH key instructions above.
|
||||
|
||||
* [Github Help: Managing Deploy Keys](https://help.github.com/articles/managing-deploy-keys)
|
||||
|
||||
### Authorisation
|
||||
|
||||
The second part of this topic is that our deploy user needs to be authorised
|
||||
to work in the deployment directory, on the server. That means we need to be
|
||||
able to work, ideally without `sudo` (none of the default Capistrano recipes
|
||||
expect `sudo` to be available), or for your custom recipes, you will need to
|
||||
have configured *passwordless* `sudo`. Configuring `sudo` to give some users
|
||||
access to come commands under some circumstances is beyond the scope of this
|
||||
documentation, but sufficed to say something like:
|
||||
|
||||
{% prism bash %}
|
||||
deploy ALL=NOPASSWD:/etc/init.d/mysqld, /etc/init.d/apache2
|
||||
{% endprism %}
|
||||
|
||||
This example would give the user named `deploy` access to call `sudo
|
||||
/etc/init.d/mysql _________` and the same for the `apache2` control script.
|
||||
|
||||
**Granting passwordless sudo should not be done lightly.** It can be dangerous.
|
||||
For example if an unprivilidged user can *edit* the script that they can run
|
||||
as root, they can easily edit it to do anything they want that is evil. Use
|
||||
this carefully, and ideally architect your systems so that non-privlidged
|
||||
users can restart services, or that services restart *themselves* when they
|
||||
notice change.
|
||||
|
|
@ -8,7 +8,7 @@ layout: default
|
|||
here have parallels in Python, or PHP applications
|
||||
</div>
|
||||
|
||||
## 1. Commit your application to some externally available source control hosting provider.
|
||||
### 1. Commit your application to some externally available source control hosting provider.
|
||||
|
||||
If you are not doing already, you should host your code somewhere with a
|
||||
provuder such as Github, BitBucket, Codeplane, or repositoryhosting.com.
|
||||
|
@ -20,7 +20,7 @@ contribute if you know these tools well, we don't and don't want to force our
|
|||
miscomprehended notions upon anyone.
|
||||
</div>
|
||||
|
||||
## 2. Move secrets out of the repository.
|
||||
### 2. Move secrets out of the repository.
|
||||
|
||||
<div class="alert-box alert">
|
||||
If you've accidentally committed state secrets to the repository, you might
|
||||
|
@ -46,7 +46,7 @@ parallel concept of ignored files)
|
|||
This should be done for any other secret files, we'll create the production
|
||||
version of the file when we deploy, and symlink it into place.
|
||||
|
||||
## 3. Initialize Capistrano in your application.
|
||||
### 3. Initialize Capistrano in your application.
|
||||
|
||||
{% prism bash %}
|
||||
$ cd my-project
|
||||
|
@ -66,3 +66,122 @@ This will create a bunch of files, the important ones are:
|
|||
└── capistrano
|
||||
└── tasks
|
||||
{% endprism %}
|
||||
|
||||
### 4. Configure your server addresses in the generated files.
|
||||
|
||||
We'll just work with the staging environment here, so you can pretend that
|
||||
`config/deploy/production.rb` doesn't exist, for the most part that's yoru
|
||||
business.
|
||||
|
||||
Capistrano breaks down common tasks into a notion of *roles*, that is, taking
|
||||
a typical Rails application that we have roughly speaking three roles, `web`,
|
||||
`app`, and `db`.
|
||||
|
||||
It can be confusing, as the boundary of web and app servers is a bit blurry if
|
||||
using [Passenger]() with Apache, which in effect embeds your app server in the
|
||||
web server (embeds Passenger in the Apache process itself), confusingly
|
||||
Passenger can also be used in modes where this isn't true, so we'll ignore
|
||||
that for the time being, and if you know the difference (i.e you are using
|
||||
nginx as your web server, and puma/unicorn, or similar for your app server,
|
||||
that should be fine) we can assume that they're the same, which is pretty
|
||||
common.
|
||||
|
||||
The example file generated will look something like this:
|
||||
|
||||
{% prism ruby %}
|
||||
set :stage, :staging
|
||||
|
||||
# Simple Role Syntax
|
||||
# ==================
|
||||
# Supports bulk-adding hosts to roles, the primary
|
||||
# server in each group is considered to be the first
|
||||
# unless any hosts have the primary property set.
|
||||
role :app, %w{example.com}
|
||||
role :web, %w{example.com}
|
||||
role :db, %w{example.com}
|
||||
|
||||
# Extended Server Syntax
|
||||
# ======================
|
||||
# This can be used to drop a more detailed server
|
||||
# definition into the server list. The second argument
|
||||
# something that quacks like a has can be used to set
|
||||
# extended properties on the server.
|
||||
server 'example.com', roles: %w{web app}, my_property: :my_value
|
||||
|
||||
# set :rails_env, :staging
|
||||
{% endprism %}
|
||||
|
||||
Both the simple role, and extended server syntaxes result in one or more
|
||||
servers for each role being defined. The `app` and `db` roles are just
|
||||
placeholders, if you are using the `capistrano/rails-*` addons (more on
|
||||
that later) then they have a meaning, but if you are deploying something
|
||||
simpler, feel free to delete them if they're meaningless to you.
|
||||
|
||||
The extended server syntax exists to allow the definition of arbitrary server
|
||||
properties; it's there incase people want to build the server list more
|
||||
comprehensively from something like the *EC2* command line tools, and want to
|
||||
use the extended properties for something that makes sense in their
|
||||
environment.
|
||||
|
||||
Servers can be defined in a bunch of ways, the following shows defining two
|
||||
servers, one where we set the username, and another where we set the port.
|
||||
These host strings are parsed and expanded out in to the equivilent of the
|
||||
server line after the comment:
|
||||
|
||||
{% prism ruby %}
|
||||
role :all, %w{hello@world.com example.com:1234}
|
||||
# ...is the same as doing...
|
||||
server 'world.com' roles: [:web], user: 'hello'
|
||||
server 'example.com', roles: [:web], port: 1234
|
||||
{% endprism %}
|
||||
|
||||
### 5. Set the shared information in `deploy.rb`.
|
||||
|
||||
The `deploy.rb` is a place where the configuration common to each environment
|
||||
can be specified, normally the *repository URL* and the *user as whom to
|
||||
deploy* are specified here.
|
||||
|
||||
The generated sample file starts with the following, and is followed by a few
|
||||
self-documenting, commented-out configuration options, feel free to play with
|
||||
them a little:
|
||||
|
||||
{% prism ruby %}
|
||||
set :application, 'my app name'
|
||||
set :repo, 'git@example.com:me/my_repo.git'
|
||||
ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }
|
||||
{% endprism %}
|
||||
|
||||
Here we'd set the name of the application, ideally in a way that's safe for
|
||||
filenames on your target operating system.
|
||||
|
||||
Second we set the repository URL, this *MUST* be somewhere that the server we
|
||||
are deploying to can reach.
|
||||
|
||||
Here's how this might look in a typical example, note that we'll cover
|
||||
authentication in the next chapter, for now we'll assume this repository is
|
||||
open source, we'll take an example application from the [Rails Examples and
|
||||
Tutorials](http://railsapps.github.io/) site; there we'll find maintained a
|
||||
handful of typical Rails apps with typical dependencies.
|
||||
|
||||
The Rails application they host, which uses Devise (for authentication) and
|
||||
Cancan (for authorization) along side Twitter Bootstrap for assets has been
|
||||
forked to the Capistrano repository, but you can find the (unchanged) original
|
||||
[here](https://github.com/RailsApps/rails3-bootstrap-devise-cancan).
|
||||
|
||||
{% prism ruby %}
|
||||
set :application, 'rails3-bootstrap-devise-cancan-demo'
|
||||
set :repo, 'https://github.com/capistrano/rails3-bootstrap-devise-cancan'
|
||||
set :branch, 'master'
|
||||
{% endprism %}
|
||||
|
||||
I've simplified the `:branch` varaible to simply be a `set` varaible, not a
|
||||
question prompt, as this repository only has a master branch.
|
||||
|
||||
## Roundup
|
||||
|
||||
**At this point Capistrano knows where to find our servers, and where to find
|
||||
our code.**
|
||||
|
||||
We've not covered how we authorise our servers to check out our code (there
|
||||
are three pretty good ways of doing that with Git), nor have we determined how
|
||||
to authorise Capistrano on our servers yet.
|
||||
|
|
|
@ -10,9 +10,7 @@ It covers using Capistrano to install an example Rails project on a previously
|
|||
unprepared server, covering all aspects of Github access, as well as
|
||||
privisioning the server using *Chef Solo* and Capistrano with *Rake*.
|
||||
|
||||
|
||||
|
||||
#### Show Notes
|
||||
#### Show Notes
|
||||
|
||||
The *Chef Solo* recipes can be reached at [this repository at
|
||||
Github][capistrano-chef-solo-example-recipes], they rely on a fairly new
|
||||
|
|
BIN
images/github-personal-api-token-page.png
Normal file
BIN
images/github-personal-api-token-page.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
Loading…
Reference in a new issue