2021-03-29 17:34:43 +02:00
#+title : 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.
2021-03-29 23:10:52 +02:00
** How it works
2021-03-29 17:34:43 +02:00
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 [[file:.lohr ][.lohr ]]
file at the repo root.
2021-03-29 23:10:52 +02:00
*** Destructive
2021-03-29 17:34:43 +02:00
This is a very destructive process: anything removed from the single source of
truth is effectively removed from any mirror as well.
2021-03-29 17:42:03 +02:00
2021-03-30 23:11:52 +02:00
** Installing
=lohr= is [[https://crates.io/crates/lohr ][published on crates.io ]], so you can install it with ~cargo install~ :
#+begin_src sh
2021-03-31 13:46:46 +02:00
$ cargo install lohr
2021-03-30 23:11:52 +02:00
#+end_src
2021-03-30 00:55:07 +02:00
** Setup
*** Quickstart
Setting up =lohr= should be quite simple:
1. Create a =Rocket.toml= file and [[https://rocket.rs/v0.4/guide/configuration/ ][add your configuration ]].
2021-03-30 11:23:09 +02:00
2. Export a secret variable:
#+begin_src sh
$ export LOHR_SECRET=42 # please don't use this secret
#+end_src
3. Run =lohr= :
2021-03-30 00:55:07 +02:00
#+begin_src sh
$ cargo run # or `cargo run --release` for production usage
#+end_src
2021-03-30 11:23:09 +02:00
4. Configure your favorite git server to send a webhook to =lohr= 's address on
2021-03-30 00:55:07 +02:00
every push event.
I used [[https://docs.gitea.io/en-us/webhooks/ ][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!)
2021-03-30 11:23:09 +02:00
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:
2021-03-30 00:55:07 +02:00
#+begin_example
git@github.com:you/your_repo
#+end_example
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.
2021-03-30 11:38:58 +02:00
**** Shared secret
As shown in the quickstart guide, you *must* set the =LOHR_SECRET= environment
variable.
2021-03-30 00:55:07 +02:00
**** Extra remote configuration
2021-03-30 22:57:27 +02:00
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.
2021-03-30 20:46:33 +02:00
This file takes the following format:
2021-03-30 00:55:07 +02:00
#+begin_src yaml
default_remotes:
- "git@github:user"
- "git@gitlab:user"
additional_remotes:
- "git@git.sr.ht:~user"
2021-03-30 20:46:33 +02:00
blacklist:
- "private-.*"
2021-03-30 00:55:07 +02:00
#+end_src
- ~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.
2021-03-30 20:46:33 +02:00
- ~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.
2021-03-30 00:55:07 +02:00
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= .
2021-03-29 23:11:13 +02:00
** Contributing
I accept patches anywhere! Feel free to [[https://github.com/alarsyo/lohr/pulls ][open a GitHub Pull Request ]], [[https://gitlab.com/alarsyo/lohr/ -/merge_requests][a GitLab
Merge Request]], or [[https://lists.sr.ht/~alarsyo/lohr-dev ][send me a patch by email ]]!
2021-03-29 23:10:52 +02:00
** Why lohr?
2021-03-29 17:42:03 +02:00
I was looking for a cool name, and thought about the Magic Mirror in Snow White.
Some *[[https://en.wikipedia.org/wiki/Magic_Mirror_(Snow_White)][furious wikipedia searching]]* later, I found that the Magic Mirror was
probably inspired by [[http://spessartmuseum.de/seiten/schneewittchen_engl.html ][the Talking Mirror in Lohr am Main ]]. That's it, that's the
story.
2021-03-29 23:17:17 +02:00
** License
=lohr= is distributed under the terms of both the MIT license and the Apache
License (Version 2.0).
See [[file:LICENSE-APACHE ][LICENSE-APACHE ]] and [[file:LICENSE-MIT ][LICENSE-MIT ]] for details.