Deploy with git push
- Introduction
- Configuration
- One-time server setup
- Authorized developers
- Create a new repository on the server
- Push-to-publish
Introduction
Wouldn’t it be nice to publish a website with a simple git push?
Here I’ll explain you how I usually do this.
I assume that the environment of the staging/production servers are the following:
- Operating system: Ubuntu 14.04 or Ubuntu 16.04
If your servers are not the above, the approach described in this document should work with minor changes given that they are *nix.
Configuration
Let’s assume that:
- the remote server is available at the address
- you want to create a new repository named
- the web server impersonates the user in the group
- you want to execute these commands after the push:
- -
One-time server setup
Install required packages
First of all, you need to install git on the server.
You can do this by running the following command:
sudo apt-get update
sudo apt-get install -y git
If the above command fails with an error like Unable to locate package git
, you can try this:
sudo apt-get install -y git-core
Create the git
user
We need to create a user account on the server. This account will be the one used by the publish process.
With the following command we create that account:
sudo adduser --gecos Git --disabled-login --disabled-password --shell /usr/bin/git-shell --home /home/git --ingroup git
Here’s the explanation of the above options:
--gecos Git
: set the full name of the account toGit
(this essentially in order to avoid asking useless data like the account room number and work/home phone)--disabled-login
: the user won’t be able to use the account until the password is set.--disabled-password
: disable the login using passwords (we’ll access the system with SSH RSA keys)--shell /usr/bin/git-shell
: when the user access the system, he will use the fake shell provided by git--home /home/git
: set the home directory for the user to/home/git
--ingroup
: add the new user to thegroup instead of the default one
git
: the username of the new account
Strengthen login security
We then need to configure the git shell.
In order to improve the security of unwanted logins and abort shell sessions, we create a file that is executed when the git
user logs in the shell and that will abort the session.
sudo mkdir /home/git/git-shell-commands
sudo nano /home/git/git-shell-commands/no-interactive-login
In the editor type in these commands:
#!/bin/sh
printf '%s\n' "Hi $USER! You've successfully authenticated, but I do not"
printf '%s\n' "provide interactive shell access."
exit 128
To save the new file hit CTRL
+o
then ENTER
.
To quit the editor, hit CTRL
+x
.
We finally have to make the file executable:
sudo chmod +x /home/git/git-shell-commands/no-interactive-login
Allow
impersonation
The git
user needs to be able to publish files acting like .
In order to allow this, run this command:
sudo visudo
Go to the end of the editor contents and add these lines:
Defaults!/usr/bin/git env_keep="GIT_DIR GIT_WORK_TREE"
git ALL=() NOPASSWD: /usr/bin/git
The first line tells the system that when the git
command is executed with a sudo
, we need to keep the two environment variables GIT_DIR
and GIT_WORK_TREE
.
The second line tells the system that the git
user can execute the git
command acting as without any further authentication.
Authorized developers
Every developer that should be able to publish needs an SSH-2 RSA key pair.
It’s possible (and recommended) to use a different key for every developer.
Create the keys under Windows
I order to create the key pair, you can use PuTTYgen.
If you already installed TortoiseGit you should already have this command, otherwise you can download it.
So, open PuTTYgen and:
- in the
Parameters
page be sure to checkSSH-2 RSA
and2048
for theNumber of bits in a generated key
- Hit the
Generate
button and move randomly your mouse over the PuTTYgen window - In the
Key comment
field enterServerName - DeveloperName
(whereServerName
is the name of the server where the key will be used, andDeveloperName
is the name of the developers owning the key) - In the
Key passphrase
andConfirm passphrase
fields enter a password of your choice - Hit the
Save private key
button to save the private key to file - Copy the contents of the
Public key for pasting into OpenSSH authorized_keys file
and save it: this is the public key that we’ll need.
Create the keys under *nix
Simply run this command:
ssh-keygen -t rsa -b 2048 -f key-for-git -C 'ServerName - DeveloperName'
Where:
-t rsa
: we want public/private key pair in the SSH-2 RSA format-b 2048
: we want 2048 bits in the key-f key-for-git
: this is the name of the file that will contain the private key-C 'ServerName - DeveloperName'
: this is the comment to associate to the key (it’s a good practice to specify the name of the server and the one the developer owning the key)
Once you run the ssh-keygen
command and specified a password of your choice, you’ll have these two files:
key-for-git
: contains the private keykey-for-git.pub
: contains the public key
Allow the developer to publish to the server
Login to the server and run this command:
sudo mkdir /home/git/.ssh
sudo nano /home/git/.ssh/authorized_keys
Go to the end of the editor contents and add a new line containing the previously generated public key.
The public key is a single line that starts with ssh-rsa
, followed by a quite long list of characters and ending with the ServerName - DeveloperName
comments specified during the creation of the key.
Create a new repository on the server
We’ll end up with:
- Directory to be published:
/var/www/
- Repository directory:
/var/git/
First of all, we create the directory that will contain web site (it will be owned by the user):
sudo mkdir -p /var/www/
sudo chown -R : /var/www/
sudo chmod u+rw -R /var/www/
Then we create the directory that will contain the bare repository data:
sudo mkdir -p /var/git/.git
cd /var/git/.git
sudo git init --bare
sudo git config core.sharedRepository group
The core.sharedRepository group
option of the git repository is needed in order to grant write access to both the git
and users (they both belong to the same user group -
).
And now the key concept of this whole approach: when someone pushes to this repository, we checkout the repository to the publish folder:
sudo nano /var/git/.git/hooks/post-receive
In the editor type these lines:
#!/bin/bash
currentUser=`whoami`
currentServer=`hostname`
repoDirectory=/var/git/.git
pubDirectory=/var/www/
echo "Hello! I'm $currentUser at $currentServer"
echo "I'm going to publish from"
echo " $repoDirectory"
echo "to"
echo " $pubDirectory"
rc=0
sudo -u git --git-dir=$repoDirectory --work-tree=$pubDirectory checkout master -f
if [ "$?" -ne "0" ]; then
echo "GOSH! GIT FAILED!!!!"
rc=1
fi
if [ $rc -eq 0 ]; then
echo "Don't worry, be happy: everything worked out like a charm ;)"
fi
exit $rc
We finally need to update the permissions of the newly created directory:
sudo chown -R git: /var/git/.git
sudo chmod -R ug+rwX /var/git/.git
sudo chmod -R ug+x /var/git/.git/hooks/post-receive
Push-to-publish
Everything is almost ready!
The only step required to deploy with a simple git push
is to add the remote to your repository.
For instance, here’s how to add a remote named deploy
to your local repository:
git remote add deploy git@:/var/git/.git
When you push to the deploy
remote, the published directory willbe updated automatically.
Nice, isn’t it?