Skip to content

Commit c84091b

Browse files
committed
Initial commit
0 parents  commit c84091b

File tree

6 files changed

+204
-0
lines changed

6 files changed

+204
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/nbproject
2+
/.idea

Dockerfile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
FROM alpine:3.9
2+
3+
RUN apk add --no-cache git openssh-client
4+
5+
COPY ./mirror.sh /usr/local/bin
6+
COPY ./server.sh /usr/local/bin
7+
8+
RUN mkdir -p /storage; \
9+
chmod +x /usr/local/bin/mirror.sh; \
10+
chmod +x /usr/local/bin/server.sh
11+
12+
EXPOSE 8080
13+
VOLUME /storage
14+
WORKDIR /storage
15+
16+
ENTRYPOINT ["/usr/local/bin/server.sh"]

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2020 Dmitrii Poddubnyi
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

mirror.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/sh
2+
3+
set -eux
4+
5+
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
6+
git fetch --prune
7+
git remote set-head origin -d
8+
git branch -a || 'true'
9+
git push --prune dest +refs/remotes/origin/*:refs/heads/* +refs/tags/*:refs/tags/*

readme.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# GitBitLabHub: Mirror your repositories between Bitbucket / Gitlab / Github using simple webhooks.
2+
- It's a simple shell script (written in pure bash, even the webserver part).
3+
- The docker image is Alpine based and the size is about 10 MB.
4+
- Single container mirrors a single repository.
5+
- Single-threaded. It will ignore the next webhook while the previous one is being processed. DDoS protection out-of-the-box :).
6+
7+
## Why mirror repositories?
8+
- You can pipe multiple services. For example, use Bitbucket private repositories
9+
as a primary storage and self-hosted Gitlab instance as a purely CI/CD tool.
10+
- Better safe than sorry. Mirroring repos is a single backup alternative for SaaS.
11+
12+
## How to use
13+
14+
### How to run using docker
15+
```
16+
docker run -it \
17+
-e SRC_REPO=git@bitbucket.org:vendor/src_repo.git \
18+
-e DEST_REPO=git@gitlab.example.com:2222/vendor/dest_repo.git \
19+
-e SRC_DEPLOY_KEY=base64_encoded_key \
20+
-e DEST_DEPLOY_KEY=base64_encoded_key \
21+
-p 8181:8080/tcp \
22+
karser/gitbitlabhub
23+
```
24+
where SRC_DEPLOY_KEY and DEST_DEPLOY_KEY can be obtained by running
25+
```
26+
base64 -w 0 < ~/.ssh/project_src_id_rsa
27+
base64 -w 0 < ~/.ssh/project_dest_id_rsa
28+
```
29+
30+
The URL will be http://localhost:8181
31+
32+
### How to run using docker-compose and traefik
33+
34+
```
35+
version: '3.3'
36+
37+
services:
38+
gitbitlabhub_repo1:
39+
image: karser/gitbitlabhub
40+
restart: always
41+
networks:
42+
- webproxy
43+
environment:
44+
SRC_REPO: 'git@bitbucket.org:vendor/src_repo.git'
45+
DEST_REPO: 'git@gitlab.example.com:2222/vendor/dest_repo.git'
46+
SRC_DEPLOY_KEY: 'base64_encoded_key'
47+
DEST_DEPLOY_KEY: 'base64_encoded_key'
48+
labels:
49+
- "traefik.enable=true"
50+
- "traefik.backend=gitbitlabhub_repo1"
51+
- "traefik.frontend.rule=Host:gitbitlabhub.example.com;PathPrefixStrip:/vendor/src_repo"
52+
- "traefik.port=8080"
53+
- "traefik.docker.network=webproxy"
54+
volumes:
55+
- ./gitbitlabhub:/storage
56+
57+
networks:
58+
webproxy:
59+
external: true
60+
```
61+
62+
The URL will be https://gitbitlabhub.example.com/vendor/src_repo
63+
64+
## How to setup mirroring
65+
66+
1. Generate 2 deployment keys for source and destination:
67+
```
68+
ssh-keygen -t rsa -f ~/.ssh/project_src_id_rsa
69+
ssh-keygen -t rsa -f ~/.ssh/project_dest_id_rsa
70+
```
71+
Add these keys to the repository settings of source and destination correspondingly.
72+
```
73+
cat ~/.ssh/project_src_id_rsa.pub
74+
cat ~/.ssh/project_dest_id_rsa.pub
75+
```
76+
The Source deployment key can be marked as readonly. Depending on the platform it's called Deploy Token or Access key.
77+
See how to add deployment/access keys to [bitbucket](https://bitbucket.org/blog/deployment-keys), [bitbucket access keys](https://confluence.atlassian.com/bitbucketserver/ssh-access-keys-for-system-use-776639781.html),
78+
[gitlab](https://docs.gitlab.com/ce/ssh/), [github](https://developer.github.com/v3/guides/managing-deploy-keys/).
79+
80+
2. Run this container with all environment variables configured properly (see [How to use](#how-to-use) section).
81+
82+
3. Create the webhook in the source repository.
83+
See how to create a webhook in [bitbucket](https://confluence.atlassian.com/bitbucket/manage-webhooks-735643732.html),
84+
[gitlab](https://docs.gitlab.com/ce/user/project/integrations/webhooks.html), [github](https://developer.github.com/webhooks/creating/).
85+
86+
87+
## How to build
88+
89+
```
90+
docker build --tag karser/gitbitlabhub:latest .
91+
docker push karser/gitbitlabhub:latest
92+
```

server.sh

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/bin/sh
2+
3+
set -eux
4+
5+
# Extract the protocol (includes trailing "://").
6+
DEST_PROTO="$(echo $DEST_REPO | sed -nr 's,^(.*://).*,\1,p')"
7+
# Remove the protocol from the URL.
8+
DEST_URL="$(echo ${DEST_REPO/$DEST_PROTO/})"
9+
# Extract the user (includes trailing "@").
10+
DEST_USER="$(echo $DEST_URL | sed -nr 's,^(.*@).*,\1,p')"
11+
DEST_USER=${DEST_USER:-git@}
12+
# Remove the user from the URL.
13+
DEST_URL="$(echo ${DEST_URL/$DEST_USER/})"
14+
# Extract the port (includes leading ":").
15+
DEST_PORT="$(echo $DEST_URL | sed -nr 's,.*:([0-9]+).*,\1,p')"
16+
DEST_PORT=${DEST_PORT:-22}
17+
# Remove the port from the URL.
18+
DEST_URL="$(echo ${DEST_URL/$DEST_PORT/})"
19+
# Extract the path (includes leading "/" or ":").
20+
DEST_PATH="$(echo $DEST_URL | sed -nr 's,[^/:]*([/:].*),\1,p')"
21+
# Remove the path from the URL.
22+
DEST_HOST="$(echo ${DEST_URL/$DEST_PATH/})"
23+
24+
25+
# Extract the protocol (includes trailing "://").
26+
SRC_PROTO="$(echo $SRC_REPO | sed -nr 's,^(.*://).*,\1,p')"
27+
# Remove the protocol from the URL.
28+
SRC_URL="$(echo ${SRC_REPO/$SRC_PROTO/})"
29+
# Extract the user (includes trailing "@").
30+
SRC_USER="$(echo $SRC_URL | sed -nr 's,^(.*@).*,\1,p')"
31+
SRC_USER=${SRC_USER:-git@}
32+
# Remove the user from the URL.
33+
SRC_URL="$(echo ${SRC_URL/$SRC_USER/})"
34+
# Extract the port (includes leading ":").
35+
SRC_PORT="$(echo $SRC_URL | sed -nr 's,.*:([0-9]+).*,\1,p')"
36+
SRC_PORT=${SRC_PORT:-22}
37+
# Remove the port from the URL.
38+
SRC_URL="$(echo ${SRC_URL/$SRC_PORT/})"
39+
# Extract the path (includes leading "/" or ":").
40+
SRC_PATH="$(echo $SRC_URL | sed -nr 's,[^/:]*([/:].*),\1,p')"
41+
# Remove the path from the URL.
42+
SRC_HOST="$(echo ${SRC_URL/$SRC_PATH/})"
43+
# name that can be used for the folder name
44+
SRC_PROJECT="$(echo $SRC_PATH | sed -nr 's,.*/(.*)\.git,\1,p')"
45+
46+
47+
mkdir -p ~/.ssh
48+
49+
eval `ssh-agent -s`
50+
echo "$SRC_DEPLOY_KEY" | base64 -d | ssh-add -
51+
echo "$DEST_DEPLOY_KEY" | base64 -d | ssh-add -
52+
ssh -o StrictHostKeyChecking=no -T "$SRC_USER$SRC_HOST" -p "$SRC_PORT"
53+
ssh -o StrictHostKeyChecking=no -T "$DEST_USER$DEST_HOST" -p "$DEST_PORT"
54+
55+
if [[ ! -d /storage/"$SRC_PROJECT" ]]; then
56+
cd /storage
57+
git clone --bare "$SRC_REPO" "$SRC_PROJECT"
58+
cd /storage/"$SRC_PROJECT"
59+
git remote add dest ssh://"$DEST_REPO"
60+
fi
61+
62+
cd /storage/"$SRC_PROJECT"
63+
64+
while true; do nc -l -p 8080 -e sh -c 'echo -e "HTTP/1.0 200 OK\r\nDate: $(date)\r\nContent-Length: 2\r\n\r\nOK"; sh /usr/local/bin/mirror.sh;'; done

0 commit comments

Comments
 (0)