lohr
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.
Destructive
This is a very destructive process: anything removed from the single source of truth is effectively removed from any mirror as well.
Installing
lohr
is published on crates.io, so you can install it with cargo install
:
$ cargo +nightly install lohr
We currently require a nightly compiler because Rocket needs one to compile (a 0.5.0 which compiles on stable Rust is in the making, stay tuned!). You can install a nightly toolchain with the following command:
$ rustup install nightly
Setup
Quickstart
Setting up lohr
should be quite simple:
-
Create a
Rocket.toml
file and add your configuration. -
Export a secret variable:
$ export LOHR_SECRET=42 # please don't use this secret
-
Run
lohr
:$ 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.
-
Add a
.lohr
file containing the remotes you want to mirror this repo to:[email protected]:you/your_repo
and push it. That's it!
lohr
is mirroring your repo now.
Configuration
Home directory
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 customize it.
Shared secret
As shown in the quickstart guide, you must set the LOHR_SECRET
environment variable.
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 LOHR_CONFIG
environment variable. If the environment variable isn't set either, it will check in 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:
- "[email protected]:~user"
blacklist:
- "private-.*"
default_remotes
is a list of remotes to use if no.lohr
file is found in a repository.additional_remotes
is a list of remotes to add in any case, whether the original set of remotes is set viadefault_remotes
or via a.lohr
file.blacklist
is a list of regular expressions to match against the full repository names. Any that matches will not be mirrored, even if it contains a.lohr
file.
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 default_remotes
contains [email protected]:alarsyo
, and a push event webhook is received for repository [email protected]:some/long/path/repo_name
, then the mirror destination will be [email protected]:alarsyo/repo_name
.
Contributing
I accept patches anywhere! Feel free to open a GitHub Pull Request, a GitLab Merge Request, or send me a patch by email!
Why lohr?
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.
License
lohr
is distributed under the terms of both the MIT license and the Apache License (Version 2.0).
See LICENSE-APACHE and LICENSE-MIT for details.