mirror of
https://github.com/terraphim/gitea-infrastructure.git
synced 2026-07-16 00:00:32 +02:00
docs: Add repository mirroring guide and GitHub Actions
- Complete mirroring guide (GitHub ↔ Gitea) - GitHub Actions workflow to sync to Gitea - Mirror status check workflow - SSH and token authentication methods - Troubleshooting guide
This commit is contained in:
@@ -0,0 +1,35 @@
|
|||||||
|
name: Mirror Status Check
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 */6 * * *' # Every 6 hours
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check-sync:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check if repositories are in sync
|
||||||
|
run: |
|
||||||
|
# Get latest commit from GitHub
|
||||||
|
GITHUB_SHA=$(curl -s \
|
||||||
|
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||||
|
"https://api.github.com/repos/terraphim/gitea-infrastructure/commits/main" | \
|
||||||
|
jq -r '.sha')
|
||||||
|
|
||||||
|
# Get latest commit from Gitea
|
||||||
|
GITEA_SHA=$(curl -s \
|
||||||
|
-H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \
|
||||||
|
"https://git.terraphim.cloud/api/v1/repos/terraphim/gitea-infrastructure/commits/main" | \
|
||||||
|
jq -r '.sha')
|
||||||
|
|
||||||
|
echo "GitHub: ${GITHUB_SHA:0:7}"
|
||||||
|
echo "Gitea: ${GITEA_SHA:0:7}"
|
||||||
|
|
||||||
|
if [ "$GITHUB_SHA" == "$GITEA_SHA" ]; then
|
||||||
|
echo "✅ Repositories are in sync"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "⚠️ Repositories are OUT OF SYNC"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
name: Sync to Gitea
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, master]
|
||||||
|
workflow_dispatch: # Allow manual trigger
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
sync:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Full history
|
||||||
|
|
||||||
|
- name: Push to Gitea
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||||
|
run: |
|
||||||
|
git remote add gitea https://git.terraphim.cloud/terraphim/gitea-infrastructure.git
|
||||||
|
git config user.name "GitHub Actions"
|
||||||
|
git config user.email "actions@github.com"
|
||||||
|
|
||||||
|
# Push to Gitea with token authentication
|
||||||
|
# If using HTTPS with token: https://token@url
|
||||||
|
git push https://oauth2:${GITEA_TOKEN}@git.terraphim.cloud/terraphim/gitea-infrastructure.git main
|
||||||
@@ -0,0 +1,467 @@
|
|||||||
|
# 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)
|
||||||
Reference in New Issue
Block a user