I'm running an Apache web server and was wondering what's the best way to deploy changes (from github) to the web server?
/var/www/ right now is only writable by root.
Should I have my git project directly in /var/www/? (so it creates /var/www/.git/?)
However, when I need to run commands (i.e. sudo git push) wouldn't work (since my ssh keys are not under sudo).
Would I be better off making /var/www/ writable by myself (and not just root)? Or should I add ssh keys to the root user? Or should I do something else entirely?
Thanks.
I use rsync to sync the contents of my local machine with the server, and if you're just deploying to one server, then it's pretty simple (and Capistrano is overkill.). I put the following aliases in ~/.bash_profile
:
alias eget='rsync -avie ssh matt@example.com:sites/example.com/www/ ~/Projects/example/example.com/www/ --exclude .DS_Store --exclude ".git*" --delete-after'
alias edep='rsync -avuie ssh ~/Projects/example/example.com/www/ matt@example.com:sites/example.com/www/ --exclude .DS_Store --exclude ".git*" --delay-updates --delete-after'
Then, from the git repo on my local machine. I do:
git commit -am 'commit some changes'
git pull --rebase # pull any new changes from remote (--rebase prevents an unnecessary merge commit.)
eget -n # confirm which files I've changed
If it looks fishy, I could do eget
without the -n and then just do a git diff -w
. Then, I could do git checkout -- path/to/file
for the files I want to keep my changes for. Then, I commit the changes that were on the server that I didn't get yet. This would only happen if the files on the server are changing in a different way than from deployments. Otherwise, you know that your local version is always more up to date than the files on the server and so don't have to worry about overwriting things on the server that you don't yet have on your local. Continue...
edep -n # just see what files will be deployed/updated/etc.
edep # looks good. Deploy for real.
Done!
Check out the rsync(1) Mac OS X Manual Page for more info.
Another option is to use the Git post-receive hook. But, you'll have to install Git on the server to do that. Also, I recommend putting the .git
directory outside of your public www
directory for security & cleanliness reasons. You can do this with the Git core.worktree
configuration option. For example, from ~/git/example.com.git
, do git init --bare; git config core.worktree ~/sites/example.com/
. That makes ~/git/example.com.git
like the .git
dir for ~/sites/example.com/
.
Create a central repository, use the branching of git to create different branches for different purposes, and never serve all of your repository publicly, nor should you ever serve your .git directory publicly (since that's the same as serving everything you ever did with the code or put in the repository to the public). Off the top of my head, here are the steps I recommend, from my own experience:
Create a central/hub repository for the code. (optional, but recommended. Even better is using github.com for your central repository). You can then check out local copies for local deployments, e.g. when you want to recreate the site on your laptop. Not necessary, but very convenient and makes sure your site is portable. You can have a staging repository and staging branch for development purposes. You can also have a repo and branch for production purposes.
Create a explicitly public directory in the repository that is not the root of the repository: E.g. Create a /www/ or /served/ or /public/ directory within the repository. This is stuff that will be publicly available and indexable by search engines, so be careful what goes in there. Assume that anything that goes in there is public knowledge, cached for eternity, and will be the target of security vulnerability attacks (because that could easily be the truth).
Create the dev repository: git clone the central repository on the server (e.g. cd /home/tchal
then git clone git@github.com:tchalvak/ninjawars.git
) , though ideally in a folder that has shared permissions for your developer group.
Create a symbolic link for you development site: cd /var/www/
, ln -s /url/to/shared/repository/public/ nickNameForDevSiteHere
, creating a symbolic link to only the served/public files of the site, creating a simple development level site. (optional, but recommended). In that manner, the dev site can easily be accessible via some ip and a nickname, e.g. http://10.0.1.123/publicdevelopmentsitenickname
without the need of a real domain name.
Specify the live & deployed code commit. You may well want to create a live-branch
for whatever code is currently "live", just be aware that this branch will probably have to be forcibly overwritten periodically, e.g. git branch live-branch
git push -f origin live-branch
. Consider it a snapshot of your code, and not a branch that will stay stable.
When you're sure that the dev site has been tested well enough, either deploy the live-branch
code manually, via a custom deploy script, or use a distinct repository with the live-branch checked out in it, serving only the explicitly public content, similar to the dev site.
create a virtualhost in apache for the domain name. For example, you could use something like:
<VirtualHost *>
ServerName greatdomain.com
ServerAlias www.greatdomain.com
DocumentRoot /srv/greatdomain/www/
</VirtualHost>
That's a huge topic, so if you're not clear on all of the details, I recommend getting into further research of setting up a virtualhost in apache.
Point your DNS for the domain name at the ip of the server.
In summary, you can pretty easily use git to deploy all of your code using specific-to-each-deployment-type branches. Won't help with syncing, for example, databases between deployments, but that is a step that you could figure out after you have things running, as a second tier of deploying a site, and do it manually in the meantime.