- Shell 97.3%
- Dockerfile 2.7%
|
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m15s
|
||
|---|---|---|
| .forgejo/workflows | ||
| .dockerignore | ||
| .gitignore | ||
| convert-mirrors.sh | ||
| docker-compose.yml | ||
| Dockerfile | ||
| github2forgejo.sh | ||
| README.md | ||
| template.env | ||
github2forgejo
Note: This is a fork of github2forgejo by MohamedElashri.
One–way bulk GitHub to Forgejo mirror script. Non-destructive (no deletes). Imports all repositories owned by a user or organization into a Forgejo user or organization as mirrors (default) or one-time clones. On reruns, mirrors are force-synced and the default branch HEAD is verified to match GitHub.
Features
- One–way mirror: GitHub -> Forgejo only
- Bulk, all-or-nothing import of owned repos
- Always authenticated to GitHub
- No tokens in clone URLs (auth passed via API payload)
- Optional
.envloading - Optional cron install for continuous mirroring
- Automatic mirror sync on rerun and HEAD verification
Usage
Quick start with .env:
# 1) Copy and edit the template
cp template.env .env
# 2) Run a mirror import (safe to rerun; will sync and verify)
./github2forejo.sh --env ./.env --strategy mirror
# 3) Optional: install a daily cron at 02:00 using your .env
./github2forejo.sh --env ./.env --strategy mirror --install-cron
Run with CLI args (no .env):
export GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
export FORGEJO_TOKEN=forgejo_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Sync personal user repos
./github2forejo.sh \
--github-user <Github_Username> \
--forgejo-url https://forgejo.example.com \
--forgejo-user <Forgejo_Username> \
--strategy mirror
Sync organization repos:
./github2forejo.sh \
--github-org <Github_Org> \
--forgejo-url https://forgejo.example.com \
--forgejo-user <Forgejo_Org> \
--strategy mirror
Clone once (no continuous updates):
./github2forejo.sh --env ./.env --strategy clone
Reverse mode (Forgejo → GitHub):
./github2forejo.sh \
--github-user <Github_Username> \
--forgejo-url https://forgejo.example.com \
--forgejo-user <Forgejo_Username> \
--reverse
Custom cron schedule:
./github2forejo.sh --env ./.env --strategy mirror \
--install-cron \
--cron-schedule "30 3 * * *"
Options (CLI)
| Option | Required | Type | Default | Description |
|---|---|---|---|---|
--github-user |
Conditional* | string | none | GitHub username for personal repos. Use --github-org for organizations. |
--github-org |
Conditional* | string | none | GitHub organization name for organization repos. Use --github-user for personal repos. |
--forgejo-url |
Yes | string | none | Forgejo base URL. Must start with https://. Can be set by FORGEJO_URL. |
--forgejo-user |
Yes | string | none | Forgejo user or org to receive the repos. Can be set by FORGEJO_USER. |
--strategy |
No | enum | mirror |
mirror for continuous updates, clone for one-time import. Can be set by STRATEGY. |
--reverse |
No | flag | false |
Reverse mode: mirror Forgejo → GitHub instead of GitHub → Forgejo. Requires git. |
--env |
No | path | none | Load key=value pairs from a .env file. CLI overrides .env. |
--install-cron |
No | flag | false |
Append a crontab entry for periodic mirroring. Can be set by INSTALL_CRON=true. |
--cron-schedule |
No | string | 0 2 * * * |
Cron expression for --install-cron. Can be set by CRON_SCHEDULE. |
-h, --help |
No | flag | n/a | Show help and exit. |
*Exactly one of --github-user or --github-org is required (unless set via environment variable).
Environment variables
| Variable | Required | Purpose |
|---|---|---|
GITHUB_TOKEN |
Yes | GitHub PAT with read access to your repos. Always used. |
FORGEJO_TOKEN |
Yes | Forgejo token that can create/import repos for the target user/org. |
GITHUB_USER |
Conditional* | GitHub username for personal repos. May be provided via CLI instead. |
GITHUB_ORG |
Conditional* | GitHub organization name for org repos. May be provided via CLI instead. |
FORGEJO_URL |
Yes | Forgejo base URL (must be https). May be provided via CLI. |
FORGEJO_USER |
Yes | Forgejo user/org target. May be provided via CLI. |
STRATEGY |
No | mirror or clone. Defaults to mirror. |
REVERSE |
No | true or false. Enable Forgejo → GitHub mode. Defaults to false. |
CRON_SCHEDULE |
No | Cron expression, defaults to 0 2 * * *. |
INSTALL_CRON |
No | true or false. Defaults to false. |
*Exactly one of GITHUB_USER or GITHUB_ORG is required (unless specified via CLI flag).
Docker usage
Docker support is available for scheduled (cron) mirroring.
Quick start with Docker Compose
# 1) Create a .env file with your configuration
cp template.env .env
# Edit .env with your tokens and settings
# 2) Start the container (runs on schedule)
docker-compose up -d
# 3) View logs
docker-compose logs -f
# 4) Stop the container
docker-compose down
Environment variables for Docker
All required variables must be set in .env or docker-compose.yml:
| Variable | Required | Purpose |
|---|---|---|
GITHUB_TOKEN |
Yes | GitHub PAT with read access to your repos. |
FORGEJO_TOKEN |
Yes | Forgejo token that can create/import repos for the target user/org. |
GITHUB_USER |
Conditional* | GitHub username for personal repos. |
GITHUB_ORG |
Conditional* | GitHub organization name for org repos. |
FORGEJO_URL |
Yes | Forgejo base URL (must be https). |
FORGEJO_USER |
Yes | Forgejo user/org target. |
STRATEGY |
No | mirror or clone. Defaults to mirror. |
CRON_SCHEDULE |
No | Cron expression, defaults to 0 2 * * * (daily at 2 AM). |
*Exactly one of GITHUB_USER or GITHUB_ORG is required.
Note: The Docker setup runs in cron mode only. For one-time imports, use the script directly on your host.
Reverse mode (Forgejo → GitHub)
By default, this script syncs from GitHub to Forgejo. The --reverse flag flips the direction, mirroring your Forgejo repositories back to GitHub.
How it works:
- Fetches all repos from the specified Forgejo user or organization
- Creates corresponding repos on GitHub if they don't exist
- Uses
git clone --mirrorto copy all branches and tags - Skips repos that are already up-to-date (verified by SHA comparison)
- Preserves repository visibility (private/public)
Requirements:
gitmust be installed on the systemGITHUB_TOKENmust have repo creation permissionsFORGEJO_TOKENmust have read access to your Forgejo repos
Example:
# Sync Forgejo user repos to GitHub user
./github2forgejo.sh \
--github-user myghuser \
--forgejo-url https://forgejo.example.com \
--forgejo-user myforgejouser \
--reverse
# Sync Forgejo org repos to GitHub org
./github2forgejo.sh \
--github-org myghorg \
--forgejo-url https://forgejo.example.com \
--forgejo-user myforgejoorg \
--reverse
Important notes:
- Reverse mode uses git for syncing, not the Forgejo mirror API
- Only one-way sync is supported (use
--reversefor Forgejo→GitHub, omit it for GitHub→Forgejo) - Existing repos on GitHub are updated in-place
- Verification is performed after each sync to ensure the SHA matches
Helper scripts
Convert mirror repos to regular repos
The convert-mirrors.sh helper script converts mirror repositories to regular repositories. This is useful when you want to stop mirroring and maintain the repos independently on your Forgejo instance.
# Interactive mode - select repos with fzf
./convert-mirrors.sh
# Convert all mirror repos
./convert-mirrors.sh --all
# With custom URL and token
./convert-mirrors.sh --url https://forgejo.example.com --token your_token
# Get help
./convert-mirrors.sh --help
Options:
| Option | Description |
|---|---|
--token |
API access token |
--url |
Forgejo instance URL (default: from .env or CLI) |
--all |
Convert all mirror repos (skip fzf selection) |
-h |
Show help message |
Environment variables:
FORGEJO_TOKEN- API access tokenFORGEJO_URL- Forgejo instance URL
.env example
# Required tokens
GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
FORGEJO_TOKEN=forgejo_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Required source: specify exactly one
GITHUB_USER=<Github_Username> # For personal repos
# GITHUB_ORG=<Github_Org> # For organization repos
# Required targets
FORGEJO_URL=https://forgejo.example.com
FORGEJO_USER=<Forgejo_Username>
# Optional
STRATEGY=mirror
CRON_SCHEDULE=0 2 * * *
INSTALL_CRON=false
Behavior and scope
- One way only: GitHub to Forgejo.
- Bulk, all or nothing: imports all repos from the specified GitHub user or organization; no per-repo selection.
- On reruns in mirror mode: each existing mirror is force-synced, then the default branch HEAD is verified to match GitHub. If mismatched, the script reports it.
- Private repos are mirrored when the GitHub token permits access.
- Tokens are not embedded in clone URLs; authentication is passed via the Forgejo migrate API payload.