|Antoine Martin d942dc1098|
lohr is a Git mirroring tool.
I created it to solve a simple problem I had: I host my own git server at https://git.alarsyo.net, but want to mirror my public projects to GitHub / GitLab, for backup and visibility purposes.
GitLab has a mirroring setting, but it doesn't allow for multiple mirrors, as far as I know. I also wanted my instance to be the single source of truth.
How it works
Gitea is setup to send webhooks to my
lohr server on every push update. When
lohr receives a push, it clones the concerned repository, or updates it if
already cloned. Then it pushes the update to all remotes listed in the
.lohr file at the repo root.
This is a very destructive process: anything removed from the single source of truth is effectively removed from any mirror as well.
lohr is published on crates.io, so you can
install it with
$ cargo install lohr
Note: currently this method won't get you the latest version of
lohr, as it
depends on Rocket v0.5.0, which isn't released yet. Updated versions of
will be published on crates.io as soon as Rocket v0.5.0 releases.
lohr should be quite simple:
Rocket.tomlfile and add your configuration.
Export a secret variable:
$ export LOHR_SECRET=42 # please don't use this secret
$ cargo run # or `cargo run --release` for production usage
Configure your favorite git server to send a webhook to
lohr's address on every push event.
I used Gitea's webhooks format, but I think they're similar to GitHub and GitLab's webhooks, so these should work too! (If they don't, please file an issue!)
Don't forget to set the webhook secret to the one you chose above.
.lohrfile containing the remotes you want to mirror this repo to:
and push it. That's it!
lohris mirroring your repo now.
lohr needs a place to clone repos and store its data. By default, it's the
current directory, but you can set the
LOHR_HOME environment variable to
As shown in the quickstart guide, you must set the
Extra remote configuration
You can provide
lohr with a YAML file containing additional configuration. You
can pass its path to the
--config flag when launching
lohr. If no
configuration is provided via a CLI flag,
lohr will check the
environment variable. If the environment variable isn't set either, it will
LOHR_HOME is a
lohr-config.yaml file exists, and try to load it.
This file takes the following format:
default_remotes: - "git@github:user" - "git@gitlab:user" additional_remotes: - "firstname.lastname@example.org:~user" blacklist: - "private-.*"
default_remotesis a list of remotes to use if no
.lohrfile is found in a repository.
additional_remotesis a list of remotes to add in any case, whether the original set of remotes is set via
default_remotesor via a
blacklistis a list of regular expressions to match against the full repository names. Any that matches will not be mirrored, even if it contains a
Both settings take as input a list of "stems", i.e. incomplete remote addresses,
to which the repo's name will be appended (so for example, if my
email@example.com:alarsyo, and a push event webhook is
received for repository
firstname.lastname@example.org:some/long/path/repo_name, then the
mirror destination will be
I was looking for a cool name, and thought about the Magic Mirror in Snow White. Some furious wikipedia searching later, I found that the Magic Mirror was probably inspired by the Talking Mirror in Lohr am Main. That's it, that's the story.
lohr is distributed under the terms of both the MIT license and the Apache
License (Version 2.0).