{"id":45656394,"url":"https://github.com/raylabshq/gitea-mirror","last_synced_at":"2026-06-13T05:01:05.218Z","repository":{"id":294147931,"uuid":"985572194","full_name":"RayLabsHQ/gitea-mirror","owner":"RayLabsHQ","description":"Gitea Mirror auto-syncs GitHub repos to your self-hosted Gitea/Forgejo, with a sleek Web UI and easy Docker deployment.","archived":false,"fork":false,"pushed_at":"2026-06-13T03:44:36.000Z","size":21113,"stargazers_count":1263,"open_issues_count":15,"forks_count":50,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-13T04:17:50.166Z","etag":null,"topics":["backup","docker","forgejo","gitea","gitea-mirror","github-mirror","mirrored-repository","mirroring","octokit"],"latest_commit_sha":null,"homepage":"https://giteamirror.com","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RayLabsHQ.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"github":["arunavo4"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":null,"thanks_dev":null,"custom":null}},"created_at":"2025-05-18T03:58:05.000Z","updated_at":"2026-06-13T03:44:38.000Z","dependencies_parsed_at":"2025-07-06T17:34:45.906Z","dependency_job_id":"6359b8c0-f8c9-4322-9b40-629f735261b8","html_url":"https://github.com/RayLabsHQ/gitea-mirror","commit_stats":null,"previous_names":["arunavo4/gitea-mirror"],"tags_count":114,"template":false,"template_full_name":null,"purl":"pkg:github/RayLabsHQ/gitea-mirror","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RayLabsHQ%2Fgitea-mirror","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RayLabsHQ%2Fgitea-mirror/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RayLabsHQ%2Fgitea-mirror/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RayLabsHQ%2Fgitea-mirror/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RayLabsHQ","download_url":"https://codeload.github.com/RayLabsHQ/gitea-mirror/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RayLabsHQ%2Fgitea-mirror/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34272603,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-13T02:00:06.617Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["backup","docker","forgejo","gitea","gitea-mirror","github-mirror","mirrored-repository","mirroring","octokit"],"created_at":"2026-02-24T08:40:21.894Z","updated_at":"2026-06-13T05:01:05.157Z","avatar_url":"https://github.com/RayLabsHQ.png","language":"TypeScript","funding_links":["https://github.com/sponsors/arunavo4"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\".github/assets/logo.png\" alt=\"Gitea Mirror Logo\" width=\"120\" /\u003e\n  \u003ch1\u003eGitea Mirror\u003c/h1\u003e\n  \u003cp\u003e\u003ci\u003eAutomatically mirror repositories from GitHub to your self-hosted Gitea/Forgejo instance.\u003c/i\u003e\u003c/p\u003e\n  \u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/RayLabsHQ/gitea-mirror/releases/latest\"\u003e\u003cimg src=\"https://img.shields.io/github/v/tag/RayLabsHQ/gitea-mirror?label=release\" alt=\"release\"/\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/RayLabsHQ/gitea-mirror/actions/workflows/astro-build-test.yml\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/RayLabsHQ/gitea-mirror/astro-build-test.yml?branch=main\" alt=\"build\"/\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/RayLabsHQ/gitea-mirror/pkgs/container/gitea-mirror\"\u003e\u003cimg src=\"https://img.shields.io/badge/ghcr.io-container-blue?logo=github\" alt=\"container\"/\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/RayLabsHQ/gitea-mirror/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/RayLabsHQ/gitea-mirror\" alt=\"license\"/\u003e\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n## 🚀 Quick Start\n\n```bash\n# Fastest way - using the simplified Docker setup\ndocker compose -f docker-compose.alt.yml up -d\n\n# Access at http://localhost:4321\n```\n\nFirst user signup becomes admin. Configure GitHub and Gitea/Forgejo through the web interface!\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\".github/assets/dashboard.png\" alt=\"Dashboard\" width=\"600\" /\u003e\n  \u003cimg src=\".github/assets/dashboard_mobile.png\" alt=\"Dashboard Mobile\" width=\"200\" /\u003e\n\u003c/p\u003e\n\n## ✨ Features\n\n- 🔁 Mirror public, private, and starred GitHub repos to Gitea/Forgejo\n- 🏛️ **GitHub Enterprise support** - Works with GHES and GHEC with data residency via `GH_API_URL`\n- 🏢 Mirror entire organizations with flexible strategies\n- 🎯 Custom destination control for repos and organizations\n- 📦 **Git LFS support** - Mirror large files with Git LFS\n- 📝 **Metadata mirroring** - Issues, pull requests (as issues), labels, milestones, wiki\n- 🚫 **Repository ignore** - Mark specific repos to skip\n- 🔐 Secure authentication with Better Auth (email/password, SSO, OIDC)\n- 📊 Real-time dashboard with activity logs\n- ⏱️ Scheduled automatic mirroring with configurable intervals\n- 🔄 **Auto-discovery** - Automatically import new GitHub repositories (v3.4.0+)\n- 🧹 **Repository cleanup** - Auto-remove repos deleted from GitHub (v3.4.0+)\n- 🎯 **Proper mirror intervals** - Respects configured sync intervals (v3.4.0+)\n- 🛡️ **[Force-push protection](docs/FORCE_PUSH_PROTECTION.md)** - Smart detection with backup-on-demand or block-and-approve modes (Beta)\n- 🗑️ Automatic database cleanup with configurable retention\n- 🐳 Dockerized with multi-arch support (AMD64/ARM64)\n\n## 📸 Screenshots\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\".github/assets/repositories.png\" alt=\"Repositories\" width=\"600\" /\u003e\n  \u003cimg src=\".github/assets/repositories_mobile.png\" alt=\"Rrepositories Mobile\" width=\"200\" /\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\".github/assets/organisation.png\" alt=\"Organisations\" width=\"600\" /\u003e\n  \u003cimg src=\".github/assets/organisation_mobile.png\" alt=\"Organisations Mobile\" width=\"200\" /\u003e\n\u003c/div\u003e\n\n## Installation\n\n### Docker (Recommended)\n\nWe provide two Docker Compose options:\n\n#### Option 1: Quick Start (docker-compose.alt.yml)\nPerfect for trying out Gitea Mirror or simple deployments:\n\n```bash\n# Clone repository\ngit clone https://github.com/RayLabsHQ/gitea-mirror.git\ncd gitea-mirror\n\n# Start with simplified setup\ndocker compose -f docker-compose.alt.yml up -d\n\n# Access at http://localhost:4321\n```\n\n**Features:**\n- ✅ Pre-built image - no building required\n- ✅ Minimal configuration needed\n- ✅ Data stored in `./data` directory\n- ✅ Configure everything through web UI\n- ✅ Automatic user/group ID mapping\n\n**Best for:**\n- First-time users\n- Testing and evaluation\n- Simple deployments\n- When you prefer web-based configuration\n\n#### Option 2: Full Setup (docker-compose.yml)\nFor production deployments with environment-based configuration:\n\n```bash\n# Start with full configuration options\ndocker compose up -d\n```\n\n**Features:**\n- ✅ Build from source or use pre-built image\n- ✅ Complete environment variable configuration\n- ✅ Support for custom CA certificates\n- ✅ Advanced mirror settings (forks, wiki, issues)\n- ✅ Multi-registry support\n\n**Best for:**\n- Production deployments\n- Automated/scripted setups\n- Advanced mirror configurations\n- When using self-signed certificates\n\n#### Using Pre-built Image Directly\n\n```bash\ndocker pull ghcr.io/raylabshq/gitea-mirror:latest\n```\n\n### Configuration Options\n\n#### Quick Start Configuration (docker-compose.alt.yml)\n\nMinimal `.env` file (optional - has sensible defaults):\n\n```bash\n# Custom port (default: 4321)\nPORT=4321\n\n# User/Group IDs for file permissions (default: 1000)\nPUID=1000\nPGID=1000\n\n# Session secret (auto-generated if not set)\nBETTER_AUTH_SECRET=your-secret-key-change-this-in-production\n```\n\nAll other settings are configured through the web interface after starting.\n\n#### Full Setup Configuration (docker-compose.yml)\n\nSupports extensive environment variables for automated deployment. See the full [docker-compose.yml](docker-compose.yml) for all available options including GitHub tokens, Gitea URLs, mirror settings, and more.\n\n📚 **For a complete list of all supported environment variables, see the [Environment Variables Documentation](docs/ENVIRONMENT_VARIABLES.md).**\n\n### LXC Container (Proxmox)\n\n```bash\n# One-line install on Proxmox VE\nbash -c \"$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/gitea-mirror.sh)\"\n```\n\nSee the [Proxmox VE Community Scripts](https://community-scripts.github.io/ProxmoxVE/scripts?id=gitea-mirror) for more details.\n\n### Nix/NixOS\n\nZero-configuration deployment with Nix:\n\n```bash\n# Run immediately - no setup needed!\nnix run --extra-experimental-features 'nix-command flakes' github:RayLabsHQ/gitea-mirror\n\n# Or build and run locally\nnix build --extra-experimental-features 'nix-command flakes'\n./result/bin/gitea-mirror\n\n# Or install to profile\nnix profile install --extra-experimental-features 'nix-command flakes' github:RayLabsHQ/gitea-mirror\ngitea-mirror\n```\n\n**NixOS users** - add to your configuration:\n```nix\n{\n  inputs.gitea-mirror.url = \"github:RayLabsHQ/gitea-mirror\";\n\n  services.gitea-mirror = {\n    enable = true;\n    betterAuthUrl = \"https://mirror.example.com\";\n    openFirewall = true;\n  };\n}\n```\n\nSecrets auto-generate, database auto-initializes. See [NIX.md](NIX.md) for quick reference or [docs/NIX_DEPLOYMENT.md](docs/NIX_DEPLOYMENT.md) for full documentation.\n\n### Manual Installation\n\n```bash\n# Install Bun\ncurl -fsSL https://bun.sh/install | bash\n\n# Setup and run\nbun run setup\nbun run dev\n```\n\n## Usage\n\n1. **First Time Setup**\n   - Navigate to http://localhost:4321\n   - Create admin account (first user signup)\n   - Configure GitHub and Gitea/Forgejo connections\n\n2. **Mirror Strategies**\n   - **Preserve Structure**: Maintains GitHub organization structure\n   - **Single Organization**: All repos go to one Gitea/Forgejo organization\n   - **Flat User**: All repos under your Gitea/Forgejo user account\n   - **Mixed Mode**: Personal repos in one org, organization repos preserve structure\n\n3. **Customization**\n   - Click edit buttons on organization cards to set custom destinations\n   - Override individual repository destinations in the table view\n   - Starred repositories can go to a dedicated org or preserve source owner/org paths\n\n## Advanced Features\n\n### Git LFS (Large File Storage)\nMirror Git LFS objects along with your repositories:\n- Enable \"Mirror LFS\" option in Settings → Mirror Options\n- Requires Gitea/Forgejo server with LFS enabled (`LFS_START_SERVER = true`)\n- Requires Git v2.1.2+ on the server\n\n### Metadata Mirroring\nTransfer complete repository metadata from GitHub to Gitea/Forgejo:\n- **Issues** - Mirror all issues with comments and labels\n- **Pull Requests** - Transfer PR discussions to Gitea/Forgejo\n- **Labels** - Preserve repository labels\n- **Milestones** - Keep project milestones\n- **Wiki** - Mirror wiki content\n- **Releases** - Transfer GitHub releases with assets\n\nEnable in Settings → Mirror Options → Mirror metadata\n\n### Repository Management\n- **Ignore Status** - Mark repositories to skip from mirroring\n- **Automatic Cleanup** - Configure retention period for activity logs\n- **Scheduled Sync** - Set custom intervals for automatic mirroring\n\n### Automatic Syncing \u0026 Synchronization\n\nGitea Mirror provides powerful automatic synchronization features:\n\n#### Features (v3.4.0+)\n- **Auto-discovery**: Automatically discovers and imports new GitHub repositories\n- **Repository cleanup**: Removes repositories that no longer exist in GitHub\n- **Proper intervals**: Mirrors respect your configured sync intervals (not Gitea/Forgejo's default 24h)\n- **Smart scheduling**: Only syncs repositories that need updating\n- **Auto-start on boot** (v3.5.3+): Automatically imports and mirrors all repositories when `SCHEDULE_ENABLED=true` or `GITEA_MIRROR_INTERVAL` is set - no manual clicks required!\n\n#### Configuration via Web Interface (Recommended)\nNavigate to the Configuration page and enable \"Automatic Syncing\" with your preferred interval.\n\n#### Configuration via Environment Variables\n\n**🚀 Set it and forget it!** With these environment variables, Gitea Mirror will automatically:\n1. **Import** all your GitHub repositories on startup (no manual import needed!)\n2. **Mirror** them to Gitea/Forgejo immediately  \n3. **Keep them synchronized** based on your interval\n4. **Auto-discover** new repos you create/star on GitHub\n5. **Clean up** repos you delete from GitHub\n\n```bash\n# Option 1: Enable automatic scheduling (triggers auto-start)\nSCHEDULE_ENABLED=true\nSCHEDULE_INTERVAL=3600        # Check every hour (or use cron: \"0 * * * *\")\n\n# Option 2: Set mirror interval (also triggers auto-start)\nGITEA_MIRROR_INTERVAL=8h     # Every 8 hours\n# Other examples: 5m, 30m, 1h, 24h, 1d, 7d\n\n# Advanced: Use cron expressions for specific times\nSCHEDULE_INTERVAL=\"0 2 * * *\"  # Daily at 2 AM (optimize bandwidth usage)\n\n# Auto-import new repositories (default: true)\nAUTO_IMPORT_REPOS=true\n\n# Auto-cleanup orphaned repositories\nCLEANUP_DELETE_IF_NOT_IN_GITHUB=true\nCLEANUP_ORPHANED_REPO_ACTION=archive  # 'archive' (recommended) or 'delete'\nCLEANUP_DRY_RUN=false                 # Set to true to test without changes\n```\n\n**Important Notes**:\n- **Auto-Start**: When `SCHEDULE_ENABLED=true` or `GITEA_MIRROR_INTERVAL` is set, the service automatically imports all GitHub repositories and mirrors them on startup. No manual \"Import\" or \"Mirror\" button clicks required!\n- The scheduler checks every minute for tasks to run. The `GITEA_MIRROR_INTERVAL` determines how often each repository is actually synced. For example, with `8h`, each repo syncs every 8 hours from its last successful sync.\n- **Large repo bootstrap**: For first-time mirroring of large repositories (especially with metadata/LFS), avoid very short intervals (for example `5m`). Start with a longer interval (`1h` to `8h`) or temporarily disable scheduling during the initial import/mirror run, then enable your regular interval after the first pass completes.\n- **Why this matters**: If your Gitea/Forgejo instance takes a long time to complete migrations/imports, aggressive schedules can cause repeated retries and duplicate-looking mirror attempts.\n\n**🛡️ Backup Protection Features**:\n- **No Accidental Deletions**: Repository cleanup is automatically skipped if GitHub is inaccessible (account deleted, banned, or API errors)\n- **Archive Never Deletes Data**: The `archive` action preserves all repository data:\n  - Regular repositories: Made read-only using Gitea/Forgejo's archive feature\n  - Mirror repositories: Renamed with `archived-` prefix (Gitea/Forgejo API limitation prevents archiving mirrors)\n  - Failed operations: Repository remains fully accessible even if marking as archived fails\n- **Manual Sync on Demand**: Archived mirrors stay in Gitea/Forgejo with automatic syncs disabled; trigger `Manual Sync` from the Repositories page whenever you need fresh data.\n- **The Whole Point of Backups**: Your Gitea/Forgejo mirrors are preserved even when GitHub sources disappear - that's why you have backups!\n- **Strongly Recommended**: Always use `CLEANUP_ORPHANED_REPO_ACTION=archive` (default) instead of `delete`\n\n### GitHub Enterprise (GHES / GHEC with Data Residency)\n\nGitea Mirror works with non-`github.com` GitHub deployments. Point the client at your Enterprise API via the `GH_API_URL` environment variable:\n\n```bash\n# GitHub Enterprise Server (self-hosted)\nGH_API_URL=https://ghe.example.com/api/v3\n\n# GitHub Enterprise Cloud with data residency\nGH_API_URL=https://api.TENANT.ghe.com\n```\n\nStandard GitHub Enterprise Cloud on `github.com` needs no override. Use a token issued by the target Enterprise instance for `GITHUB_TOKEN`.\n\n## Troubleshooting\n\n### Reverse Proxy Configuration\n\nIf you run behind a reverse proxy on a subpath (for example `https://git.example.com/mirror`), configure:\n\n```bash\n# BASE_URL handles the path prefix — auth URLs stay as origin only\nBASE_URL=/mirror\nBETTER_AUTH_URL=https://git.example.com\nPUBLIC_BETTER_AUTH_URL=https://git.example.com\nBETTER_AUTH_TRUSTED_ORIGINS=https://git.example.com\n# → Auth endpoints resolve to: https://git.example.com/mirror/api/auth/*\n```\n\nNotes:\n- `BASE_URL` sets the application path prefix.\n- `BETTER_AUTH_URL` and `PUBLIC_BETTER_AUTH_URL` should be **origin only** (e.g. `https://git.example.com`). Do not include the base path — it is applied automatically from `BASE_URL`. Any path accidentally included is stripped.\n- `BETTER_AUTH_TRUSTED_ORIGINS` should also contain origins only (no path).\n- `BASE_URL` is runtime configuration, so prebuilt registry images can be reused across different subpaths.\n\n### Mirror Token Rotation (GitHub Token Changed)\n\nFor existing pull-mirror repositories, changing the GitHub token in Gitea Mirror does not always update stored mirror credentials in Gitea/Forgejo for already-created repositories.\n\nIf sync logs show authentication failures (for example `terminal prompts disabled`), do one of the following:\n\n1. In Gitea/Forgejo, open repository **Settings → Mirror Settings** and update the mirror authorization password/token.\n2. Or delete and re-mirror the repository so it is recreated with current credentials.\n\n### Re-sync Metadata After Changing Mirror Options\n\nIf you enable metadata options (issues/PRs/labels/milestones/releases) after repositories were already mirrored:\n\n1. Go to **Repositories**, select the repositories, and click **Sync** to run a fresh sync pass.\n2. For a full metadata refresh, use **Re-run Metadata** on selected repositories. This clears metadata sync state for those repos and immediately starts Sync.\n3. If some repositories still miss metadata, reset metadata sync state in SQLite and sync again:\n\n```bash\nsqlite3 data/gitea-mirror.db \"UPDATE repositories SET metadata = NULL;\"\n```\n\nThis clears per-repository metadata completion flags so the next sync can re-run metadata import steps.\n\n### Mirror Interval vs Gitea/Forgejo `MIN_INTERVAL`\n\nGitea Mirror treats the interval configured in **Configuration** (or `GITEA_MIRROR_INTERVAL`) as the source of truth and applies it to mirrored repositories during sync.\n\nIf your Gitea/Forgejo server has `mirror.MIN_INTERVAL` set to a higher value (for example `24h`) and Gitea Mirror is set lower (for example `8h`), sync/mirror operations can fail when updating mirror settings.\n\nTo avoid this:\n\n1. Set Gitea Mirror interval to a value greater than or equal to your server `MIN_INTERVAL`.\n2. Do not rely on manual per-repository mirror interval edits in Gitea/Forgejo, as they will be overwritten on sync.\n\n## Development\n\n```bash\n# Install dependencies\nbun install\n\n# Run development server\nbun run dev\n\n# Run tests\nbun test\n\n# Build for production\nbun run build\n```\n\n## Technologies\n\n- **Frontend**: Astro, React, Shadcn UI, Tailwind CSS v4\n- **Backend**: Bun runtime, SQLite, Drizzle ORM\n- **APIs**: GitHub (Octokit), Gitea/Forgejo REST API\n- **Auth**: Better Auth with session-based authentication\n\n## Security\n\n### Token Encryption\n- All GitHub and Gitea/Forgejo API tokens are encrypted at rest using AES-256-GCM\n- Encryption is automatic and transparent to users\n- Set `ENCRYPTION_SECRET` environment variable for production deployments\n- Falls back to `BETTER_AUTH_SECRET` if not set\n\n### Password Security\n- User passwords are securely hashed by Better Auth\n- Never stored in plaintext\n- Secure cookie-based session management\n\n### Admin Password Recovery (CLI)\nIf email delivery is not configured, an admin with server access can reset a user password from the command line:\n\n```bash\nbun run reset-password -- --email=user@example.com --new-password='new-secure-password'\n```\n\nWhat this does:\n- Updates the credential password hash for the matching user\n- Creates a credential account if one does not already exist\n- Invalidates all active sessions for that user (forces re-login)\n\nUse this only from trusted server/admin environments.\n\n## Authentication\n\nGitea Mirror supports multiple authentication methods. **Email/password authentication is the default and always enabled.**\n\n### 1. Email \u0026 Password (Default)\nThe standard authentication method. First user to sign up becomes the admin.\n\n### 2. Single Sign-On (SSO) with OIDC\nEnable users to sign in with external identity providers like Google, Azure AD, Okta, Authentik, or any OIDC-compliant service.\n\n**Configuration:**\n1. Navigate to Settings → Authentication \u0026 SSO\n2. Click \"Add Provider\"\n3. Enter your OIDC provider details:\n   - Issuer URL (e.g., `https://accounts.google.com`)\n   - Client ID and Secret from your provider\n   - Use the \"Discover\" button to auto-fill endpoints\n\n**Redirect URL for your provider:**\n```\nhttps://your-domain.com/api/auth/sso/callback/{provider-id}\n```\n\nNeed help? The [SSO \u0026 OIDC guide](docs/SSO-OIDC-SETUP.md) now includes a working Authentik walkthrough plus troubleshooting tips. If you upgraded from a version earlier than v3.8.10 and see `TypeError … url.startsWith` after the callback, delete the old provider and add it again using the Discover button (see [#73](https://github.com/RayLabsHQ/gitea-mirror/issues/73) and [#122](https://github.com/RayLabsHQ/gitea-mirror/issues/122)).\n\n### 3. Header Authentication (Reverse Proxy)\nPerfect for automatic authentication when using reverse proxies like Authentik, Authelia, or Traefik Forward Auth.\n\n**Environment Variables:**\n```bash\n# Enable header authentication\nHEADER_AUTH_ENABLED=true\n\n# Header names (customize based on your proxy)\nHEADER_AUTH_USER_HEADER=X-Authentik-Username\nHEADER_AUTH_EMAIL_HEADER=X-Authentik-Email\nHEADER_AUTH_NAME_HEADER=X-Authentik-Name\n\n# Auto-provision new users\nHEADER_AUTH_AUTO_PROVISION=true\n\n# Restrict to specific email domains (optional)\nHEADER_AUTH_ALLOWED_DOMAINS=example.com,company.org\n```\n\n**How it works:**\n- Users authenticated by your reverse proxy are automatically logged in\n- No additional login step required\n- New users can be auto-provisioned if enabled\n- Falls back to regular authentication if headers are missing\n\n**Example Authentik Configuration:**\n```nginx\n# In your reverse proxy configuration\nproxy_set_header X-Authentik-Username $authentik_username;\nproxy_set_header X-Authentik-Email $authentik_email;\nproxy_set_header X-Authentik-Name $authentik_name;\n```\n\n### 4. OAuth Applications (Act as Identity Provider)\nGitea Mirror can also act as an OIDC provider for other applications. Register OAuth applications in Settings → Authentication \u0026 SSO → OAuth Applications tab.\n\n**Use cases:**\n- Allow other services to authenticate using Gitea Mirror accounts\n- Create service-to-service authentication\n- Build integrations with your Gitea Mirror instance\n\n## Known Limitations\n\n### Pull Request Mirroring Implementation\nPull requests **cannot be created as actual PRs** in Gitea/Forgejo due to API limitations. Instead, they are mirrored as **enriched issues** with comprehensive metadata.\n\n**Why real PR mirroring isn't possible:**\n- Gitea/Forgejo's API doesn't support creating pull requests from external sources\n- Real PRs require actual Git branches with commits to exist in the repository\n- Would require complex branch synchronization and commit replication\n- The mirror relationship is one-way (GitHub → Gitea/Forgejo) for repository content\n\n**How we handle Pull Requests:**\nPRs are mirrored as issues with rich metadata including:\n- 🏷️ Special \"pull-request\" label for identification\n- 📌 [PR #number] prefix in title with status indicators ([MERGED], [CLOSED])\n- 👤 Original author and creation date\n- 📝 Complete commit history (up to 10 commits with links)\n- 📊 File changes summary with additions/deletions\n- 📁 List of modified files (up to 20 files)\n- 💬 Original PR description and comments\n- 🔀 Base and head branch information\n- ✅ Merge status tracking\n\nThis approach preserves all important PR information while working within Gitea/Forgejo's API constraints. The PRs appear in the issue tracker with clear visual distinction and comprehensive details.\n\n## Contributing\n\nContributions are welcome! Please read our [Contributing Guidelines](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.\n\n## License\n\nGNU Affero General Public License v3.0 (AGPL-3.0) - see [LICENSE](LICENSE) file for details.\n\n## Star History\n\n\u003ca href=\"https://www.star-history.com/#RayLabsHQ/gitea-mirror\u0026type=date\u0026legend=bottom-right\"\u003e\n \u003cpicture\u003e\n   \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://api.star-history.com/svg?repos=RayLabsHQ/gitea-mirror\u0026type=date\u0026theme=dark\u0026legend=bottom-right\" /\u003e\n   \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://api.star-history.com/svg?repos=RayLabsHQ/gitea-mirror\u0026type=date\u0026legend=bottom-right\" /\u003e\n   \u003cimg alt=\"Star History Chart\" src=\"https://api.star-history.com/svg?repos=RayLabsHQ/gitea-mirror\u0026type=date\u0026legend=bottom-right\" /\u003e\n \u003c/picture\u003e\n\u003c/a\u003e\n\n## Support\n\n- 📖 [Documentation](https://github.com/RayLabsHQ/gitea-mirror/tree/main/docs)\n- 🔐 [Environment Variables](docs/ENVIRONMENT_VARIABLES.md)\n- 🛡️ [Force-Push Protection](docs/FORCE_PUSH_PROTECTION.md)\n- 🐛 [Report Issues](https://github.com/RayLabsHQ/gitea-mirror/issues)\n- 💬 [Discussions](https://github.com/RayLabsHQ/gitea-mirror/discussions)\n- 🔧 [Proxmox VE Script](https://community-scripts.github.io/ProxmoxVE/scripts?id=gitea-mirror)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraylabshq%2Fgitea-mirror","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fraylabshq%2Fgitea-mirror","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraylabshq%2Fgitea-mirror/lists"}