Automatic deploy using Git
The technique, mentioned in the title is just on of the many and there are plenty of ways achieving our target result…
For current article — let’s take some predefined setup, so that I can show you my own steps with screenshots, but the approach would be almost the same for other ways (I’ll mention them too, just without explanation).
— — — — — —
Setup
- Linux machine with project to deploy with shell access for your user
- Some server with already prepared branch for deployment (for example origin/master or production), the described below method is suitable for projects that are not compiled (PHP/Python..), but with some more Kung Fu can be adopted to compiled projects too: deploy bin folder with dependencies for .NET, for example.
And that’s it.
The brief idea is:
Install Git on target machine (sure your project must already use Git for source controlling), prepare SSH keys for passwordless exchange of information with your Git “server”, clone the project, run pull command using for example cron.
- Install Git.
On “Debian” family linux machines just run:
$ sudo apt-get update
$ sudo apt-get install git
2. Generate SSH keys and clone the project
Lets assume we want to clone the project into some project_dir, also for simplicity I’ll assume that your code is hosted on BitBucket (need this assumption just to show the operation with SSH keys), on other cloud services the process will be very similar.
By the way, why SSH? We sure can use HTTPS for secure transfer; lets compare both via simple sentences:
HTTPS:
- Is suitable if you push to and pull from server infrequently.
- Requires you to enter a password each time you connect.
SSH:
- Is more effective if you push and pull from server many times a day.
- Removes the need to enter a password each time you connect.
- But requires key generation and exchange
Also the URLs of the repository will be different, in case of bitbucket:
HTTPS https://<repo_owner>@bitbucket.org/<accountname>/<reponame>.git
SSH git@bitbucket.org:<repo_owner>/<reponame>.git
or
ssh://git@bitbucket.org/<repo_owner>/<reponame>.git
Let’s setup SSH keys using the command:
cd ~/.ssh
ssh-keygen -t rsa
What is does: go to .ssh hidden directory for your user and run ssh-keygen command with -t option (in this case rsa — RSA (R. Rivest, A. Shamir, L. Adleman), a cryptosystem for public-key encryption)
When prompted either accept the default key name (id_rsa
) or give your key a unique name. Press enter when asked for a passphrase, which will generate a passwordless key. Usually this isn’t recommended, but we need our script to be able to connect to Bitbucket without a passphrase. A public and private key pair will be generated. Example of terminal screen from BitBucket.org:
List the contents of ~/.ssh
to view the key files.
$ ls ~/.ssh
id_rsa id_rsa.pub
In our case of deployment we want to ONLY deploy to our server, so in this case go to your project’s BitBucket settings page and choose Access Keys, which will give the key readonly access to the code, suitable for our case.
Copy the contents of your public key to the Bitbucket Access Keys list (in my example: id_rsa.pub ‘s content) and save. This will allow the request, encrypted with your private key, to access your repository without password.
On your server, edit your ~/.ssh/config
file to add bitbucket.org as a host. This ensures that the correct key is used when connecting by SSH to bitbucket.org. You’ll need to create the config
file if it doesn’t exist:
Host bitbucket.org
IdentityFile ~/.ssh/id_rsa
Whenever you do a git pull
Bitbucket will verify your identity automatically, without prompting you for a password.
You can verify key exchange correctness by running:
$ ssh -T git@bitbucket.org
The command message tells you which of your Bitbucket accounts can log in with that key.
conq: logged in as emmap1.
You can use git or hg to connect to Bitbucket. Shell access is disabled.
In case your server users Apache as webserver you can use an .htaccess (with Deny For All line, for example) directive to hide the .git directory, but if that .htaccess file were accidentally deleted or edited you’d be left wide open.
Now we can clone our repo with git clone:
git clone git@bitbucket.org:
<accountname>/<reponame>
.git
For other OS you can use instruction from Bitbucket, for example.
3. Setup cron job to pull the changes
We will use crontab in this example.
Crontab (CRON TABle) is a file which contains the schedule of cron entries to be run and at specified times. Here is really nice quick reference on how to work with it, but in our case we need just:
crontab -e
That will create crontab file in case it was not already created for current user and open it in VI (exit with Esc, :q, Enter). Enter there your job description like (means: every 5 minutes go to project dir and call git pull from origin master branch from there):
*/5 * * * * cd <project_dir> && git pull -q origin master
After that: Esc, :wq, Enter and you will see:
crontab: installing new crontab
That’s it! You can face problems with permissions/git not in PATH or smth, but that is our of this article. This method is quite simple, but dumb: the server will ask repository server every “n” minutes for changes and do the pull. More clever way will be to set the pull request using WebHooks, but this is a theme for another article…