
Deploy Gitea Mirror | (Just Updated) GitHub to Gitea and Forgejo Backup, Admin Preset, Data Survives Redeploys
Gitea Mirror: back up GitHub repos to Gitea or Forgejo, admin preset
gitea-mirror
Just deployed
/app/data
Deploy and Host Gitea Mirror on Railway
Built for an LLM agent to deploy and use. The deploy form has no fields to fill, and the admin account is created for you at first boot, so nobody can claim the instance by opening the page first. Gitea Mirror is an open-source, self-hosted service that backs up GitHub repositories, organisations and starred repositories into your own Gitea or Forgejo server and keeps them in sync on a schedule.
About Hosting Gitea Mirror
This template runs one service, gitea-mirror: a Bun and Astro web app with its SQLite database and generated secrets on a volume mounted at /app/data. You connect a GitHub token and a Gitea or Forgejo token on its Configuration page (or through the API), pick what to mirror, and it keeps the copies current.
Admin preset. Upstream lets the first visitor register and become the only admin, so a fresh public deploy belongs to whoever finds the URL first, and an agent has no login to use. This template generates ADMIN_EMAIL and ADMIN_PASSWORD per deploy and creates that account at first boot; upstream then refuses every further sign-up. Redeploys keep the account, the database and the secrets because they live on the volume.
Using it. Sign in at your domain with the two variables, or use the API: sign in once, create an API key (gm_ prefix), and send it in the x-api-key header on every call. Keys can be read only or full access, and a key cannot mint more keys.
Agent contract
- Public URL:
https://RAILWAY_PUBLIC_DOMAIN(the generated domain of thegitea-mirrorservice; also in the variableBETTER_AUTH_URL) - Private URL:
http://gitea-mirror.railway.internal:8080 - Credentials:
ADMIN_EMAILandADMIN_PASSWORD(generated; the API key is created from them) - Auth: sign in with
POST /api/auth/sign-in/email(JSON body, anOriginheader equal toBETTER_AUTH_URL), create a key withPOST /api/auth/api-key/createusing that session cookie, then send the key as thex-api-keyheader; a call without a key or with a wrong key answers401 - Health:
GET /api/healthreturns 200
#!/bin/sh
# needs: BETTER_AUTH_URL, ADMIN_EMAIL, ADMIN_PASSWORD (variables of the gitea-mirror service); also curl
J="Content-Type: application/json"
curl -s -w "\nhealth: %{http_code}\n" "$BETTER_AUTH_URL/api/health" | tail -n 1
curl -s -o /dev/null -w "sign-in: %{http_code}\n" -c /tmp/gm.jar -X POST -H "$J" -H "Origin: $BETTER_AUTH_URL" -d "{\"email\":\"$ADMIN_EMAIL\",\"password\":\"$ADMIN_PASSWORD\"}" "$BETTER_AUTH_URL/api/auth/sign-in/email"
KEY=$(curl -s -b /tmp/gm.jar -X POST -H "$J" -H "Origin: $BETTER_AUTH_URL" -d '{"name":"agent"}' "$BETTER_AUTH_URL/api/auth/api-key/create" | sed -n 's/.*"key":"\([^"]*\)".*/\1/p')
curl -s -o /dev/null -w "read with key: %{http_code}\n" -H "x-api-key: $KEY" "$BETTER_AUTH_URL/api/dashboard"
curl -s -o /dev/null -w "read without key: %{http_code}\n" "$BETTER_AUTH_URL/api/dashboard"
curl -s -o /dev/null -w "write without key: %{http_code}\n" -X POST -H "$J" -d '{"owner":"octocat","repo":"hello-world"}' "$BETTER_AUTH_URL/api/sync/repository"
curl -s -o /dev/null -w "write with wrong key: %{http_code}\n" -X POST -H "$J" -H "x-api-key: gm_wrong" -d '{"owner":"octocat","repo":"hello-world"}' "$BETTER_AUTH_URL/api/sync/repository"
curl -s -o /dev/null -w "sign-up after admin: %{http_code}\n" -X POST -H "$J" -H "Origin: $BETTER_AUTH_URL" -d '{"email":"x@example.com","password":"password12345","name":"x"}' "$BETTER_AUTH_URL/api/auth/sign-up/email"
A fresh deploy prints health: 200, sign-in: 200, read with key: 200, read without key: 401, write without key: 401, write with wrong key: 401 and sign-up after admin: 403. To mirror a repository, add your GitHub and Gitea tokens on the Configuration page, then POST /api/sync/repository with the key.
Why Deploy Gitea Mirror on Railway?
Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.
By deploying Gitea Mirror on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.
- Agent-ready - no deployer fields, a contract block and one script that proves health, sign-in, API keys and the refusals.
- Not claimable by a stranger - the admin exists before the first visitor, and sign-up is closed.
- Data survives redeploys - database, admin and secrets sit on a volume at
/app/data. - Pinned - the upstream image is pinned by digest.
- Your own copy of your code - GitHub repositories, forks and stars land on a Gitea or Forgejo server you control.
Common Use Cases
- Backing up GitHub - keep a current copy of every repository and organisation on your own server.
- Leaving GitHub gradually - mirror first, switch remotes when ready.
- Archiving starred repositories - keep projects that may be taken down.
- Feeding a self-hosted CI - build from Gitea or Forgejo copies of public repositories.
Dependencies for Gitea Mirror Hosting
- The gitea-mirror service with a volume, created by the template. A Gitea or Forgejo server to mirror into, and a GitHub token, are yours to supply.
Deployment Dependencies
Template Content
gitea-mirror
ghcr.io/bon5co/gitea-mirror-railway:3.51.7