Using GIT to deploy website to simple webserver

in #technology7 years ago (edited)

With companies like Heroku, developers are having it easy to build, run, scale and operate applications on prepared servers. We are all getting pampered with those nice deployment processes. But lets take a step back and let us try to make an easy deployment-process for your simple webserver.

GIT deploy with post receive hook

At zauberware technologies there is no project, no snippet, no line of code without a GIT repository. We use Bitbucket (others might use GitHub) to share our code base across the company / community. You could also create your own GIT remote repository on your web server. The best: You can use this remote to directly deploy your website. This short tutorial describes how we set things up to make changes live by just running "git push production". Our main goal was to throw away the current deploy process with standard ftp clients.

Ok, what do we want?

A git push to a remote repository that has a detached work tree. This repo uses a post-receive hook that runs "git checkout -f" to copy the source code of the website into the correct folder. on your FTP server

GIT deploy with post receive hook

1. Setup local repository

If you have an existing projects you can go to step 2.

Let us suppose we are starting from scratch with a new website project:

$ mkdir my-website && cd my-website
$ git init
Initialized empty Git repository in /.../my-website/.git/
$ echo 'Hello World!' > index.html
$ git add index.html
$ git commit -m 'Initial commit'

2. The remote respository

To setup a remote repository on you web server you need SSH access and GIT should be installed. If you do not want to enter a password every time you push to the remote git you have to make sure that your public key is included in ~./ssh/authorized_keys and you are running ssh-agent locally.

(How to setup SSH key and upload to server)

Login into your server and let's set everything up:

$ ssh [email protected]
  1. create repository folder to store all future remote git repos
  2. create a website project folder -> this is where the deployed code goes
  3. setup post-receive hook
$ mkdir repositories && cd repositories
$ mkdir my-website.git && cd my-website.git 
$ git init --bare
Initialized empty Git repository in /.../my-website.git/

Great, we created a repository (bare repo) and we could start collaboration code through it. But our aim was to deploy changes to live server. For this we use a post-receive hook which checks out the latest tree from master into the websites folder on the server.

$ mkdir /websites 
$ mkdir /websites/my-website.de
$ cat > hook/post-receive
#!/bin/sh
GIT_WORK_TREE=/websites/my-website.de git checkout -f master
$ chmod +x hooks/post-receive 

We only checkout master to prevent changes on the server, when someone pushed other branches to this remote.

Note: This is not the only way how to configure your post-receive...

Git config

If the project is getting larger and larger you may need to update the git config file in the remote repo.

Example for 1and1 server:

[core]
    packedGitWindowSize = 640m
    packedGitLimit = 640m
    preloadindex = false

[pack]
    windowMemory = 640m
    threads = 1

3. Add remote on locale machine

Back on your local work station we go via console into your project folder. You may have a origin git remote which links to github or bitbucket. Now we want to add the git repo on your server as a remote. Let's call it production...

$ git add remote production ssh://[email protected]/repositories/my-website.git

Be sure that the path is correct. Depends on your webhoster. For a lot of time this worked:

$ git add remote production ssh://[email protected]/~/repositories/my-website.git

Try to push to master on the remote:

$ git push production +master:refs/heads/master

On the server, /websites/my-website.de should contain a copy of your files independent of any git meta data.

For future changes you can just make:

$ git push production

to push changes to the remote and the post-receive hook will immediately update the files in the project folder.

Notes

Others solved their problems with:

  • Make sure that the work tree (/websites/my-website.de) is writable by the user who runs the hook.
  • You may have to set the GIT_DIR environment variable in the post-receive hook (set to /repositories/my-website.git)
  • Make sure that the hook/post-receive file is executable by the user

Some CMS need different setting for local development and production. You can add other preparations in the post-receive hook. Or use other githooks (LINK TO GIT) to create your custom deploy process.

Configure post-receive hook for CMS which have different htaccess files for development and production environment

The only we thing we had problems with were the different htaccess files. We call them htaccess_prod in our code base and in the post-receive hook we move this file to the .htaccess location.

#!/bin/sh
#GITDIR=~/repositories/pmg.zauberware.com.git
WORK_TREE=~/websites/pmg.zauberware.com
GIT_WORK_TREE=~/websites/pmg.zauberware.com git checkout -f master

# special tasks (here for CraftCMS)
# rename htaccess for prod
cd $WORK_TREE
mv public/htaccess_prod public/.htaccess
mv public/en/htaccess_prod public/en/.htaccess

# be sure that craft storage folder exists
mkdir -p craft/storage/
chmod 705 craft/storage/

Thanks you all for reading ! If something is not working as expected, leave me a comment and we solve it together! If you need professional help you should have a look at our website and get in touch with our company! ;)