Deploy a website to a remote server with Git push

Three steps to configure the deployment process:

  1. Create an empty Git repo on the server
  2. Write a Git Hook to deploy the code
  3. Deploy from the local computer

On the remote server

Add two files project-create.sh and project-delete.sh to /www directory

project-create.sh:

#!/bin/bash

# source: https://gist.github.com/francoisromain/58cabf43c2977e48ef0804848dee46c3
# and another script to delete the directories created by this script
# project-delete.sh: https://gist.github.com/francoisromain/e28069c18ebe8f3244f8e4bf2af6b2cb

# Call this file with `bash ./project-create.sh project-name [service-name]`
# - project-name is mandatory
# - service-name is optional

# This will creates 4 directories and a git `post-receive` hook.
# The 4 directories are:
# - $GIT: a git repo
# - $TMP: a temporary directory for deployment
# - $WWW: a directory for the actual production files
# - $ENV: a directory for the env variables

# When you push your code to the git repo,
# the `post-receive` hook will deploy the code
# in the $TMP directory, then copy it to $WWW.

DIR_TMP="/var/tmp/"
DIR_WWW="/var/www/"
DIR_GIT="/var/git/"
DIR_ENV="/var/env/"
DIR_HTML="/public_html"

if [ $# -eq 0 ]; then
	echo 'No project name provided (mandatory)'
	exit 1
else
	echo "- Project name:" "$1"
fi

if [ -z "$2" ]; then
	echo '- Service name (optional): not provided'
	GIT=$DIR_GIT$1.git
	TMP=$DIR_TMP$1
	WWW=$DIR_WWW$1$DIR_HTML
	ENV=$DIR_ENV$1
	
	# Create $WWW parent directory
	sudo mkdir -p "$DIR_WWW$1$DIR_HTML"
	cd "$DIR_WWW"
	sudo chown -R www-data:www-data "$1"
	sudo chmod -R g+rwX "$1"
else
	echo "- Service name (optional):" "$2"
	GIT=$DIR_GIT$1.$2.git
	TMP=$DIR_TMP$1.$2
	WWW=$DIR_WWW$1$DIR_HTML/$2
	ENV=$DIR_ENV$1/$2
fi

echo "- git:" "$GIT"
echo "- tmp:" "$TMP"
echo "- www:" "$WWW"
echo "- env:" "$ENV"

export GIT
export TMP
export WWW
export ENV

# Create a directory for the env repository
sudo mkdir -p "$ENV"
cd "$ENV" || exit
sudo touch .env

# Create a directory for the git repository
sudo mkdir -p "$GIT"
cd "$GIT" || exit

# Init the repo as an empty git repository
sudo git init --bare

# Define group recursively to "www-data", on the directories
sudo chgrp -R www-data .

# Define permissions recursively, on the sub-directories
# g = group, + add rights, r = read, w = write, X = directories only
# . = curent directory as a reference
sudo chmod -R g+rwX .

# Sets the setgid bit on all the directories
# https://www.gnu.org/software/coreutils/manual/html_node/Directory-Setuid-and-Setgid.html
sudo find . -type d -exec chmod g+s '{}' +

# Make the directory a shared repo
sudo git config core.sharedRepository group

cd hooks || exit

# create a post-receive file
sudo tee post-receive <<EOF
#!/bin/bash
# The production directory
WWW="${WWW}"
# A temporary directory for deployment
TMP="${TMP}"
# The Git repo
GIT="${GIT}"
# The Env  repo
ENV="${ENV}"
# Deploy the content to the temporary directory
mkdir -p \$TMP
git --work-tree=\$TMP --git-dir=\$GIT checkout -f
# Copy the env variable to the temporary directory
cp -a \$ENV/. \$TMP
# Do stuffs, like npm install
cd \$TMP || exit
# Replace the content of the production directory
# with the temporary directory
cd / || exit
rm -rf \$WWW
mv \$TMP \$WWW
# Do stuff like starting docker
cd \$WWW || exit
# docker-compose up -d --build
EOF

# make it executable
sudo chmod +x post-receive

Above is an edited copy made for my server.

Gist: https://gist.github.com/francoisromain/58cabf43c2977e48ef0804848dee46c3

project-delete.sh:

#!/bin/bash

# source: https://gist.github.com/francoisromain/e28069c18ebe8f3244f8e4bf2af6b2cb
# and another script to create the directories deleted by this script
# project-create.sh: https://gist.github.com/francoisromain/58cabf43c2977e48ef0804848dee46c3

# Call this file with `bash ./project-delete.sh project-name [service-name]`
# - project-name is mandatory
# - service-name is optional

# This will delete 4 directories
# - $GIT: a git repo
# - $TMP: a temporary directory for deployment
# - $WWW: a directory for the actual production files
# - $ENV: a directory for the env variables

DIR_TMP="/var/tmp/"
DIR_WWW="/var/www/"
DIR_GIT="/var/git/"
DIR_ENV="/var/env/"

function dir_delete() {
        sudo rm -rf "$1"
}

if [ $# -eq 0 ]; then
        echo 'No project name provided (mandatory)'
        exit 1
else
        echo "- Project name:" "$1"
fi

if [ -z "$2" ]; then
        echo '- Service name (optional): not provided'
        GIT=$DIR_GIT$1.git
        TMP=$DIR_TMP$1
        WWW=$DIR_WWW$1
        ENV=$DIR_ENV$1
else
        echo "- Service name (optional):" "$2"
        GIT=$DIR_GIT$1.$2.git
        TMP=$DIR_TMP$1.$2
        WWW=$DIR_WWW$1/$2
        ENV=$DIR_ENV$1/$2
fi

echo "- git:" "$GIT"
echo "- tmp:" "$TMP"
echo "- www:" "$WWW"
echo "- env:" "$ENV"

dir_delete "$GIT"
dir_delete "$ENV"
dir_delete "$WWW"
dir_delete "$TMP"

Gist: https://gist.github.com/francoisromain/e28069c18ebe8f3244f8e4bf2af6b2cb

Update both files to be unix encoded:

dos2unix /var/www/project-create.sh
dos2unix /var/www/project-delete.sh

Before executing the file, lets check a few things.

Check members of group www-data:

grep 'www-data' /etc/group

If user you’ll use on Git (the ssh key you need to load) is not part of group, then add like this:

usermod -a -G www-data christine

Create a new project on the server:

bash /var/www/project-create.sh <your-project>

Change the directory owner and group (having chris as the user breaks keeps christine user blocked out):

sudo chown www-data:www-data /var/www

On your local computer

In Bitbucket create a new repo as usual. Clone it to a new project folder under sites. Add a test file and commit it.

Open the Git terminal now and write this:

# Add your server as a Git remote called 'deploy'
git remote add deploy ssh://christine@35.192.41.230/var/git/<your-project>.git/

# Push your code and deploy
git push deploy master

Change remote url if things changed:

git remote set-url deploy ssh://chris@35.192.41.230/var/git/<your-project>.git/
git remote set-url deploy https://github.com/USERNAME/REPOSITORY.git

Add SSH key to Git

# Lists already added identities (‘ssh keys’)
ssh-add -l

#Run SSH Agent
eval `ssh-agent -s`

# Add a new identity (you'll see name of file when you showed the list)
ssh-add ~/.ssh/id_rsa
#Password is 57575757aA

Open id_rsa.pub under C:\Users\Christine.ssh. Check Google Compute under Metadata to see if this SSH key has been added already.

Note: Trying to load ppk files didn’t work.. I’d create new ones and I couldn’t get past the password when trying to add them to Git. Think Git will only accept id_rsa.

Getting error:

Okay now Git says its moved but I don’t see that on the server!!

Look into these:

https://help.github.com/en/articles/changing-a-remotes-url

https://github.com/facebookresearch/deepmask/issues/23

https://community.atlassian.com/t5/Bitbucket-questions/Permission-denied-publickey-fatal-Could-not-read-from-remote/qaq-p/448733

Leave a Reply

Your email address will not be published. Required fields are marked *