Deploy Gitea Mirror with the Helm Chart
Why ship it to Kubernetes
If your homelab already runs a cluster (k3s, Talos, MicroK8s), Helm is the fastest way to keep Gitea Mirror close to the rest of your self-hosted stack. The chart in helm/gitea-mirror bundles the deployment, service, ingress, and persistence so you can version your backup mirror just like any other release.
Requirements
- Kubernetes 1.23+ with storage (Rook, Longhorn, local-path, etc.)
- Helm 3.8+
- GitHub PAT and Gitea API token ready (same scopes as the Docker playbook)
- Namespace with outbound access to GitHub and your Gitea host
Step-by-step
1. Create a namespace (optional)
kubectl create namespace gitea-mirror
2. Provide credentials and install the chart
The chart README documents multiple supported approaches. Choose the one that matches how you manage secrets.
The chart is published to GitHub Container Registry as an OCI package on every release, at oci://ghcr.io/raylabshq/charts/gitea-mirror. Each chart version deploys the application release with the same number, and the chart’s default image tag is that release, so there is nothing to clone and no tag to look up. Installing from a clone still works: replace the OCI reference with ./helm/gitea-mirror from the repository root.
Inline quick start (no values file):
helm upgrade --install gitea-mirror oci://ghcr.io/raylabshq/charts/gitea-mirror \
--namespace gitea-mirror \
--set "gitea-mirror.github.username=<your-gh-username>" \
--set "gitea-mirror.github.token=<your-gh-token>" \
--set "gitea-mirror.gitea.url=https://gitea.example.com" \
--set "gitea-mirror.gitea.token=<your-gitea-token>"
Using a values file:
# values-gitea-mirror.yaml
gitea-mirror:
github:
username: "your-gh-user"
token: "ghp_your_token"
gitea:
url: "https://git.lab.local"
token: "gitea_your_token"
persistence:
enabled: true
size: 1Gi
helm upgrade --install gitea-mirror oci://ghcr.io/raylabshq/charts/gitea-mirror \
--namespace gitea-mirror \
--values values-gitea-mirror.yaml
Add --version 3.31.0 (or any published release) to pin the chart. Without it Helm installs the newest one.
Bring your own Secret (recommended for production):
kubectl -n gitea-mirror create secret generic gitea-mirror-secrets \
--from-literal=GITHUB_TOKEN="ghp_your_token" \
--from-literal=GITEA_TOKEN="gitea_your_token" \
--from-literal=ENCRYPTION_SECRET="$(openssl rand -base64 48)"
# values-gitea-mirror.yaml
gitea-mirror:
existingSecret: "gitea-mirror-secrets"
github:
username: "your-gh-user"
gitea:
url: "https://git.lab.local"
Helm renders a Deployment, Service, optional Ingress/Gateway resources, and—when persistence is enabled—a PVC mounted at /app/data for the SQLite database and mirrored repositories.
3. Verify the release
kubectl -n gitea-mirror get pods,svc,pvc
kubectl -n gitea-mirror logs deploy/gitea-mirror --tail=100
Watch for the Runtime server listening line in the logs. Once ready, browse to the ingress host (or userland port-forward with kubectl port-forward svc/gitea-mirror 4321:4321). Complete the first-run wizard just like the Docker playbook.
After the pod is healthy, open Configuration → Connections inside the UI to add GitHub owners, choose a destination strategy, and enable metadata/LFS mirroring.
4. Keep it updated
- Re-run the
helm upgradecommand without--versionto move to the newest chart, and with it the newest application image. Pass--versionto stay on a specific release. - Leave
image.tagempty to run the release the chart was published for. If you set it, use the tag as it appears on the registry, with thevprefix, for example--set image.tag=v3.31.0. - Use Helm rollbacks if a release misbehaves:
helm rollback gitea-mirror <REVISION> -n gitea-mirror.
Observability
- Attach the
/api/healthendpoint to your cluster’s probing (Kubernetes probes are already configured by the chart); external monitors like Uptime Kuma or Blackbox Exporter can poll it too. - Watch PVC growth with
kubectl df-pvor your storage dashboard—the volume holds the SQLite database and any pre-sync backup bundles.
Disaster-recovery drill
- Scale the deployment down:
kubectl -n gitea-mirror scale deploy gitea-mirror --replicas=0. - Snapshot the PVC (CSI snapshots or Velero).
- Restore into a test namespace and scale the deployment back up.
- Confirm you can log in and the mirrored repositories are intact.
Cleanup
helm uninstall gitea-mirror -n gitea-mirror
kubectl delete namespace gitea-mirror
Remove the PVC manually if you want a clean slate: kubectl delete pvc gitea-mirror-storage -n gitea-mirror.
Ready to run on bare metal instead? Head over to the Proxmox LXC playbook.
FAQ
Where do I define GitHub owners and organizations?
Add owners from the Configuration → Connections screen after the release is running. The chart seeds credentials and defaults, but owner discovery happens in the UI.
Can I manage secrets outside of Kubernetes?
Yes. Leave existingSecret empty and the chart will create a secret with the values from the file, but using a pre-created secret keeps PATs out of Git history and lets you rotate them with kubectl apply.
How do I throttle syncs to fit my quota?
Adjust gitea-mirror.automation.schedule_interval in your values file (default: 3600 seconds = 1 hour). Lower values mean more frequent syncs; higher values create quieter schedules. You can also change the interval later from Configuration → Automation in the web UI.
Related guides
- Proxmox LXC or Unraid for single-node homelabs
- Automate the backup schedule once the chart is up
