Deploy a website to a remote server with Git push
Three steps to configure the deployment process with a Git Hook.
Git is a great tool for version control, but not only. It can also simplify the deployment process, thanks to Git Hooks.
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
tl;dr
On the remote server:
# Copy the 'project-create.sh' bash script https://gist.github.com/francoisromain/58cabf43c2977e48ef0804848dee46c3
# Then create a new project
# It configures a Git repo, and creates a Git hook$ bash ./path/to/project-create.sh <your-project>
On your local computer:
# Add your server as a Git remote called 'deploy'
git remote add deploy ssh://<your-name>@<your-ip>/srv/git/<your-project>.git/# Push your code and deploy
git push deploy master
Prerequisite
- Connect to the server via SSH withoutroot
.
- Git is installed globally on the server and locally.
User access and permissions
Connect to the server: $ ssh <your-name>@<your-ip>
Add your user to the users
group, so it has permissions to use Git: $ sudo adduser <your-name> users
.
On the server, we are going to use two directories:
/srv/tmp/
is a temporary directory for deployment./srv/www/
contains the actual production files (this could be/var/www/html/
on an Apache server).
Create the directories and set the permissions so your user can deploy without a root
access:
sudo mkdir -p /srv/tmp/
sudo mkdir -p /srv/www/sudo chgrp -R users /srv
sudo chmod -R g+w /srv
1. Create an empty Git repo on the server
First we need to configure an empty Git repo on the remote server to push the content of our local git repo.
Create an empty Git repo
sudo mkdir -p /srv/git/<your-app>.git
# Init the repo as an empty git repository
cd /srv/git/<your-app>.git
sudo git init --bare
Conventions:
- Add a
.git
extension on a git repo. - Store git repos in
srv/git/
.
Set the permissions on the Git repo
We need to set the permissions on the repo so that we can modify its content without sudo (from stackoverflow).
cd /srv/git/<your-app>.git
# Define group recursively to "users", on the directories
sudo chgrp -R users .# 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 Git shared repo
sudo git config core.sharedRepository group
2. Write a Git hook to deploy the code
When we push our code to the server, we want to trigger a command to deploy the code from the git repo. To do so, we use a Git post-receive hook.
Create the Git hook file
cd /srv/git/<your-app>.git/hooks
# create a post-receive file
sudo touch post-receive
# make it executable
sudo chmod +x post-receive
Edit the /srv/git/<your-app>.git/hooks/post-receive
file content:
#!/bin/sh# The production directory
TARGET="/srv/www/<your-app>"# A temporary directory for deployment
TEMP="/srv/tmp/<your-app>"# The Git repo
REPO="/srv/git/<your-app>.git"# Deploy the content to the temporary directory
mkdir -p $TEMP
git --work-tree=$TEMP --git-dir=$REPO checkout -fcd $TEMP
# Do stuffs, like npm install…# Replace the production directory
# with the temporary directory
cd /
rm -rf $TARGET
mv $TEMP $TARGET
Here is a bash script to automate the two steps above. Upload it somewhere on your server, then call
bash ./project-create.sh <your-project>
.
3. Deploy from the local computer
Initialize the repo and add the server repo as a remote
cd <your-app>
# Initialize git repo
git init
# Add the server repo as a remote called "deploy"
git remote add deploy ssh://<your-name>@<your-ip>/srv/git/<your-app>.git/
Push to the server (and deploy)
git add .
git commit -m "<commit message>"
git push deploy master
Next steps:
- Automate testing before deployment.
- Configure a load balancer to ensure no downtime.