Web

Synchroniser son serveur web avec Github

Article par (Webdesigner / Développeur Front-End chez Alsacréations, Strasbourg)
Créé le (31615 lectures)
Tags : webdev, git, github

Github est un bon moyen de partager ses sources, et intégré dans un workflow, c’est un outil puissant et très efficace, que ce soit pour travailler seul, ou en groupe. C’est aussi un bon moyen de déployer ses fichiers et sources sur son serveur personnel. Ne serait-il pas merveilleux si, à chaque fois que vous "pushiez" des mises à jour vers Github, que ces nouveaux fichiers et modifications soient automatiquement mises à jour sur votre serveur directement?

Cet article a été publié initialement sur le blog personnel de l'auteur, edenpulse à la date du Samedi 17 Mai 2014.

Je vais prendre pour acquis le fait que vous maitrisez un minimum le concept de Git, que la ligne de commande n’est pas votre ennemie (il n’y aura pas grand chose à y faire promis !) et que vous avez déjà un repo contenant des fichiers. Vérifiez bien que votre hébergeur vous autorise de vous connecter en SSH si vous êtes sur un hébergement mutualisé.

1ère étape : Génerer sa clé ssh.

Commencez par vous connecter en SSH à votre serveur personnel. 

$: ssh -l votrelogin adresseduserveur
<entrez votre mot de passe>
$: cd ~/.ssh
$: ls -al
<Liste les fichiers dans votre répertoire .ssh>

Si vous pouvez voir des fichiers nommés id_rsa.pub ou id_dsa.pub, vous pouvez passer directement à l’étape #2.

Sinon :

$: ssh-keygen -t rsa -C "votreemail@example.com"
<cela va créer une clé ssh avec votre email comme label>
#Generating public/private rsa key pair.
# Enter file in which to save the key (/Users/you/.ssh/id_rsa): [Presser entrer]
<A ce moment le serveur va vous demander une passphrase, non obligatoire.>

Le serveur va répondre quelque chose comme ceci :

Your identification has been saved in /Users/you/.ssh/id_rsa.
# Your public key has been saved in /Users/you/.ssh/id_rsa.pub.
# The key fingerprint is:
# 01:0f:f4:3b:ca:85:d6:17:a1:7d:f0:68:9d:f0:a2:db your_email@example.com

Il faut maintenant ajouter la clé à ssh-agent.

$: ssh-add ~/.ssh/id_rsa

Ceci fait, il faut copier la clé dans votre presse-papier, la commande pbcopy s’en charge très bien.

$: pbcopy < ~/.ssh/id_rsa.pub

Maintenant, il faut se rendre sur Github pour déclarer cette nouvelle clé.

  • Aller dans la partie SSH Keys.
  • Cliquer sur Add SSH key
  • Mettez une description pour la clé, par exemple “Serveur Perso”
  • Collez la clé ( CMD-V / CTRL-V / Clic-droit : coller)
  • Cliquez sur Add key
  • Confirmez votre choix en entrant votre mot de passe Github.

2ème étape : Tester sa clé SSH.

Très bien, on a généré la clé, il faut maintenant tester pour voir si elle fonctionne bien et communique correctement avec Github.

Retour dans le terminal :

$: ssh -T git@github.com

Vous allez très certainement voir un message tel que :

The authenticity of host 'github.com (207.97.227.239)' can't be established.
# RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
# Are you sure you want to continue connecting (yes/no)?

Tapez en toutes lettres yes.

Vous devriez voir ceci apparaitre :

Hi username! You've successfully authenticated, but Github does not
# provide shell access.

Si vous avez des problèmes, Github fourni un lien pour vérifier que tout est correct ici

3ème étape : Cloner le repo.

Pour le moment, on a une clé SSH qui permet de communiquer direct vers Github. Maintenant, cd vers le répertoire parent de l’endroit où nous voulons stocker le clone du repo Github.

Par exemple :

$: cd /mondomaine/repertoire-ou-je-veux-stocker-la-chose

En n’oubliant pas que Git crée un répertoire pour le repo, et y glisse les fichiers à l’intérieur.

Une fois à l’endroit ou l’on souhaite stocker les fichiers sources. Cloner le repo :

$: git clone git@github.com:votrenom/votrerepo.git

L’adresse peut être aisément trouvée sur la colone de droite de votre repo sur Github : ssh clone url.

Le serveur devrait vous rappatrier tous les fichiers de votre repo maintenant. Une fois l’opération terminée, vérifiez si les fichiers sont bien présents. ( ls est votre ami). Si c’est le cas, parfait ! Il ne nous reste plus qu’un étape !

4ème et dernière étape : activer la synchro

Très bien, votre repo est cloné. Il faut maintenant paramétrer Github pour qu’a chaque mise à jour de votre part, il notifie le serveur, et que celui-ci télécharge les nouvelles données.

Direction votre serveur de nouveau

  • Allez dans le répertoire de votre repo.
  • Créez un nouveau fichier nommé github-sync.php
  • Ouvrez le fichier et collez-y ceci :
<?php `git pull`;
  • Notez vous l’url d’accès direct à ce fichier par exemple : http://demo.demo.com/votrerepo/github-sync.php
  • Rendez vous sur Github, dans les paramètres de votre repo.
  • Allez dans la partie Webhooks & Services
  • Cliquez sur Add Webhook
  • Remplissez la case Payload URL avec l’url d’accès direct à votre fichier de sync : http://demo.demo.com/votrerepo/github-sync.php
  • Dans Content Type sélectionner application/json
  • Laisser “Secret” vide.
  • Selectionnez dans les choix en dessous Just the push event
  • Cochez la case Active (c’est mieux…)
  • Puis finaliser en cliquant sur Add webhook.

Voila c’est terminé, dorénavant, lorsque vous “commiterez” sur votre Github, votre serveur rappatriera tout seul les nouveaux fichiers !

Commentaires

arnaudbey a dit le

Ça présuppose qu'apache à le droit d'éxécuter git et qu'il a les permissions suffisantes pour écrire dans le dossier non ?

Manumanu a dit le

Excellent, mais en effet il faudrait quelques précisions concernant les prérequis sur le serveur.

edenpulse a dit le

C'est exact @arnaudbey, il faut qu'apache soit capable d'exécuter git, et les permissions suffisantes pour écrire dans le dossier. Il faut également que le safe-mode soit désactivé, pour que php puisse exécuter des commandes shell.
Je vais éditer l'article en conséquence rapidement.

arnaudbey a dit le

Me suis permis de le noter parce qu'il me semble que c'est le moins évident à faire au final (par rapport au hook git). Le plus simple je crois est d'autoriser apache à lancer git, via sudoers, et à exécuter git avec sudo.

edenpulse a dit le

C'est une bonne méthode effectivement. :) Après, d'après mon expérience, sur un hébergement mutualisé 1&1 et OVH, ça fonctionne parfaitement. Git est inclu dans le même groupe qu'apache, ce qu'il fait qu'il à les mêmes droits.
Effectivement, pour les dédiés, c'est un cas à prévoir.

pouetpouet a dit le

Bonjour,

Oui en l'état le tutoriel ne marchera pas, voici donc ce que vous devez faire du côté admin serveur pour aboutir à un résultat fonctionnel (cf suggestion manumanu):

<?php echo exec('whoami');
chmod 0777 /var/www/html
mkdir /var/www/.ssh
chown -R www-data:www-data /var/www/.ssh (si le résultat de whoami executé par php est www-data)
cd /var/www/.ssh
sudo -u www-data ssh-keygen -t rsa -C 'your@mail.com' (si le résultat de whoami executé par php est www-data)
id_rsa-git pour le nom de la clé privée (aucun mot de passe ensuite)
ssh-add /var/www/.ssh/id_rsa-git
touch config
nano
(puis enregistrer ce contenu)
Host bitbucket.org github.com
IdentityFile /var/www/.ssh/id_rsa-git
chown -R www-data:www-data /var/www/html (si le résultat de whoami executé par php est www-data)
chmod 0700 /var/www/.ssh

bofh a dit le

Bonjour, c'est sympa de partager ses tips avec la communauté, dans le cadre de mon travail je m’intéresse particulièrement aux problématiques de déploiement automatisé et d'intégration continue. Quand j'ai vu un article parlant de git/github sur alsacréations j'ai cliqué compulsivement mais j'ai beau lire et relire votre article je n'en comprends pas l’intérêt une âme charitable pourrait m'expliquer ?

Au passage @pouetpouet ta proposition d'améliorations est à éviter absolument c'est extrêmement dangereux on n’expose JAMAIS au grand JAMAIS un .ssh dans un serveur web (wtf?) donner les droits www-data au dossier est la pire chose à faire de plus la clé privée doit être en chmod 600 (700 pour ~/.ssh et 644 pour la clé publique seul le propriétaire de la clé doit pouvoir lire son contenu) donner le droit de lecture à www-data rends possible la lecture de la clé par un user mal intentionné en détournant un script php (techno choisie au hasard) mal fichu et hop on compromet votre serveur web car on peut récupérer votre paire de clés. Au passage le chown -R est inutile R=recursif votre dossier .ssh est vide donc ca fait deux touches de moins à triturer donc chown www-data:www-data /var/www/.ssh et c'est tout.

@pouetpouet mon propos n'est pas de troller, blesser ou donner des leçons juste de contribuer et de mettre le doigt sur un mauvaise pratique d'après moi. J'accepte aussi les critiques y a pas de soucis on est entre gens biens non ? Belle journée et je veux bien qu'on m'éclaire sur l'article initial revenons au sujet de départ... ;)

pouetpouet a dit le

@bofh

Non non vous avez raison de souligner les points 'pas très propres' (ce n'est pas du troll). Donc je vais rectifier maintenant que j'ai réussi à faire fonctionner les webhooks aussi bien sur bitbucket que github et répos publiques ou privés.

J'ai en fait rassemblé les données de plusieurs tutos et après plusieurs tests j'ai constaté que la partie de clé ssh créée dans un /var/www (et non /var/ww/html donc pas la partie publique...), trouvée dans un tuto en anglais est inutile car sur mon serveur de prod cela fonctionne aussi très bien avec la clé liée à l'utilisateur par défaut /root/.ssh (testé sur bitbucket: ssh -T git@bitbucket.org).

Donc cela veut dire que les remarques de votre second paragraphe sont maintenant inutiles aussi.

Par contre appliquer les changements utilisateur/groupe sur toute l'arborescence /html au résultat de whoami par PHP est essentiel sinon le hook php appelant git ne s'exécutera pas et les fichiers ne seront pas mis à jour !!!

Enfin si votre répo est privé vos devez mettre en clair le mot de passe votre compte github ou bitbucket dans l'URL de la remote (.git/config), c'est à dire avec la syntaxe suivante:

https://nom_utilisateur:mot_de_passe@github.com/nom_utilisateur/nom_repo.git

(avec un mot de passe ne contenant pas les caractères spéciaux @ ou :)
sinon la commande pull attendant votre mot de passe n'aboutira pas. (Il doit y avoir une solution plus clean mais en tout cas celle-ci est fonctionnelle)

Maintenant même si je ne suis pas admin linux même et que ce n'est ni mon travail (contrairement à vous si vos dires sont corrects), je vois tout à fait l'intérêt de tels processus et d'ailleurs je m'étais demandé après l'avoir imaginé un certain temps si un tel système existait et me doutant bien que cela devait exister (comme beaucoup d'autres personnes d'ailleurs).

A vous de trouvez l'intérêt sinon ça n'a pas d'intérêt?

pouetpouet a dit le

@pouetpouet :

Je me réponds à moi-même. Cette partie est sûrement aussi inutile:

"Par contre appliquer les changements utilisateur/groupe sur toute l'arborescence /html au résultat de whoami par PHP est essentiel sinon le hook php appelant git ne s'exécutera pas et les fichiers ne seront pas mis à jour !!!"

Il suffirait juste de l'appliquer les changements de proprio sur le fichier php qui reçoit le payload post de bitbucket ou github...

bofh a dit le

En fait finalement c'est bien trop compliqué tout ca et il y a de grandes chances que cela ne marche pas en fonction de la conf du serveur, de l'utilisateur apache/php, de la conf de php, pour moi c'est une hérésie d'utiliser php pour ça il a bien plus simple en plus ça implique que les fichiers sur le serveur ne bougent pas sinon le pull échouera. En fait je voulais des précisions sur l'article car c'est pas très clair le serveur qu'on synchronise avec le dépot c'est pour une appli ou c'est juste un mirroir des sources ? Si c'est une appli en général il faudrait envisager un workflow de déploiement avec des tags et faire ça via git-archive et un script de déploiement en gros y a pas de raison quand on fait un commit sur master qu'il faut déployer en prod et mettre sur la prod le dépôt git en entier...

Bref d'après moi php ca doit être utilisé pour l'appli mais pas pour faire du sysadmin trop dangereux et inutile. Y a bien plus simple et on est certain que ca marchera partout Alsacréation prône l'utilisation des standards à juste titre pour pas tomber dans le spécifique alors pourquoi ne pas utiliser intelligemment les outils à notre disposition.
Kiss style :
ssh nous permet d'executer des commandes à distance pourquoi pas faire un
ssh monlogin@monserveur "git pull"
ou ssh monlongin@monserveur "cd /srv/www/app.net && git pull"
on mets ca dans un hook post commit en local et c'est bon c'est reglé et pas besoin d'aller dans les params dans github d'utiliser un script php de se soucier des droits de sécu ... Par contre ça implique que on bosse toujours sur la même branche et que le serveur ne modifie pas les fichiers versionnés ou qu'on a le .gitignore qui va bien pour les fichiers du cache ...

bofh a dit le

Et enfin plus élégant :

on créé une remote branche pour la prod (notre serveur distant) sur notre dépot local:
$ git remote add web ssh://monlogin@monserveur.com/~/www/monprojet

on va sur le serveur en ssh :
$ ssh monlogin@monserveur.com

on place notre hook
$ cd ~/www/monprojet
$ cat > .git/hooks/post-receive
#!/bin/sh
GIT_WORK_TREE=/home/monlogin/www/monprojet git checkout -f

on donne les droits d'execution à notre hook
$ chmod +x .git/hooks/post-receive

et ensuite pour notre synchro après le commit :

$ git push web master

on peut même push sur plusieurs serveur avec le même nom de remote il faut dans ce cas la jouer avec le .git/config :

[remote "web"]
url = ssh://monlogin@monserveur.com/~/www/monprojet
url = ssh://monlogin@monautreserveur.com/~/www/monprojet

en fonction des versions de git y a juste un paramètre à ajouter sur le serveur en ssh dans le dossier monprojet si vous rencontrez une erreur suite au git push web (a faire sur le seveur) :
$ git config receive.denycurrentbranch ignore

c'est pas plus simple ? ;) les hooks git c'est le bien !!!!

Bon week end un peu en avance !

bofh a dit le

@pouetpouet encore moi :) désolé @edenpulse on se lâche un peu c'est dredi ...

Pour github plutot que de cloner en https utilisez ssh :

git clone git@github.com/user/projet.git

et rendez vous dans les paramètres de votre compte dans github pour ajouter votre ou vos clés publiques comme ca pas besoin de stocker un mot de passe en clair, et c'est bien plus pratique !

pouetpouet a dit le

En effet grosse faille de sécurité que:
fichier
http://domai.ne/.git/config
visible.
Donc solution ici finale ici (pour bitbucket):

https://confluence.atlassian.com/pages/viewpage.action?pageId=271943168

bofh a dit le

<Directory ~ "\.ssh">
Order allow,deny
Deny from all
</Directory>

dans la conf du vhost apache ou dans un vritual host idem pour git :

<Directory ~ "\.git">
Order allow,deny
Deny from all
</Directory>

bofh a dit le

ou plutot dans un .htaccess je voulais dire...

pouetpouet a dit le

Oui tout à fait d'accord pour le dernier point.
Mettre le maximum de sécurité ne pourra pas faire de mal.

En conclusion il a plein de manières de mettre en place des déploiements git over ssh automatiques.
Et je suis assez d'accord aussi sur le fait qu'il faille laisser à PHP s'occuper de ce qu'il doit s'occuper...

tedMosby a dit le

Bonsoir à tous,

J'ai un serveur Web mutualisé OVH et j'ai installé git.
Tout se passe bien. J'arrive a faire des pull et des push sur le projet.
Un de mes collègues à réussi à cloner le projet depuis le serveur sans problème.

Ma config est la suivante :
git remote add origin ssh://ftp.nomdedomaine.com/homez.210/lakr/projets/lap.git

Quand je fais les mises à jour, il m'indique que j'utilise bien le serveur.
fetch ssh://ftp.nomdedomaine.com/homez.210/lakr/projets/git.git +refs/heads/master:refs/remotes/origin/master
Jusqu'à présent tout est normal.

Mais quand je regarde sur mon serveur dans le répertoire homez.210/lakr/projets/lap.git, aucun ficher est stocké dans ce répertoire.
Est ce normal? Avez vous une explication?

bofh a dit le

@tedMosby en principe à la racine de ton projet tu dois avoir un dossier .git ou est stocké ta conf ...

donc à priori dans homez.210/lakr/projets/ tu dois avoir un .git avec tout ce qui va bien dedans (base git, conf ...)

Raf33 a dit le

Bonjour à tous,

j'ai bien lut attentivement tous vos posts mais après avoir installé git sur centos et créé un fichier github-sync.php ... les fichiers modifiés sont biens rapatriés sur le serveur, le seul petit problème est que les modifications sont visibles en ftp mais pas en front.

Pour exemple, je bouge le fichier index.php 1 dossier au dessus de public_html et le site fonctionne toujours...

un cache ou quelque chose que git aurait installé? J'ai beau cherché j'avoue que après 8h de config et de recherche je trouve pas... Merci d'avance

jerembel a dit le

Bonjour à tous

Voilà j'ai un souci car suite à la lecture de cet article et des commentaires j ai souscrit un abonnement OVH mutualisé offre pro (ssh inclus) pour pouvoir faire du deploiement via git (hook pull auto)

Cependant, le port 22 (ssh) est ouvert en entrée mais pas en sortie chez OVH !!! donc on peut sans problème se connecter au serveur en ssh depuis sa machine, mais pas se connecter à github depuis le serveur :

$: ssh -T git@github.com tombe en timeout sans connexion etablie...

Bien sur il est impossible de résilier ou meme de se retracter sur un abonnement OVH (voleurs avez vous dis ..?)

Est ce le type du support d ovh qui me dit n'importe quoi ou vos commentaires qui sont en erreur ?

PLZ HELP

Merci à vous :)

jerembel a dit le

@edenpulse : Bonjour à tous

Voilà j'ai un souci car suite à la lecture de cet article et des commentaires j ai souscrit un abonnement OVH mutualisé offre pro (ssh inclus) pour pouvoir faire du deploiement via git (hook pull auto)

Cependant, le port 22 (ssh) est ouvert en entrée mais pas en sortie chez OVH !!! donc on peut sans problème se connecter au serveur en ssh depuis sa machine, mais pas se connecter à github depuis le serveur :

$: ssh -T git@github.com tombe en timeout sans connexion etablie...

Bien sur il est impossible de résilier ou meme de se retracter sur un abonnement OVH (voleurs avez vous dis ..?)

Est ce le type du support d ovh qui me dit n'importe quoi ou vos commentaires qui sont en erreur ?

PLZ HELP

Merci à vous :)

jerembel a dit le

@edenpulse : Bonjour à tous

Voilà j'ai un souci car suite à la lecture de cet article et des commentaires j ai souscrit un abonnement OVH mutualisé offre pro (ssh inclus) pour pouvoir faire du deploiement via git (hook pull auto)

Cependant, le port 22 (ssh) est ouvert en entrée mais pas en sortie chez OVH !!! donc on peut sans problème se connecter au serveur en ssh depuis sa machine, mais pas se connecter à github depuis le serveur :

$: ssh -T git@github.com tombe en timeout sans connexion etablie...

Bien sur il est impossible de résilier ou meme de se retracter sur un abonnement OVH (voleurs avez vous dis ..?)

Est ce le type du support d ovh qui me dit n'importe quoi ou vos commentaires qui sont en erreur ?

PLZ HELP

Merci à vous :)

clementoriol a dit le

Ayant eu exactement le même problème que @jerembel je reviens poster la résolution ici. J'ai pu faire marcher le ssh vers git@github.com depuis le mutualisé pro OVH grâce à cette petite manip : https://help.github.com/articles/using-ssh-over-the-https-port/

Courage à ceux ayant eu le même souci :)