Federating Gitblit

SINCE 0.6.0

A Gitblit federation is a mechanism to clone repositories and keep them in sync from one Gitblit instance to another. Federation can be used to maintain a mirror of your Gitblit instance, to aggregate repositories from developer workstations, or to initially clone groups of repositories to developer workstations. If you are/were a Subversion user you might think of this as svn-sync, but better.

If your Gitblit instance allows federation and it is properly registered with another Gitblit instance, each of the non-excluded repositories of your Gitblit instance can be mirrored, in their entirety, to the pulling Gitblit instance. You may optionally allow pulling of user accounts and backup of server settings.

The federation feature should be considered a security backdoor and enabled or disabled as appropriate for your installation.

Please review all the documentation to understand how it works and its limitations.

block diagram

Important Changes to Note

The Gitblit 0.8.0 federation protocol adds retrieval of teams and referenced push scripts. Older clients will not know to request team or push script information.

The Gitblit 0.7.0 federation protocol is incompatible with the 0.6.0 federation protocol because of a change in the way timestamps are formatted.

Gitblit 0.6.0 uses the default google-gson timestamp serializer which generates locally formatted timestamps. Unfortunately, this creates problems for distributed repositories and distributed developers. Gitblit 0.7.0 corrects this error by serializing dates to the iso8601 standard. As a result 0.7.0 is not compatible with 0.6.0. A partial backwards-compatibility fallback was considered but it would only work one direction and since the federation mechanism is bidirectional it was not implemented.

Origin Gitblit Instance Requirements

federation.passphrase

The passphrase is used to generate permission tokens that can be shared with other Gitblit instances.

The passphrase value never needs to be shared, although if you give another Gitblit instance the ALL federation token then your passphrase will be transferred/backed-up along with all other server settings.

This value can be anything you want: an integer, a sentence, an haiku, etc. You should probably keep the passphrase simple and use standard Latin characters to prevent Java properties file encoding errors. The tokens generated from this value are affected by case, so consider this value CASE-SENSITIVE.

The federation feature is completely disabled if your passphrase value is empty.

NOTE:
Changing your federation.passphrase will break any registrations you have established with other Gitblit instances.

Pulling Gitblit Instance Requirements

Controlling What Gets Pulled

If you want your repositories (and optionally users accounts and settings) to be pulled by another Gitblit instance, you need to register your origin Gitblit instance with a pulling Gitblit instance by providing the url of your Gitblit instance and a federation token.

Gitblit generates the following standard federation tokens:

String allToken = SHA1(passphrase + "-ALL");
String usersAndRepositoriesToken = SHA1(passphrase + "-USERS_AND_REPOSITORIES");
String repositoriesToken = SHA1(passphrase + "-REPOSITORIES");

The ALL token allows another Gitblit instance to pull all your repositories, user accounts, server settings, and referenced push scripts.
The USERS_AND_REPOSITORIES token allows another Gitblit instance to pull all your repositories and user accounts.
The REPOSITORIES token only allows pulling of the repositories.

Individual Gitblit repository configurations such as description and accessRestriction are always mirrored.

If federation.passphrase has a non-empty value, the federation tokens are displayed in the log file and are visible, to administrators, in the web ui.

The three standard tokens grant access to ALL your non-excluded repositories. However, if you only want to specify different groups of repositories to be federated then you need to define federation sets.

Federation Sets

Federation Sets (*federation.sets*) are named groups of repositories. The Federation Sets are defined in gitblit.properties and are available for selection in the repository settings page. You can assign a repository to one or more sets and then distribute the federation token for the set. This allows you to grant federation pull access to a subset of your available repositories. Tokens for federation sets only grant pull access for the member repositories.

Federation Proposals (Origin Gitblit Instance)

Once you have properly setup your passphrase and can see your federation tokens, you are ready to share them with a pulling Gitblit instance.

The registration process can be partially automated by sending a federation proposal to the pulling Gitblit instance.
To send a proposal:

  1. Login to your Gitblit instance as an administrator
  2. Select and click the propose link for the appropriate token on the federation page
  3. Confirm the publicly accessible url of your (origin) Gitblit instance
  4. Enter the url of the pulling Gitblit instance you want to federate with
  5. Optionally enter a message for the administrators
  6. Click propose

Not all Gitblit instances accept federation proposals, there is a setting which allows Gitblit to outright reject them. In this case an email or instant message to the administrator of the other Gitblit instance is required. :)

If your proposal is accepted, the proposal is cached to disk on the pulling Gitblit server and, if properly configured, the administrators of that Gitblit server will receive an email notification of your proposal.

Your proposal includes:

  1. the url of your Gitblit instance
  2. the federation token you selected and its type
  3. the list of your non-excluded repositories, and their configuration details, that you propose to share

Submitting a proposal does not automatically register your server with the pulling Gitblit instance.
Registration is a manual process for an administrator.

Federation Proposals (Pulling Gitblit Instance)

If your Giblit instance has received a federation proposal, you will be alerted to that information the next time you login to Gitblit as an administrator.

You may view the details of a proposal by scrolling down to the bottom of the repositories page and selecting a proposal. Sample registration settings will be generated for you that you may copy & paste into either your gitblit.properties file or your web.xml file.

Excluding Repositories (Origin Gitblit Instance)

You may exclude a repository from being pulled by any federated Gitblit instance by setting its federation strategy to EXCLUDE in the repository's settings page.

Excluding Repositories (Pulling Gitblit Instance)

You may exclude repositories to pull in a federation registration. You may exclude all or you may exclude based on a simple fuzzy pattern. Only one wildcard character may be used within each pattern. Patterns are space-separated within the exclude and include fields.

federation.example.exclude = skipit.git

OR

federation.example.exclude = *
federation.example.include = somerepo.git someotherrepo.git

OR

federation.example.exclude = *
federation.example.include = common/* library/*

Tracking Status (Pulling Gitblit Instance)

Below the repositories list on the repositories page you will find a section named federation registrations. This section enumerates the other gitblit servers you have configured to periodically pull. The status of the latest pull will be indicated on the left with a colored circle, similar to the status of an executed unit test or Hudson/Jenkins build. You can drill into the details of the registration to view the status of the last pull from each repository available from that origin Gitblit instance. Additionally, you can specify the federation.N.notifyOnError=true flag, to be alerted via email of regressive status changes to individual registrations.

Tracking Status (Origin Gitblit Instance)

Origin Gitblit instances can not directly track the success or failure status of Pulling Gitblit instances. However, the Pulling Gitblit instance may elect to send a status acknowledgment (*federation.N.sendStatus=true*) to the origin Gitblit server that indicates the per-repository status of the pull operation. This is the same data that is displayed on the Pulling Gitblit instances ui.

How does it work? (Origin Gitblit Instances)

A pulling Gitblit instance will periodically contact your Gitblit instance and will provide the token as proof that you have granted it federation access. Your Gitblit instance will decide, based on the supplied token, if the requested data should be returned to the pulling Gitblit instance. Gitblit data (user accounts, repository metadata, and server settings) are serialized as JSON using google-gson and returned to the pulling Gitblit instance. Standard Git clone and pull operations are used to transfer commits.

The federation process executes using an internal administrator account, $gitblit. All the normal authentication and authorization processes are used for federation requests. For example, Git commands are authenticated as $gitblit / token.

While the $gitblit account has access to all repositories, server settings, and user accounts, it is prohibited from accessing the web ui and it is disabled if federation.passphrase is empty.

How does it work? (Pulling Gitblit Instances)

Federated repositories defined in gitblit.properties are checked after Gitblit has been running for 1 minute. The next registration check is scheduled at the completion of the current registration check based on the registration's specified frequency.

After a repository has been cloned it is flagged as isFederated (which identifies it as being sourced from another Gitblit instance), isFrozen (which prevents Git pushes to this mirror) and federationStrategy=EXCLUDED (which prevents this repository from being pulled by another federated Gitblit instance).

Origin Verification

During a federated pull operation, Gitblit does check that the origin of the local repository starts with the url of the federation registration.
If they do not match, the repository is skipped and this is indicated in the log.

User Accounts & Teams

By default all user accounts and teams (except the admin account) are automatically pulled when using the ALL token or the USERS_AND_REPOSITORIES token. You may exclude a user account from being pulled by a federated Gitblit instance by checking exclude from federation in the edit user page.

The pulling Gitblit instance will store a registration-specific users.conf file for the pulled user accounts and their repository permissions. This file is stored in the federation.N.folder folder.

If you specify federation.N.mergeAccounts=true, then the user accounts and team definitions from the origin Gitblit instance will be integrated into the users.conf file of your Gitblit instance and allow sign-on of those users.

NOTE:
Upgrades from older Gitblit versions will not have the #notfederated role assigned to the admin account. Without that role, your admin account WILL be transferred with an ALL or USERS_AND_REPOSITORIES token.
Please consider adding the #notfederated role to your admin account!

Server Settings

Server settings are only pulled when using the ALL token.

The pulling Gitblit instance will store a registration-specific gitblit.properties file for all pulled settings. This file is stored in the federation.N.folder folder.

These settings are unused by the pulling Gitblit instance.

Push Scripts

Your Groovy push scripts are only pulled when using the ALL token.

The pulling Gitblit instance will retrieve any referenced (i.e. used) push script and store it locally as registration_scriptName.groovy in the federation.N.folder folder.

These scripts are unused by the pulling Gitblit instance.

Collisions and Conflict Resolution

Gitblit does not detect conflict and it does not offer conflict resolution of repositories, users, teams, or settings.

If an object exists locally that has the same name as the remote object, it is assumed they are the same and the contents of the remote object are merged into the local object. If you can not guarantee that this is the case, then you should not store any federated repositories directly in git.repositoriesFolder and you should not enable mergeAccounts.

By default, federated repositories can not be pushed to, they are read-only by the isFrozen flag. This flag is ONLY enforced by Gitblit's JGit servlet. If you push to a federated repository after resetting the isFrozen flag or via some other Git access technique then you may break Gitblit's ability to continue pulling from the origin repository. If you are only pushing to a local branch then you might be safe.

Federation Pull Registration Keys

federation.N.url string the url of the origin Gitblit instance (required)
federation.N.token string the token provided by the origin Gitblit instance (required)
federation.N.frequency x [mins/hours/days] the period to wait between pull executions
federation.N.folder string the destination folder, relative to git.repositoriesFolder, for these repositories.
default is git.repositoriesFolder
federation.N.bare boolean if true (default), each repository is cloned as a bare repository (i.e. no working folder).
federation.N.mirror boolean if true (default), each repository HEAD is reset to origin/master after each pull. The repository is flagged isFrozen after the initial clone.

If false, each repository HEAD will point to the FETCH_HEAD of the initial clone from the origin until pushed to or otherwise manipulated.
federation.N.mergeAccounts boolean if true, merge the retrieved accounts into the users.conf of this Gitblit instance.
default is false
federation.N.sendStatus boolean if true, send the status of the federated pull to the origin Gitblit instance.
default is false
federation.N.include string array
(space-delimited)
list of included repositories (wildcard and fuzzy matching supported)
federation.N.exclude string array
(space-delimited)
list of excluded repositories (wildcard and fuzzy matching supported)
federation.N.notifyOnError boolean if true, send an email to the administrators on an error.
default is false

Example Federation Pull Registrations

These examples would be entered into the gitblit.properties file of the pulling gitblit instance.

(Nearly) Perfect Mirror Example

block diagram

This assumes that the token is the ALL token from the origin gitblit instance.

The repositories, example1_users.conf, example1_gitblit.propertiesn and all example1_scripts.groovy will be put in git.repositoriesFolder and the origin user accounts will be merged into the local user accounts, including passwords and all roles. The Gitblit instance will also send a status acknowledgment to the origin Gitblit instance at the end of the pull operation. The status report will include the state of each repository pull (EXCLUDED, SKIPPED, NOCHANGE, PULLED, MIRRORED). This way the origin Gitblit instance can monitor the health of its mirrors.

This example is considered nearly perfect because while the origin Gitblit's server settings & push scripts are pulled and saved locally, they are not merged with your server settings so its not a true mirror.

federation.example1.url = https://go.gitblit.com
federation.example1.token = 6f3b8a24bf970f17289b234284c94f43eb42f0e4
federation.example1.frequency = 120 mins
federation.example1.folder =
federation.example1.bare = true 
federation.example1.mirror = true
federation.example1.mergeAccounts = true
federation.example1.sendStatus = true

Just Repositories Example

This assumes that the token is the REPOSITORIES token from the origin gitblit instance.
The repositories will be put in git.repositoriesFolder/example2.

federation.example2.url = https://tomcat.gitblit.com/gitblit
federation.example2.token = 6f3b8a24bf970f17289b234284c94f43eb42f0e4
federation.example2.frequency = 120 mins
federation.example2.folder = example2
federation.example2.bare = true
federation.example2.mirror = true

All-but-One Repository Example

This assumes that the token is the REPOSITORIES token from the origin gitblit instance.
The repositories will be put in git.repositoriesFolder/example3.

federation.example3.url = https://tomcat.gitblit.com/gitblit
federation.example3.token = 6f3b8a24bf970f17289b234284c94f43eb42f0e4
federation.example3.frequency = 120 mins
federation.example3.folder = example3
federation.example3.bare = true
federation.example3.mirror = true
federation.example3.exclude = somerepo.git

Just One Repository Example

This assumes that the token is the REPOSITORIES token from the origin gitblit instance.
The repositories will be put in git.repositoriesFolder/example4.

federation.example4.url = https://tomcat.gitblit.com/gitblit
federation.example4.token = 6f3b8a24bf970f17289b234284c94f43eb42f0e4
federation.example4.frequency = 120 mins
federation.example4.folder = example4
federation.example4.bare = true
federation.example4.mirror = true
federation.example4.exclude = *
federation.example4.include = somerepo.git

Federation Client

Instead of setting up a full-blown pulling Gitblit instance, you can also use the federation client command-line utility. This is a packaged subset of the federation feature in a smaller, simpler command-line only tool.

The federation client relies on many of the same dependencies as Gitblit and will download them on first execution.

federation.properties

You may use the federation.properties file to configure one or more Gitblit instances that you want to pull from. This file is a subset of the standard gitblit.properties file.

By default this tool does not daemonize itself; it executes and then quits. This allows you to use the native scheduling feature of your OS. Of course, if you'd rather use Gitblit's scheduler you may use that by specifying the --daemon parameter.

http.sslVerify

If you are pulling from a Gitblit with a self-signed SSL certificate you will need to configure Git/JGit to bypass certificate verification.
(Git-Config Manual Page)

git config --global --bool --add http.sslVerify false

Command-Line Parameters

Instead of using federation.properties you may directly specify a Gitblit instance to pull from with command-line parameters.

java -cp fedclient.jar;"%CD%/ext/*" com.gitblit.FederationClient --url https://go.gitblit.com --mirror --bare --token 123456789
     --repositoriesFolder c:/mymirror

java -cp "fedclient.jar:ext/*" com.gitblit.FederationClient --url https://go.gitblit.com --mirror --bare --token 123456789
     --repositoriesFolder /srv/mymirror --daemon --frequency "24 hours"