# Repository Mirroring: GitHub ↔ Gitea Complete guide for setting up mirroring between GitHub and self-hosted Gitea. ## Overview **Mirroring** keeps two repositories in sync automatically. Choose your direction: | Direction | Use Case | |-----------|----------| | **GitHub → Gitea** | GitHub as primary, Gitea as backup/mirror | | **Gitea → GitHub** | Gitea as primary, GitHub for visibility/CI | | **Bidirectional** | Both accept commits (advanced) | --- ## Method 1: Gitea as Mirror (GitHub → Gitea) Gitea periodically pulls from GitHub. Best for backup scenarios. ### Step 1: Create Mirror in Gitea **Via Web Interface:** 1. Go to https://git.terraphim.cloud 2. Click **"+"** → **"New Migration"** 3. Select **"GitHub"** 4. Enter URL: `https://github.com/terraphim/gitea-infrastructure` 5. **Authentication:** - If private repo: Enter GitHub Personal Access Token - If public: Leave empty 6. Check **"This repository will be a mirror"** 7. Click **"Migrate Repository"** **Via Gitea API:** ```bash # Get Gitea API token (Settings → Applications → Generate Token) GITEA_TOKEN="your_gitea_api_token" # Create mirror curl -X POST \ "https://git.terraphim.cloud/api/v1/repos/migrate" \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "clone_addr": "https://github.com/terraphim/gitea-infrastructure", "repo_name": "gitea-infrastructure-mirror", "repo_owner": "terraphim", "mirror": true, "auth_token": "your_github_token_if_private" }' ``` ### Step 2: Configure Mirror Settings 1. Go to repository **Settings** → **Repository** 2. Scroll to **Mirror Settings** 3. Set **Synchronization Interval**: `8h` (or your preference) 4. Click **"Update Mirror"** ### Step 3: Manual Sync (Optional) ```bash # Trigger immediate sync curl -X POST \ "https://git.terraphim.cloud/api/v1/repos/terraphim/gitea-infrastructure-mirror/mirror-sync" \ -H "Authorization: token ${GITEA_TOKEN}" ``` --- ## Method 2: GitHub as Mirror (Gitea → GitHub) Push from Gitea to GitHub. Best when Gitea is your primary. ### Step 1: Add GitHub Remote to Local Repository ```bash cd /home/alex/infrastructure/gitea_config # Add GitHub as mirror remote git remote add github https://github.com/terraphim/gitea-infrastructure.git # Or use SSH (recommended for automation) git remote add github git@github.com:terraphim/gitea-infrastructure.git ``` ### Step 2: Configure Push Mirroring in Gitea **Option A: Gitea Push Mirror (Native)** 1. In Gitea, go to repository **Settings** → **Repository** 2. Scroll to **Mirror Settings** 3. Check **"Push Mirror"** 4. Set **Git Remote URL**: `https://github.com/terraphim/gitea-infrastructure.git` 5. Add authentication: - **Username**: Your GitHub username - **Password/Token**: GitHub Personal Access Token 6. Set **Interval**: `8h` 7. Click **"Add Push Mirror"** **Option B: Using Git Hooks (More Control)** Create a post-receive hook in Gitea: 1. Go to repository **Settings** → **Git Hooks** 2. Find **post-receive** hook 3. Edit and add: ```bash #!/bin/bash # Push to GitHub after receiving commits # Use deploy key or HTTPS with token export GIT_SSH_COMMAND='ssh -i /path/to/deploy_key -o StrictHostKeyChecking=no' git push github main --mirror echo "Mirrored to GitHub" ``` ### Step 3: Test Push Mirroring ```bash # Make a test commit echo "# Test" >> README.md git add README.md git commit -m "test: Mirror sync" # Push to Gitea git push origin main # Check GitHub (should appear within seconds) ``` --- ## Method 3: Bidirectional Mirroring Both repositories accept commits. **Warning:** Can cause conflicts! ### Architecture ``` Developer A → Gitea ←→ GitHub ← Developer B ↑___________↓ Bidirectional sync ``` ### Setup 1. **Set up both mirrors:** - GitHub → Gitea (Method 1) - Gitea → GitHub (Method 2) 2. **Conflict Resolution Strategy:** - Always use `git merge` instead of `git push --force` - Set up webhook for immediate sync - Have clear contribution guidelines 3. **Webhook-based Immediate Sync:** **In Gitea:** - Settings → Webhooks → Add Webhook → Gitea - Target URL: Your sync service - Events: Push **GitHub → Gitea sync service:** ```python # sync-service.py (simplified) from flask import Flask, request import subprocess app = Flask(__name__) @app.route('/github-webhook', methods=['POST']) def github_hook(): # Trigger Gitea pull subprocess.run(['curl', '-X', 'POST', 'https://git.terraphim.cloud/api/v1/repos/terraphim/repo/mirror-sync']) return 'OK' @app.route('/gitea-webhook', methods=['POST']) def gitea_hook(): # Trigger GitHub push subprocess.run(['git', 'push', 'github', 'main']) return 'OK' ``` --- ## Method 4: Local Git Configuration (Simplest) Push to both remotes simultaneously from your local machine. ### Setup ```bash cd /home/alex/infrastructure/gitea_config # Check current remotes git remote -v # origin: should be Gitea # Add GitHub as additional remote git remote add github https://github.com/terraphim/gitea-infrastructure.git # Or use SSH: git remote add github git@github.com:terraphim/gitea-infrastructure.git ``` ### Push to Both ```bash # Push to Gitea (origin) git push origin main # Push to GitHub git push github main ``` ### Automate with Git Alias Add to `~/.gitconfig`: ```ini [alias] pushall = !git push origin $(git branch --show-current) && git push github $(git branch --show-current) pa = pushall ``` Usage: ```bash git pa # Pushes to both remotes ``` ### Automate with Bash Function Add to `~/.bashrc` or `~/.zshrc`: ```bash git-push-all() { local current_branch=$(git branch --show-current) echo "Pushing to all remotes..." git push origin "$current_branch" git push github "$current_branch" echo "✅ Pushed to Gitea and GitHub" } alias gpa='git-push-all' ``` --- ## Authentication Setup ### GitHub Personal Access Token 1. Go to GitHub → Settings → Developer settings → Personal access tokens 2. Generate new token (classic) 3. Scopes needed: - `repo` (full control of private repositories) - `workflow` (if using GitHub Actions) 4. Copy token ### Use Token in Gitea When setting up push mirror: - **Username**: Your GitHub username - **Password**: Your Personal Access Token (not your password!) ### SSH Key Setup (Recommended) **For automated pushes:** 1. Generate deploy key: ```bash ssh-keygen -t ed25519 -f ~/.ssh/gitea_github_deploy -C "gitea-mirror" ``` 2. Add public key to GitHub: - Repository Settings → Deploy Keys → Add deploy key - Paste contents of `~/.ssh/gitea_github_deploy.pub` - Allow write access 3. Add private key to Gitea server: ```bash # Copy to Gitea server scp ~/.ssh/gitea_github_deploy bigbox:~/.ssh/ ssh bigbox "chmod 600 ~/.ssh/gitea_github_deploy" ``` 4. Configure SSH for GitHub in Gitea: ```bash # Create SSH config ssh bigbox "cat > ~/.ssh/config << 'EOF' Host github-mirror HostName github.com User git IdentityFile ~/.ssh/gitea_github_deploy StrictHostKeyChecking no EOF" ``` 5. Update remote to use SSH: ```bash ssh bigbox "cd ~/gitea-stack && git remote set-url github git@github-mirror:terraphim/gitea-infrastructure.git" ``` --- ## Verification and Monitoring ### Check Mirror Status **In Gitea:** - Repository → Settings → Repository → Mirror Settings - Shows last sync time and status **Via API:** ```bash # Check mirror status curl -s \ "https://git.terraphim.cloud/api/v1/repos/terraphim/gitea-infrastructure-mirror" \ -H "Authorization: token ${GITEA_TOKEN}" | \ jq '.mirror_updated, .mirror_interval' ``` ### Monitoring Script Create `check-mirror.sh`: ```bash #!/bin/bash # Check if mirrors are in sync echo "Checking repository sync status..." # Get latest commit from GitHub GITHUB_SHA=$(curl -s \ "https://api.github.com/repos/terraphim/gitea-infrastructure/commits/main" | \ jq -r '.sha') # Get latest commit from Gitea GITEA_SHA=$(curl -s \ "https://git.terraphim.cloud/api/v1/repos/terraphim/gitea-infrastructure/commits/main" | \ jq -r '.sha') if [ "$GITHUB_SHA" == "$GITEA_SHA" ]; then echo "✅ Repositories are in sync" echo "Latest commit: ${GITHUB_SHA:0:7}" else echo "⚠️ Repositories are OUT OF SYNC" echo "GitHub: ${GITHUB_SHA:0:7}" echo "Gitea: ${GITEA_SHA:0:7}" fi ``` --- ## Troubleshooting ### Mirror Not Syncing **Check Gitea logs:** ```bash ssh bigbox "docker logs gitea | grep -i mirror" ``` **Test manually:** ```bash ssh bigbox cd ~/gitea-stack git fetch github git log HEAD..github/main # Check if behind ``` ### Authentication Failures **GitHub token expired:** - Generate new token in GitHub - Update in Gitea mirror settings **SSH key issues:** ```bash ssh bigbox "ssh -T github-mirror" # Should show: Hi terraphim/gitea-infrastructure! You've successfully authenticated ``` ### Conflict Resolution If repositories diverge: ```bash # On local machine git fetch origin # Gitea git fetch github # GitHub # Check differences git log --left-right --graph --cherry-pick --oneline origin/main...github/main # Merge changes git checkout main git merge origin/main git merge github/main # Push to both git push origin main git push github main ``` --- ## Best Practices ### 1. One-Way vs Two-Way - **Use one-way** for most cases (clear primary/secondary) - **Use two-way** only for specific workflows with clear contribution guidelines ### 2. Sync Frequency - **Backup mirrors**: 24h interval - **Active development**: 1h interval or webhook-triggered - **CI/CD**: Immediate webhook sync ### 3. Notifications Set up alerts for sync failures: - Gitea webhook on sync failure - GitHub Actions monitoring - Email notifications ### 4. Documentation Document your mirroring strategy: - Which repository is primary? - Where should PRs be opened? - How to handle conflicts? --- ## Quick Reference | Task | Command | |------|---------| | Check remotes | `git remote -v` | | Add GitHub remote | `git remote add github https://github.com/terraphim/gitea-infrastructure.git` | | Push to all | `git push origin main && git push github main` | | Force sync | `curl -X POST "https://git.terraphim.cloud/api/v1/repos/terraphim/repo/mirror-sync"` | | Check status | `git log origin/main..github/main` | --- ## Recommended Setup for Your Use Case **Primary: Gitea (self-hosted, private)** **Mirror: GitHub (backup, CI/CD)** 1. Use **Method 2 (Push Mirror)** from Gitea to GitHub 2. Set sync interval: 1 hour 3. Use SSH authentication with deploy key 4. Enable GitHub Actions for CI/CD on GitHub side 5. Keep Gitea as single source of truth for commits This gives you: - ✅ Full control on Gitea - ✅ GitHub as backup - ✅ Can use GitHub Actions for CI/CD - ✅ Simple one-way sync (less conflicts)