Find a file
2021-03-30 22:00:59 +02:00
.github/workflows ci: fail on clippy warnings 2021-03-30 12:13:20 +02:00
src job: move blacklist processing to request 2021-03-30 22:00:59 +02:00
.envrc nix: add 'direnv' integration 2021-03-29 19:43:41 +00:00
.gitignore git: ignore 'result/' symlink from 'nix build' 2021-03-29 19:43:41 +00:00
.lohr repo: add sourcehut mirror 2021-03-29 22:20:25 +02:00
.pre-commit-config.yaml pre-commit: add more useful hooks 2021-03-29 19:43:41 +00:00
Cargo.lock job: add processing blacklist to global config 2021-03-30 16:28:00 +00:00
Cargo.toml job: add processing blacklist to global config 2021-03-30 16:28:00 +00:00
default.nix nix: support legacy nix using 'flake-compat' 2021-03-29 19:43:41 +00:00
flake.lock nix: flake: use 'nixpkgs' input for 'naersk' 2021-03-29 19:43:41 +00:00
flake.nix nix: flake: add meta information in package 2021-03-30 18:40:32 +00:00
LICENSE-APACHE README: add license notice 2021-03-29 23:17:17 +02:00
LICENSE-MIT README: add license notice 2021-03-29 23:17:17 +02:00
README.org README: mention 'LOHR_CONFIG' 2021-03-30 18:46:33 +00:00
rust-toolchain setup basic app 2021-03-29 02:01:53 +02:00
shell.nix nix: support legacy nix using 'flake-compat' 2021-03-29 19:43:41 +00:00

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.

Setup

Quickstart

Setting up lohr should be quite simple:

  1. Create a Rocket.toml file and add your configuration.
  2. Export a secret variable:

    $ export LOHR_SECRET=42 # please don't use this secret
  3. Run lohr:

    $ cargo run # or `cargo run --release` for production usage
  4. 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.
  5. Add a .lohr file containing the remotes you want to mirror this repo to:

    git@github.com: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

lohr looks for a lohr-config.yaml file in its LOHR_HOME directory. The LOHR_CONFIG variable takes precedence over looking into the state directory. This file takes the following format:

default_remotes:
  - "git@github:user"
  - "git@gitlab:user"

additional_remotes:
  - "git@git.sr.ht:~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 via default_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 git@github.com:alarsyo, and a push event webhook is received for repository git@gitlab.com:some/long/path/repo_name, then the mirror destination will be git@github.com: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.