Information Security Stack Exchange is a question and answer site for information security professionals. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I tend to use Git for deploying production code to the web server. That usually means that somewhere a master Git repository is hosted somewhere accessible over ssh, and the production server serves that cloned repository, while restricting access to .git/ and .gitignore. When I need to update it, I simply pull to the server's repository from the master repository. This has several advantages:

  1. If anything ever goes wrong, it's extremely easy to rollback to an earlier revision - as simple as checking it out.
  2. If any of the source code files are modified, checking it as easy as git status, and if the server's repository has been modified, it will be come obvious the next time I try to pull.
  3. It means there exists one more copy of the source code, in case bad stuff happens.
  4. Updating and rolling back is easy and very fast.

This might have a few problems though:

  • If for whatever reason web server decides it should serve .git/ directory, all the source code there was and is becomes readable for everyone. Historically, there were some (large) companies who made that mistake. I'm using .htaccess file to restrict access, so I don't think there's any danger at the moment. Perhaps an integration test making sure nobody can read the .git/ folder is in order?

  • Everyone who accidentally gains read access to the folder also gains access to every past revision of the source code that used to exist. But it shouldn't be much worse than having access to the present version. After all, those revisions are obsolete by definition.

All that said, I believe that using Git for deploying code to production is reasonably safe, and a whole lot easier than rsync, ftp, or just copying it over. What do you think?

share|improve this question
Wouldn't standard practice have your git repository exist one level up from your htdoc folder so accidentally serving it out wouldn't happen? – Fiasco Labs Nov 14 '13 at 8:13
That's a good suggestion, and I'm doing just that for a latest personal project. But on another project my clients repository is organized differently (with htdoc being at the root of repository), so the question still applies. – Septagram Nov 14 '13 at 8:20
How do you ensure changes made after you deploy to test won't get deployed to production? – Graham Hill Nov 14 '13 at 10:05
So far I didn't have a chance to work in a team with dedicated testing server and QA (probably bad). I test thoroughly on the dev machine and only deploy new features in specific iterations. Then if there's a need for a bugfixes until the next iteration, they are done on a separate branch. E.g., version 0.6 is released, work started on 0.7. Bug is found on 0.6, fix applied in a branch 0.6 and merged into a master branch. Production then pulls branch 0.6. And until 0.7 is released, all fixes go first into branch 0.6. Sometimes (not always) I create a separate branch for production version ahead – Septagram Nov 14 '13 at 10:38
Is this really a security question? – tylerl Nov 15 '14 at 0:03
up vote 43 down vote accepted

I would go as far as considering using git for deployment very good practice.

The two problems you listed has very little to do with using git for deployment itself. Substitute .git/ for the config file containing database passwords and you have the same problem. If I have read access to your web root, I have read access to whatever is contained in it. This is a server hardening issue that you have to discuss with your system administration.

git offers some very attractive advantages when it comes to security.

  1. You can enforce a system for deploying to production. I would even configure a post-receive hook to automatically deploy to production whenever a commit to master is made. I am assuming of course, a workflow similar to git flow.

  2. git makes it extremely easy to rollback the code deployed on production to a previous version if a security issue is raised. This can be helpful in blocking access to mission-critical security flaws that you need time to fix properly.

  3. You can enforce a system where your developers have to sign the commits they make. This can help in tracing who deployed what to production if a deliberate security flaw is found.

share|improve this answer
Nice answer, I am really looking forward to using git in my production servers! However, I'm reluctant to use automatic push as you (and several others I read) suggested. Automatic push can change your production server when you don't want to, and you could accidentaly leave your server offline. Maybe I'm missing something and overcomplicating matters, but I prefer the paranoic approach of ssh'ing into the production server, do a git fetch origin master, then git diff master origin/master. Only then I would do git merge origin/master --ff-only. Do you have any thoughts about this matter? – pedromanoel Jun 11 '14 at 13:07
@pedromanoel I subscribe to the school of thought where anything you push to master should be production ready so that shouldn't really be a concern. What you are suggesting works as well. – Terry Chia Jun 17 '14 at 11:51
Our master branch commits deploy to the Dev Web server. We have a QA, Staging and Production branch that map to their respective environments. When we want to release to production we simply have to merge in the tested code into the production branch. This has worked well for us. We use KUDU for this. Not sure what other tools are available. – RayLoveless Jun 19 '15 at 20:44
@TerryChia Can you suggest any tutorials / tools for setting up your post-receive hooks for automatic deployments? We use Kudu but I've found it tricky to set up for non asure sites(We have our own IIS servers on prem). – RayLoveless Jun 19 '15 at 21:02

There's nothing wrong with deploying from a git repo, in fact it's a pretty common practice and as you say a lot less prone to errors than copying files over ftp or rsync.

Given the information you've provided I'd note the following points:

  • Don't just pull in the latest master. Production should be deployed from a release tag. Use git flow or similar to get a little more process around the deployment of the code and creation of the tags. Because tags are an immutable reference to your code at a given time it's more stable than pointing to a master branch that could be updated by an errant commit.

  • As for serving the .git directory this shouldn't be a big issue. Just redirect anything prefixed with .git to a 404 in .htaccess.

  • Your git authentication should be ssh key based so no repo passwords need to be stored on the server.

Hurray for git deployment workflows!

share|improve this answer

You can use the --separate-git-dir=<git dir> argument when calling git clone. This will place a symbolic link in the .git directory (symbolic to Git, I don't think it's a symbolic link to your OS), and you can specify the <git dir> to somewhere outside of the document root.

share|improve this answer

An alternative approach that I have taken before is something similar to Terry Chia's comment regarding post-receive hooks.

Git has a number of hooks that can be used to perform all sorts of tasks before/during/after multiple different actions.

Create a bare repository anywhere other than your web folder. The bare repository can then be used as a remote to push to, and a post-receive hook can be triggered to checkout the new code into a specified directory.

This approach has some advantages: The deployment location acts as a "one-way" street where code must go through source control to end up in production. You can deploy different branches/versions to different locations (all from the same bare repo). It also provides a nice easy way to rollback using standard git checkout. However, a caveat/consequence of this is that code changes on the server won't reflect in git (bare repositories don't have working directories) so you'd have to manually perform git --work-tree=/path/to/code status to see any changes (but you shouldn't be changing production code anyway, right?)

share|improve this answer
I don't think you need that introductory paragraph. It only tempts to flag your post for deletion. Better work on a good answer. – techraf Mar 29 at 15:08
As a reader when I see "meant to be a comment" type answers I normally discount it as not useful and skip reading it. You have some useful content in this post. I would build up on that. Wash, rinse, and repeat until you have enough reputation to leave comments. – baconface Mar 29 at 20:23
Thanks for the feedback! I removed the first sentence and expanded my answer. It ended up being too long for a comment anyway. – russdot Mar 30 at 0:33

Here is the script I use to make git to push to prod.

It assumes that anything pushed to the master branch is ready for production. All other pushed branches are ignored. You can modify this hook script to suit your needs.

As far as your concerns, I place my git directory under /var/git and my production files somewhere else (like /var/www) and restrict access to these directories.

You could also have your git repo on a separate server from your production server and then use something like scp and ssh in the script above to move your files from the git server to the production server. This would allow you to still use git to push to prod while keeping your code separate from your production.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.