What are the best practices here? What should operators that currently deploy this way do instead?
What are the best practices here? What should operators that currently deploy this way do instead?
This simplest solution is to add something like ' location ~ /\.git { deny all; }' to your nginx config (or just hide all paths starting with '.'; you rarely want to serve hidden files).
The most important practice for remediating this is to have a very clear disconnect between deployment artifacts and development repositories. You want to have your developers write code, and then some preprocessing step to distill that repository into the minimal deployment artifact. This artifact then goes through your integ tests on a gamma stage and onto prod. Whatever deployment system you use should know what git commit this artifact originated from, but the artifact should not have that information on its own.
If you want the really poor man's version of this, just have a build system in your repository which populates an "out" directory with everything you actually want to deploy, and then rsync that sucker around.
If you want a hip answer to this, Docker has the "Dockerfile" which will specify all artifacts that should be added into it, and should serve as a distillation of what's needed to run your application.
I'll point out that this issue won't affect many types of sites in the first place. For example, if you use any sane rails setup, you already have the "public" directory which you use as your static files root, and then you proxy to the unicorn/rack/whatever process which will never serve such files.
I would wager that the majority of these sites are poorly configured apache2 + php messes since php made the massive mistake of having the filesystem act as routing; any web framework with good routing (e.g. rails, django, even sinatra, web.py) will not suffer from this without going out of your way a bit.
Like this:
git --git-dir=/foo/bar.git --work-tree=/foo/bar.work init
git --git-dir=/foo/bar.git config receive.denyCurrentBranch ignore
Then create (and chmod +x): /foo/bar.git/hooks/post-update #!/bin/sh
work_tree=/foo/bar.work
GIT_WORK_TREE=$work_tree git checkout -f
Then you just create a symlink to the work tree for your website root, or put the work tree there, or whatever, depending on preference. Can't say this is perfect, but it works pretty well for smaller projects.It depends on what sort of platform and server you're running on but just do what you have to do so you're not serving your .git.
1. Configure your webserver to hide common directories and files.
2. Don't store passwords / credentials in version control. 2a. If you use a test suite, add a test to verify this.
3. Have a make step that builds the deployment content into a separate directory. (e.g. a gulp deploy task)
4. Rsync the deploy content to your destination server.
Instead of 4, more complex systems (with multiple servers, libraries, etc) use Docker to build an image from your deloy content.