36

I want to deploy with jenkins to the test environment and to the production environment. To do so I need to connect to the server of the wanted environment, something like ssh/scp.

I would like to know what the best way is.

I found some plugins to do this, like the Jenkins-Deploy-Plug-in or Jenkins Publish over SSH Plugin. The first has lots of issues, which is not really trustworthy to deploy to production and for the second you need to change the global configuration, which is manual work for every deploy.

Any ideas how to solve this? Maybe with some scripts or plugins?

The only current idea I have is: to connect with jenkins to a server (maybe with the SSH Plugin) and to execute there a script that connects to the wished environment. But that are two connections. Is that really neccessary? I hope for a more straightforward way for this.

thanks for any hint.

user1338413
  • 2,471
  • 8
  • 29
  • 36
  • A bit late here but, this is really what [ARA tools](https://en.wikipedia.org/wiki/Application_release_automation) are meant for. Integrate Jenkins with something like BuildMaster or XLDeploy and then have that tool do the deployment to production. – Karl Harnagy Feb 28 '17 at 19:41

3 Answers3

21

I suggest the following procedure:

one single shell script (stored somewhere on the jenkins server) does everything. Basically, the script does scp of the build artifact and then connects to the server (ssh) and does all the necessary tasks to deploy (setup maintenance page, backup the current app, deploy the new app, ...).

On the jenkins server, there are at least 2 jobs:

  • the first one simply does the build (using maven, or any other build script)
  • the second job does the deploy : so this job only runs the shell script. (I suggest one deploy job for each target environment : testing, production, ...)

It does not require any "special" jenkins plugin to achieve this "one click deployment". It only requires that the jenkins user has ssh access to the target server.

EDIT

Here is a sample shell script to illustrate my post

#This script will copy the last artifact build by the job "MyApp" to test.myserver.com
#and remotely execute the deployment script.

#copy the war to the server
#(the job "MyApp" is using maven, that's why the war can be found at this location)
scp -i <HOME_DIR>/.ssh/id_dsa $HUDSON_HOME/jobs/MyApp_Build/workspace/myapp/target/myapp.war     deployeruser@test.myserver.com:/tmp/

#connect to the server and execute the deployment script
ssh -i <HOME_DIR>/.ssh/id_dsa deployeruser@test.myserver.com 
#The following is just an example of what a deployment script can be.
#of course you must adapt it to your needs and environment
"cd <TOMCAT_DIR>;
#first copy the current war to a backup directory (additionaly, I have a cron task deleting old undeployed apps)
cp -rf myapp-apps/myapp* undeployed/myapp-apps/; 
#execute a script (stored on the server) to properly stop the app
sh bin/myapp.sh stop; 
#delete current app
rm -rf myapp-apps/myapp; 
rm -rf myapp-apps/myapp.war;
#copy the uploaded war in tomcat app directory 
cp /tmp/myapp.war myapp-apps/; 
#execute a script (stored on the server) to start the app
sh bin/myapp.sh start"
Miha
  • 303
  • 3
  • 19
ben75
  • 29,217
  • 10
  • 88
  • 134
  • 1. do you mean to store the script on the same server as jenkins? Didnt know that jenkins can store scripts as well. 2. I thought of one parametersized job, which deploys depanding on the parameter either to test-env or production. Is there a reason you suggest one job for each target environment? – user1338413 Dec 20 '12 at 16:57
  • One job per target because it's "one click to test" and "one click to prod". Using parametrized jobs may requires more click ? (don't know exactly what you mean by parametersized job) – ben75 Dec 20 '12 at 18:00
  • I put the script at /home/jenkins/deploy-script/deploy-myapp-test.sh and I simply call this script with a jenkins job. I don't use jenkins to store the script : I put it manually at this location. – ben75 Dec 20 '12 at 18:04
  • except the target server, the two jobs "deploy to test" and "deploy to prod" are identical (From my current point of view). So I thought it could be an option to use parameterized jobs to pass the target server-url as parameter. But this is new for me, didnt try that out yet, too. Thanks for your assistance. I hope i will manage to write a working script tomorrow, which is new for me as well. Maybe you like to share your "deploy-myapp-test.sh" script as an example. – user1338413 Dec 20 '12 at 22:06
  • thanks, always good to see an example. Even i have to adapt lot of things. like configure the server for the ssh connection as the server actually needs a password authentication, getting the .war from a repository and other details. – user1338413 Dec 21 '12 at 10:16
  • how do you set the permissions? I always get permission denied. As root I have the permissions and can execute the script, which works fine. But when jenkins calls the script it gets "permission denied" for everything, to create new directory, remove it and most critical for the key. I cant just set the permission for the private_key for everyone. Its currently 600. So how did you solve this? – user1338413 Jan 04 '13 at 11:02
  • The user running jenkins is not root (and that's good). On my configuration, the user running jenkins is also the owner of the private_key file. On the server side, you have to ensure that the user performing the remote login have enough privileges to play with your deployments directories. (maybe another question ?) – ben75 Jan 04 '13 at 11:21
  • http://stackoverflow.com/questions/14156078/what-permissions-should-jenkins-have-to-execute-shell-commands-without-being-ins – user1338413 Jan 04 '13 at 11:23
8

Using SSH compromises security on your environment
and is quite hard to troubleshoot.

It is better to install a Jenkins-Slave on the remote machine
and run the tests there by executing a Job on the Slave.

The Slave is monitored by the Server, which saves you a lot of trouble
managing the connection.

You can trigger the remote Job at the end of a successful build
and pass it the artifact of that build.
(can also have the first Job store the artifacts on a shared drive
and pass the location of those artifacts to the next Job).

See here:

Gonen
  • 4,005
  • 1
  • 31
  • 39
  • I want to deploy to production. If i understood you right, then i would need a Jenkins-Slave on my production-server? thats not a good idea. And as the test-server should be a copy of the production server, it makes no sense to deploy to it different and configure it different (like having on it a jenkins-slave) than the production-server. – user1338413 Dec 21 '12 at 15:55
  • 2
    Good point. On the other hand, having the ability to force a remote installation on your production-server is also "not-so-cool", unless you can tightly monitor those deployments (i.e.: happens only when you want, to the release you want, and gives good feedback on success or failure). – Gonen Dec 21 '12 at 16:15
  • I agree with Gonen so far. Some sort of client must exist on the prod server to allow a deployment. Just because SSH is usually built in does not make it more valid than a Jenkins slave. My concern is whether or not the Jenkins prod slave can be locked to just the prod deployment job. If another Jenkins job can come along and hijack it without proper permisssions, this could be a problem. I haven't gotten deep enough into Jenkins yet to know, but it doesn't look good given the security options I see at the moment. – juanitogan Aug 04 '14 at 22:15
  • @juanitogan, Jenkins can be locked-down to a level that only selected users could create/modify/delete/run jobs, and I consider the connection between the slave (agent) to the master to be safe, it terms that it is difficult to hijack a slave, and you can restrict its administration to selected users. Taking into account the good feedback you get from Jenkins for every operation that runs on it, it should be much easier (and thus: safer) to to control. – Gonen Aug 10 '14 at 09:24
  • 1
    @Gonen, Yes, but what's to keep a developer who can create/modify/delete/run jobs on development machines from temporarily borrowing the production slave to circumvent QA and throw something into production? If you have rights to one slave, you have rights to all slaves, as far as I can tell. – juanitogan Aug 27 '14 at 19:47
  • @juanitogan, should restrict the "copy-to-production" job to the relevant people (CM) and allow it (and only it) to run on the production-server. Assuming you control the creation of new jobs, this will prevent others from hijacking this server. – Gonen Aug 30 '14 at 22:29
3

Ideally, you should be using something like Fabric or Capistrano for deployments, and call those scripts from Jenkins. I've used Capistrano extensively for both Ruby On Rails and Non-Ruby applications too. The biggest advantage I see are:

  • The intelligence built in to rollback the deployment in case there are errors while deployments.
  • Hooks it provides to run a set of scripts such as DB migration, service restarts etc.
  • Manual rollback in case you need to.
Jonathan Eustace
  • 2,469
  • 12
  • 31
  • 54
leenasn
  • 1,466
  • 10
  • 16