Often times when building web applications, I used to spend time deploying my web applications via ssh
and scp
. Then I used Heroku for a few projects, and I really liked that deploying to heroku was as easy as it could be.
I wanted to have a similar deployment scheme on my own projects that aren’t deployed on Heroku.
How it works
Since git is a distributed version control system, you can push the code that lives on your machine to another machine very easily via ssh
. So your first instinct is to set up a repo in the location that your code needs to be deployed, and push to it via git. This is a good instinct, but git does not allow you to push code to a working copy. To resolve this, you will create a bare repository on your server, and push to it. You will also set up a git hook to automatically deploy your application when code gets pushed to the bare repository.
Setting it up
Before you start, your codebase needs to be in a git repository. This could be a Github repository that you use for version control. I will assume that your codebase lives in one directory called project
on your development machine, which I will refer to as develop
.
This codebase will be deployed to your server. I will refer to your server as deploy
.
Now, you are going to create a bare git repository on deploy
, and you will be able to push to it from develop
.
username@deploy:~$ mkdir repos # this is the dir where all your repos will be stored.
username@deploy:~$ cd repos
username@deploy:~/repos$ mkdir project.git
username@deploy:~/repos$ cd project.git # You can replace this with the name of your project.
username@deploy:~/repos/project.git$ git init --bare
# Initialized empty Git repository in /home/username/repos/project.git
You will now set up your codebase on develop
to push to the repos/project.git directory on deploy
.
username@develop:~$ cd /path/to/my/project
username@develop:~/code/project$ git status
# This must be a git repo.
username@develop:~/code/project$ git remote add deploy username@deploy:~/repos/project.git # This is the path to your bare repo.
username@develop:~/code/project$ git push deploy master
This will push your codebase, to the bare repository you just created on deploy
. You can verify this by cloning the bare repository if you’d like.
username@develop:~$ cd /tmp
username@develop:/tmp$ git clone username@deploy:~/repos/project.git
# Cloning into 'project'...
# remote: Counting objects: 666, done.
# remote: Compressing objects: 100% (417/417), done.
# remote: Total 666 (delta 255), reused 632 (delta 221)
# Receiving objects: 100% (666/666), 621.96 KiB | 462 KiB/s, done.
# Resolving deltas: 100% (255/255), done.
username@develop:/tmp$ cd project
username@develop:/tmp$ ls
# make sure your files are here.
Now that we are pushing to the repos/project.git directory on deploy
. Let’s set up our repository to actually deploy its code. I’ll assume that your application gets deployed to /var/www/myproject.com
.
username@deploy:~$ cd repos/project.git
username@deploy:~$ ls
# HEAD branches config description hooks info objects refs
username@deploy:~$ cd hooks
username@deploy:~$ [editor] post-receive
The post-receive hook gets called by git right after code gets pushed to a repository (right after git push deploy master). We will make this hook deploy your application to /var/www/myproject.com
. Using an editor of your choice, place the following in the post-receive file.
#!/bin/bash
### This file gets run when code is pushed to the project.git directory.
GIT_WORK_TREE=/var/www/myproject.com git checkout -f
Make the hook executable.
username@deploy:~/repos/project.git/hooks$ chmod +x post-receive
Make sure that your user has permissions to write to /var/www/myproject.com
. This is it! You can now deploy your code anytime you want by running:
username@develop:~/code/project$ git push deploy master
Verify that your code is deployed when you push, and you should never need to use scp
to deploy ever again.