diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | LICENSE-BSD | 23 | ||||
-rw-r--r-- | README.rst | 145 | ||||
-rwxr-xr-x | webhook.py | 3 |
4 files changed, 171 insertions, 1 deletions
@@ -1,2 +1,3 @@ __pycache__ git-mirror.conf* +README.html diff --git a/LICENSE-BSD b/LICENSE-BSD new file mode 100644 index 0000000..7ef1730 --- /dev/null +++ b/LICENSE-BSD @@ -0,0 +1,23 @@ +Copyright (c) 2014, Ralf Jung <post@ralfj.de> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..940a744 --- /dev/null +++ b/README.rst @@ -0,0 +1,145 @@ +git-mirror - Sync your git repositories +======================================= + +Introduction +------------ + +git-mirror_ is a tool to keep multiple git repositories of the same project in +sync. Whenever something is pushed to any repository, the commits will +immediately be forwarded to all the others. The tool assumes to run on a server +hosting one of these repositories - so there has to be at least one you can +control. A typical use-case would be your own gitolite_ installation, that you +want to keep in sync with GitHub_. + +.. _git-mirror: https://www.ralfj.de/projects/git-mirror +.. _gitolite: http://gitolite.com/gitolite/index.html +.. _GitHub: https://github.com/ + +Setup (gitolite) +---------------- + +This describes how you set up git-mirror on a server running gitolite. For other +git hosting software, please consult the respective documentation on adding git +hooks. I will assume that gitolite is installed to ``/home/git/gitolite``, that +the repositories are sitting in ``/home/git/repositories``, and that git-mirror +has been cloned to ``/home/git/git-mirror``. + +First of all, you need to create a file called ``git-mirror.conf`` in the +``git-mirror`` directory. For now, it only needs to contain a single line:: + + mail-sender = git@example.com + +We will also need to add hooks to the git repositories you want to sync. The +easiest way to manage these hooks is to put them into your ``gitolite-admin`` +repository, so enable the following line in ``/home/git/.gitolite.rc``:: + + LOCAL_CODE => "$rc{GL_ADMIN_BASE}/local", + +Make sure you read the `security note +<http://gitolite.com/gitolite/non-core.html#pushcode>`_ concerning this +configuration. + +Now add a file called ``local/hooks/repo-specific/git-mirror`` to your +``gitolite-admin`` repository, make ii executable, and give it the following +content:: + + #!/bin/sh + exec ~/git-mirror/githook.py + +For every repository you want to be synced, you can enable the hook by adding +the following line to its configuration in ``conf/gitolite.conf``:: + + option hook.post-receive = git-mirror + +(If you need multiple hooks here, you can separate them by spaces.) + +Finally, you need to tell git-mirror where to sync incoming changes to this +repository to. Add a block like the following to ``git-mirror.conf``:: + + [repo-name] + owner = post@ralfj.de + local = /home/git/repositories/repo-name.git + deploy-key = ssh-key + mirror-a = git@server2.example.com:repo-name.git + mirror-b = git@server2.example.org:the-repo.git + +Here, ``local`` has to be set to the path where the repository is stored +locally. ``deploy-key`` is the name of the SSH key used for pushing the changes +to other repositories. ``owner`` is the e-mail-address that error messages +occurring during synchronization are sent to. And finally, the URLs to push to +are given by ``mirror-<something>``. If these other servers also run gitolite +and have a symmetric setup, then no matter where a change is pushed, git-mirror +will forward it to all the other repositories. + +Setup (GitHub) +-------------- + +This explains how to configure a GitHub repository that should be part of a +synchronized set. I will assume that one of the copies of the repository lives +on a gitolite server you control. + +Since you cannot install a normal git hook on GitHub, syncing changes that are +sent to GitHub has to be done with a webhook. First of all, you will have to +configure your webserver to run ``webhook.py`` as CGI script. Consult the +webserver documentation for more details. + +Secondly, ``webhook.py`` needs to be able to find the main git-mirror scripts, +and it needs to be able to execute them as the ``git`` user. For the first +point, open ``webhook.py`` and change ``webhook_core`` to point to the file +``webhook-core.py`` in your git-mirror clone. If your installation matches the +paths I used above, that should already be the case. For the second point, +``webhook.py`` is using ``sudo`` to elevate its privileges. You need to tell +``sudo`` that this is all right, by creating a file +``/etc/sudoers.d/git-mirror`` with content:: + + www-data ALL=(git) NOPASSWD: /home/git/git-mirror/webhook-core.py + +Now, if you visit ``https://example.com/git-mirror/webhook.py`` (replace with +your URL), the script should run and tell you ``Repository missing or not +found.``. + +The next step is to add this as a webhook to the GitHub repository you want to +sync with, to create a fresh SSH key and configure it as deployment key for the +repository, and to configure git-mirror accordingly. For additional security, +one shouldalso configure a shared HMAC secret, such that the webhook can verify +that the data indeed comes from GitHub. + +To make your job easier, there is a script ``github-add-hooks.py`` that can do +all this for you. It assumes that the repository exists on the GitHub side, but +has not yet been configure for git-mirror, neither locally nor remotely. + +To give the script access to your repositories, you need to create an access +token for it. Go to "Personal Access Tokens" in your GitHub configuration, and +create a new token with the permissions ``admin:repo_hook`` and ``public_repo``. +Add the token and the webhook URL to the top part of ``git-mirror.conf`` (right +below ``mail-sender``):: + + github-token = pastethetokenhere + webhook-url = https://example.com/git-mirror/webhook.py + +Now you can call the automatic setup script as follows:: + + ./github-add-hooks.py -o UserName -e email@ddress.com -l ~/repositories/repo-name.git/ -n github-repo-name + +Notice that the username is case-sensitive! This will do all the setup on the +GitHub side, and it will add an appropriate configuration block to your local +``git-mirror.conf``. You will still have to manually add the local git hook to +gitolite. + +Source, License +--------------- + +You can find the sources in the `git repository`_ (also available `on GitHub`_). +They are provided under a `2-clause BSD license`_. See the file ``LICENSE-BSD`` +for more details. + +.. _git repository: http://www.ralfj.de/git/git-mirror.git +.. _on GitHub: https://github.com/RalfJung/git-mirror +.. _2-clause BSD license: http://opensource.org/licenses/bsd-license.php + +Contact +------- + +If you found a bug, or want to leave a comment, please +`send me a mail <mailto:post-AT-ralfj-DOT-de>`_. I'm also happy about pull +requests :) @@ -26,7 +26,8 @@ # This is the CGI script receiving GitHub webhooks. # You may have to change the location of the "main" webhook script: webhook_core = "/home/git/git-mirror/webhook-core.py" -# + +# Do NOT change anything below here import urllib.request, urllib.parse, json, os, sys # get repository from query string |