mirror of
https://github.com/RayLabsHQ/gitea-mirror.git
synced 2025-12-06 11:36:44 +03:00
Added a few more articles
This commit is contained in:
@@ -19,7 +19,7 @@ import { useCases } from '@/lib/use-cases';
|
||||
</div>
|
||||
|
||||
<div class="grid gap-4 sm:gap-6 lg:gap-8 lg:grid-cols-3">
|
||||
{useCases.map((useCase) => (
|
||||
{useCases.slice(0, 3).map((useCase) => (
|
||||
<article class="group relative flex flex-col rounded-2xl border bg-background/80 p-6 sm:p-8 shadow-sm transition-all duration-300 hover:-translate-y-1 hover:shadow-lg">
|
||||
<div class="absolute inset-0 rounded-2xl bg-gradient-to-br from-primary/5 via-accent/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
|
||||
<div class="relative flex flex-col h-full">
|
||||
@@ -60,5 +60,15 @@ import { useCases } from '@/lib/use-cases';
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div class="mt-10 text-center">
|
||||
<a
|
||||
href="/use-cases/"
|
||||
class="inline-flex items-center gap-2 rounded-full border border-primary/40 bg-primary/10 px-6 py-2 text-sm font-semibold text-primary transition-colors hover:bg-primary/15"
|
||||
>
|
||||
View more use cases
|
||||
<ArrowRight class="h-4 w-4" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
79
www/src/components/UseCasesList.tsx
Normal file
79
www/src/components/UseCasesList.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
|
||||
import { useCases } from '@/lib/use-cases';
|
||||
import { ArrowRight } from 'lucide-react';
|
||||
|
||||
const featured = useCases.slice(0, 3);
|
||||
const more = useCases.slice(3);
|
||||
|
||||
export function FeaturedUseCases() {
|
||||
return (
|
||||
<div className="mt-8 grid gap-6 lg:grid-cols-3">
|
||||
{featured.map((item) => (
|
||||
<article key={item.slug} className="group relative flex flex-col rounded-3xl border border-primary/50 bg-primary/5 p-6 sm:p-7 shadow-lg shadow-primary/10 transition-all duration-300 hover:-translate-y-1">
|
||||
<div className="flex flex-wrap items-center gap-2 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground">
|
||||
{item.tags.map((tag) => (
|
||||
<span key={tag} className="inline-flex items-center rounded-full border border-muted px-2.5 py-1">{tag}</span>
|
||||
))}
|
||||
</div>
|
||||
<h2 className="mt-4 text-xl font-semibold sm:text-2xl text-foreground">{item.title}</h2>
|
||||
<p className="mt-3 text-sm sm:text-base text-muted-foreground">{item.summary}</p>
|
||||
<div className="mt-5 grid gap-3 text-sm text-muted-foreground">
|
||||
<div>
|
||||
<h3 className="text-xs font-semibold uppercase tracking-wide text-foreground/70">Pain point</h3>
|
||||
<p>{item.painPoint}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xs font-semibold uppercase tracking-wide text-foreground/70">Outcome</h3>
|
||||
<p>{item.outcome}</p>
|
||||
</div>
|
||||
</div>
|
||||
<a
|
||||
href={`/use-cases/${item.slug}/`}
|
||||
className="mt-6 inline-flex w-max items-center gap-2 rounded-full border border-primary/50 px-4 py-2 text-sm font-semibold text-primary transition-colors hover:bg-primary/10"
|
||||
>
|
||||
View playbook
|
||||
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
|
||||
</a>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function MoreUseCases() {
|
||||
return (
|
||||
<div className="mt-8 grid gap-6 md:grid-cols-2">
|
||||
{more.map((item) => (
|
||||
<article key={item.slug} className="group relative flex flex-col rounded-3xl border border-muted bg-background/70 p-6 sm:p-7 transition-all duration-300 hover:-translate-y-1 hover:border-primary/40 hover:shadow-lg">
|
||||
<div className="flex flex-wrap items-center gap-2 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground">
|
||||
{item.tags.map((tag) => (
|
||||
<span key={tag} className="inline-flex items-center rounded-full border border-muted px-2.5 py-1">{tag}</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<h2 className="mt-4 text-xl font-semibold sm:text-2xl text-foreground/90">{item.title}</h2>
|
||||
<p className="mt-3 text-sm sm:text-base text-muted-foreground">{item.summary}</p>
|
||||
|
||||
<div className="mt-5 grid gap-3 text-sm text-muted-foreground">
|
||||
<div>
|
||||
<h3 className="text-xs font-semibold uppercase tracking-wide text-foreground/70">Pain point</h3>
|
||||
<p>{item.painPoint}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xs font-semibold uppercase tracking-wide text-foreground/70">Outcome</h3>
|
||||
<p>{item.outcome}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a
|
||||
href={`/use-cases/${item.slug}/`}
|
||||
className="mt-6 inline-flex w-max items-center gap-2 rounded-full border border-primary/50 px-4 py-2 text-sm font-semibold text-primary transition-colors hover:bg-primary/10"
|
||||
>
|
||||
View playbook
|
||||
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
|
||||
</a>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
115
www/src/layouts/UseCaseIndexLayout.astro
Normal file
115
www/src/layouts/UseCaseIndexLayout.astro
Normal file
@@ -0,0 +1,115 @@
|
||||
---
|
||||
import '../styles/global.css';
|
||||
import { Header } from '../components/Header';
|
||||
import Footer from '../components/Footer.astro';
|
||||
|
||||
const {
|
||||
content: {
|
||||
title = 'Use Case',
|
||||
description = 'Explore how Gitea Mirror helps engineering teams stay resilient.',
|
||||
canonical = 'https://gitea-mirror.com/use-cases',
|
||||
}
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<title>{title} · Gitea Mirror</title>
|
||||
<meta name="description" content={description} />
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
<link rel="canonical" href={canonical} />
|
||||
<script is:inline>
|
||||
const theme = localStorage.getItem('theme') ||
|
||||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
|
||||
document.documentElement.classList.toggle('dark', theme === 'dark');
|
||||
</script>
|
||||
</head>
|
||||
<body class="min-h-screen bg-background text-foreground antialiased">
|
||||
<Header client:load />
|
||||
<main class="pt-24 pb-20">
|
||||
<article class="use-case-content mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<slot />
|
||||
</article>
|
||||
</main>
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<style is:global>
|
||||
.use-case-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
padding-top: 3rem;
|
||||
padding-bottom: 3rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1.75;
|
||||
}
|
||||
|
||||
.use-case-content > :is(h1, h2, h3) {
|
||||
font-weight: 700;
|
||||
color: var(--foreground);
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.use-case-content h1 {
|
||||
font-size: clamp(2rem, 3vw + 1rem, 2.75rem);
|
||||
}
|
||||
|
||||
.use-case-content h2 {
|
||||
font-size: clamp(1.5rem, 2.5vw + 0.75rem, 2.125rem);
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.use-case-content h3 {
|
||||
font-size: clamp(1.25rem, 1.5vw + 0.75rem, 1.5rem);
|
||||
}
|
||||
|
||||
.use-case-content p {
|
||||
margin: 0;
|
||||
color: var(--muted-foreground);
|
||||
}
|
||||
|
||||
.use-case-content ul,
|
||||
.use-case-content ol {
|
||||
padding-left: 1.5rem;
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
color: var(--muted-foreground);
|
||||
}
|
||||
|
||||
.use-case-content li::marker {
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.use-case-content pre {
|
||||
background-color: color-mix(in srgb, var(--muted) 70%, transparent);
|
||||
border-radius: 1rem;
|
||||
padding: 1rem 1.25rem;
|
||||
font-family: 'Fira Code', 'JetBrains Mono', ui-monospace, SFMono-Regular, monospace;
|
||||
font-size: 0.95rem;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.use-case-content code:not(pre code) {
|
||||
background-color: color-mix(in srgb, var(--muted) 70%, transparent);
|
||||
color: var(--foreground);
|
||||
padding: 0.1rem 0.35rem;
|
||||
border-radius: 0.4rem;
|
||||
font-size: 0.92em;
|
||||
}
|
||||
|
||||
.use-case-content a {
|
||||
color: color-mix(in srgb, var(--primary) 85%, var(--accent));
|
||||
font-weight: 600;
|
||||
text-decoration: underline;
|
||||
text-decoration-thickness: 2px;
|
||||
text-decoration-color: color-mix(in srgb, var(--primary) 50%, transparent);
|
||||
}
|
||||
|
||||
.use-case-content a:hover {
|
||||
text-decoration-color: var(--primary);
|
||||
}
|
||||
</style>
|
||||
@@ -32,4 +32,44 @@ export const useCases: UseCase[] = [
|
||||
outcome: 'The community script provisions the container, installs Bun, and wires persistence so mirroring works minutes after boot.',
|
||||
tags: ['Proxmox', 'Automation', 'Homelab'],
|
||||
},
|
||||
{
|
||||
slug: 'sync-github-to-self-hosted-gitea',
|
||||
title: 'Sync GitHub to Self-Hosted Gitea',
|
||||
summary: 'Run continuous mirrors so your homelab Gitea instance stays in lockstep with GitHub without manual pulls.',
|
||||
painPoint: 'Tinkerers want to keep a local Gitea in sync but `git pull --mirror` cron jobs break on metadata and new repos.',
|
||||
outcome: 'Gitea Mirror auto-discovers repos, syncs metadata, and respects intervals so your LAN copy matches upstream every hour.',
|
||||
tags: ['Continuous Sync', 'Self-Hosted', 'Homelab'],
|
||||
},
|
||||
{
|
||||
slug: 'preserve-github-history',
|
||||
title: 'Preserve GitHub History Forever',
|
||||
summary: 'Archive commit history, issues, and releases into Gitea so side projects survive account removals or repo deletion.',
|
||||
painPoint: 'Homelab archivists fear SaaS changes wiping years of work, but manual exports miss metadata and LFS assets.',
|
||||
outcome: 'Scheduled mirrors capture full history with metadata snapshots, giving you an air-gapped archive you control.',
|
||||
tags: ['Archival', 'Metadata', 'Homelab'],
|
||||
},
|
||||
{
|
||||
slug: 'github-backup-automation',
|
||||
title: 'Automate GitHub Backups',
|
||||
summary: 'Replace brittle scripts with policy-driven schedules, health checks, and alerts that keep your Git backups honest.',
|
||||
painPoint: 'Cron jobs and shell scripts fail silently, leaving you with stale mirrors when you need a restore most.',
|
||||
outcome: 'Gitea Mirror tracks sync status, retries failures, and exposes health endpoints so you can trust every backup window.',
|
||||
tags: ['Automation', 'Observability', 'Homelab'],
|
||||
},
|
||||
{
|
||||
slug: 'starred-repos-collection',
|
||||
title: 'Build a Starred Repo Collection',
|
||||
summary: 'Mirror starred GitHub projects into your own Gitea library so favorites stay browsable even when upstream disappears.',
|
||||
painPoint: 'Curators star dozens of repos but lose them when owners delete or rename, and there’s no offline copy.',
|
||||
outcome: 'The starred collector funnels every star into a dedicated Gitea org with metadata intact for long-term tinkering.',
|
||||
tags: ['Curation', 'Automation', 'Homelab'],
|
||||
},
|
||||
{
|
||||
slug: 'vendor-lock-in-prevention',
|
||||
title: 'Stay Ready to Leave GitHub',
|
||||
summary: 'Keep an always-current mirror so you can pivot from GitHub to self-hosted tooling whenever policies shift.',
|
||||
painPoint: 'Indie builders worry about pricing, auth changes, or ToS updates but lack a live fallback they can swap to instantly.',
|
||||
outcome: 'Continuous mirrors mean you can flip DNS to Gitea, keep working locally, and evaluate alternatives without downtime.',
|
||||
tags: ['Vendor Independence', 'Continuity', 'Homelab'],
|
||||
},
|
||||
];
|
||||
|
||||
67
www/src/pages/use-cases/github-backup-automation.mdx
Normal file
67
www/src/pages/use-cases/github-backup-automation.mdx
Normal file
@@ -0,0 +1,67 @@
|
||||
---
|
||||
layout: ../../layouts/UseCaseLayout.astro
|
||||
title: "Automate GitHub Backups"
|
||||
description: "Replace fragile cron scripts with scheduled mirrors, health checks, and alerts that keep GitHub backups trustworthy."
|
||||
canonical: "https://gitea-mirror.com/use-cases/github-backup-automation/"
|
||||
---
|
||||
|
||||
## Why automation beats cron
|
||||
|
||||
Shell scripts and `git clone --mirror` jobs work until they don’t—usually when GitHub rotates tokens, repositories rename, or metadata gets missed. Gitea Mirror centralizes scheduling, retries, and monitoring so your backups keep running while you sleep.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Gitea Mirror deployment with outbound HTTPS access
|
||||
- GitHub PAT + Gitea token stored in the UI or environment
|
||||
- Healthcheck endpoint (Healthchecks.io, Cronitor, Uptime Kuma) for alerts
|
||||
- Optional: Mailer or webhook destinations for failure notifications
|
||||
|
||||
## Step-by-step
|
||||
|
||||
### 1. Configure schedules centrally
|
||||
|
||||
1. Visit **Settings → Mirror Options**.
|
||||
2. Set the global interval (e.g. `30 minutes`).
|
||||
3. Use **Schedule windows** to run heavy syncs overnight (e.g. `02:00-05:00`).
|
||||
4. Override intervals per org/repo when you need faster protection for a critical project.
|
||||
|
||||
### 2. Turn on smart retries
|
||||
|
||||
- Under **Advanced**, enable **Backoff retries** so failed syncs retry with exponential delay.
|
||||
- Toggle **Stale sync alerts** to get warned when a repo hasn’t synced in your target window.
|
||||
- Set the failure threshold (for example, alert after 3 consecutive failures).
|
||||
|
||||
### 3. Wire in health monitoring
|
||||
|
||||
- Add a Healthchecks.io ping to the **Outgoing webhooks** field with `/api/health`.
|
||||
- If you self-host Uptime Kuma, create an HTTP check against `http://<mirror-host>:4321/api/health`.
|
||||
- Subscribe an email or webhook channel under **Notifications** for failure summaries.
|
||||
|
||||
### 4. Manage credentials safely
|
||||
|
||||
- Store tokens in the built-in secret storage rather than `.env` files on disk.
|
||||
- Turn on **Token expiry reminders** (set e.g. 30 days before the expiry) to rotate proactively.
|
||||
- Use GitHub fine-grained PATs per org to minimize blast radius.
|
||||
|
||||
### 5. Document recovery steps
|
||||
|
||||
- Save the `docker compose`/Helm/Proxmox commands you used in your homelab wiki.
|
||||
- Export the mirror configuration JSON (`/api/export`) monthly so you can rehydrate quickly.
|
||||
- Note which repos are excluded and why; auditors will ask.
|
||||
|
||||
## Validate automation
|
||||
|
||||
- Force a failure by revoking a PAT, confirm alerts fire, then restore the token.
|
||||
- Run `bun run manage-db check` (or the UI health check) to ensure migrations and tasks are clean.
|
||||
- Diff the last sync times via the dashboard CSV export.
|
||||
|
||||
## Best practices
|
||||
|
||||
- Group repos by criticality so you can assign tighter schedules where it matters.
|
||||
- Keep the mirror in the same timezone as your documentation to simplify scheduling.
|
||||
- Pair automation with the [Preserve GitHub History](../preserve-github-history/) playbook to maintain context, not just code.
|
||||
|
||||
## Related playbooks
|
||||
|
||||
- [Backup GitHub Repositories](../backup-github-repositories/)
|
||||
- [Run Gitea Mirror inside a Proxmox LXC](../proxmox-lxc-homelab/)
|
||||
@@ -1,61 +1,120 @@
|
||||
---
|
||||
layout: ../../layouts/UseCaseLayout.astro
|
||||
layout: ../../layouts/UseCaseIndexLayout.astro
|
||||
title: "Gitea Mirror Use Cases"
|
||||
description: "Discover the top workflows teams unlock with automated GitHub to Gitea mirroring."
|
||||
description: "Homelab-friendly playbooks that keep GitHub repos mirrored inside Gitea without promising enterprise guarantees."
|
||||
canonical: "https://gitea-mirror.com/use-cases/"
|
||||
---
|
||||
|
||||
import { ArrowRight, ShieldAlert, Sparkles, Home } from 'lucide-react';
|
||||
import { useCases } from '@/lib/use-cases';
|
||||
import { ArrowRight } from 'lucide-react';
|
||||
|
||||
<div class="mx-auto max-w-3xl px-4 text-center">
|
||||
<span class="inline-flex items-center rounded-full border px-3 py-1 text-xs font-semibold uppercase tracking-widest text-muted-foreground">
|
||||
Use Case Library
|
||||
</span>
|
||||
<h1 class="mt-6 text-3xl font-bold sm:text-4xl md:text-5xl">
|
||||
Operational playbooks for backup-ready engineering teams
|
||||
</h1>
|
||||
<p class="mt-4 text-base sm:text-lg text-muted-foreground">
|
||||
Each guide shows how to configure Gitea Mirror, schedule mirrors, and validate results so your team can ship with confidence.
|
||||
</p>
|
||||
</div>
|
||||
<section class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div class="rounded-3xl border border-primary/20 bg-gradient-to-br from-primary/10 via-background to-background p-8 sm:p-12 shadow-lg">
|
||||
<div class="flex flex-wrap items-center gap-3 text-xs font-semibold uppercase tracking-[0.25em] text-primary">
|
||||
<Sparkles class="h-4 w-4" />
|
||||
Built by and for homelab tinkerers
|
||||
</div>
|
||||
<h1 class="mt-6 text-3xl font-bold sm:text-4xl md:text-[2.75rem] md:leading-tight">
|
||||
Gitea Mirror in Action: Use Cases for Self-Hosted GitHub Backups
|
||||
</h1>
|
||||
<p class="mt-4 max-w-3xl text-base sm:text-lg text-muted-foreground">
|
||||
Gitea Mirror is an open-source side project. It’s perfect for your homelab, indie dev studio, or early-stage team that
|
||||
needs backups and optional failover. There’s <strong class="font-semibold text-foreground">no enterprise SLA</strong>—just
|
||||
practical playbooks you can own, fork, and improve.
|
||||
</p>
|
||||
|
||||
<div class="mx-auto mt-16 grid max-w-6xl gap-6 px-4 sm:gap-8">
|
||||
{useCases.map((useCase) => (
|
||||
<article class="group relative overflow-hidden rounded-3xl border bg-background/80 p-8 shadow-sm transition-all duration-300 hover:-translate-y-1 hover:shadow-lg">
|
||||
<div class="absolute inset-0 rounded-3xl bg-gradient-to-br from-primary/5 via-accent/5 to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100" />
|
||||
<div class="relative">
|
||||
<div class="flex flex-wrap items-center gap-3 text-xs font-medium uppercase tracking-wider text-muted-foreground">
|
||||
{useCase.tags.map((tag) => (
|
||||
<span class="inline-flex items-center rounded-full border border-muted px-3 py-1">
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
<div class="mt-6 grid gap-4 sm:grid-cols-2">
|
||||
<div class="flex items-start gap-3 rounded-2xl border border-muted bg-background/80 p-4">
|
||||
<div>
|
||||
<h2 class="!mt-0 text-sm font-semibold uppercase tracking-wide text-foreground/80">Ideal for</h2>
|
||||
<p class="mt-1 text-sm text-muted-foreground">
|
||||
Homelabbers, solo builders, and scrappy startups that want GitHub peace of mind without managed pricing.
|
||||
</p>
|
||||
</div>
|
||||
<h2 class="mt-6 text-2xl font-semibold sm:text-3xl">
|
||||
{useCase.title}
|
||||
</h2>
|
||||
<p class="mt-4 text-sm sm:text-base text-muted-foreground">
|
||||
{useCase.summary}
|
||||
</p>
|
||||
<div class="mt-6 grid gap-4 text-sm sm:text-base text-muted-foreground">
|
||||
<div>
|
||||
<h3 class="text-sm font-semibold uppercase tracking-wide text-foreground/80">Pain Point</h3>
|
||||
<p>{useCase.painPoint}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-sm font-semibold uppercase tracking-wide text-foreground/80">Outcome</h3>
|
||||
<p>{useCase.outcome}</p>
|
||||
</div>
|
||||
</div>
|
||||
<a
|
||||
href={`/use-cases/${useCase.slug}/`}
|
||||
class="mt-8 inline-flex items-center gap-2 text-sm font-semibold text-primary transition-colors hover:text-primary/80"
|
||||
>
|
||||
Read the playbook
|
||||
<ArrowRight class="h-4 w-4 transition-transform group-hover:translate-x-1" />
|
||||
</a>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
<div class="flex items-start gap-3 rounded-2xl border border-muted bg-background/80 p-4">
|
||||
<div>
|
||||
<h2 class="!mt-0 text-sm font-semibold uppercase tracking-wide text-foreground/80">Worth noting</h2>
|
||||
<p class="mt-1 text-sm text-muted-foreground">
|
||||
Community support only. No compliance guarantees, no 24/7 pager. Kick the tires before depending on it.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="use-cases" class="py-16 sm:py-24 px-4 sm:px-6 lg:px-8">
|
||||
<div class="max-w-7xl mx-auto">
|
||||
<div class="text-center max-w-3xl mx-auto mb-12 sm:mb-16">
|
||||
<span class="inline-flex items-center rounded-full border px-3 py-1 text-xs font-semibold uppercase tracking-widest text-muted-foreground mb-4">
|
||||
Use Cases
|
||||
</span>
|
||||
<h2 class="text-2xl sm:text-3xl md:text-4xl font-bold tracking-tight">
|
||||
Real-World Gitea Mirror Workflows
|
||||
</h2>
|
||||
<p class="mt-4 text-base sm:text-lg text-muted-foreground">
|
||||
Discover how developers and teams are using Gitea Mirror to create reliable, self-hosted backups of their GitHub repositories. These use cases provide step-by-step instructions for common scenarios.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-4 sm:gap-6 lg:gap-8 lg:grid-cols-3">
|
||||
{useCases.map((useCase) => (
|
||||
<article class="group relative flex flex-col rounded-2xl border bg-background/80 p-6 sm:p-8 shadow-sm transition-all duration-300 hover:-translate-y-1 hover:shadow-lg">
|
||||
<div class="absolute inset-0 rounded-2xl bg-gradient-to-br from-primary/5 via-accent/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
|
||||
<div class="relative flex flex-col h-full">
|
||||
<h3 class="text-xl font-semibold mb-3">
|
||||
{useCase.title}
|
||||
</h3>
|
||||
<p class="text-sm sm:text-base text-muted-foreground mb-4">
|
||||
{useCase.summary}
|
||||
</p>
|
||||
|
||||
<dl class="grid gap-3 text-sm sm:text-base text-muted-foreground">
|
||||
<div>
|
||||
<dt class="font-semibold text-foreground">Pain Point</dt>
|
||||
<dd>{useCase.painPoint}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="font-semibold text-foreground">Outcome</dt>
|
||||
<dd>{useCase.outcome}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
|
||||
<div class="mt-6 flex flex-wrap gap-2">
|
||||
{useCase.tags.map((tag) => (
|
||||
<span class="inline-flex items-center rounded-full border border-muted px-3 py-1 text-xs font-medium uppercase tracking-wide text-muted-foreground">
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<a
|
||||
href={`/use-cases/${useCase.slug}/`}
|
||||
class="mt-auto inline-flex items-center gap-2 pt-6 text-sm font-medium text-primary transition-colors hover:text-primary/80"
|
||||
>
|
||||
Read the playbook
|
||||
<ArrowRight class="h-4 w-4 transition-transform group-hover:translate-x-1" />
|
||||
</a>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mx-auto mt-16 max-w-7xl px-4 sm:px-6 lg:px-8 pb-8">
|
||||
<div class="rounded-3xl border border-primary/20 bg-primary/5 p-6 sm:p-10 text-center">
|
||||
<h2 class="text-2xl font-semibold sm:text-3xl">Have a niche workflow?</h2>
|
||||
<p class="mt-3 text-sm sm:text-base text-muted-foreground">
|
||||
Fork the project, open an issue, or drop a PR. These guides are community-made—just like the tooling behind them.
|
||||
</p>
|
||||
<a
|
||||
href="https://github.com/RayLabsHQ/gitea-mirror"
|
||||
class="mt-6 inline-flex items-center gap-2 rounded-full border border-primary/50 bg-background px-5 py-2 text-sm font-semibold text-primary transition-colors hover:bg-primary/10"
|
||||
>
|
||||
Contribute on GitHub
|
||||
<ArrowRight class="h-4 w-4" />
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
69
www/src/pages/use-cases/preserve-github-history.mdx
Normal file
69
www/src/pages/use-cases/preserve-github-history.mdx
Normal file
@@ -0,0 +1,69 @@
|
||||
---
|
||||
layout: ../../layouts/UseCaseLayout.astro
|
||||
title: "Preserve GitHub History Forever"
|
||||
description: "Archive commits, issues, releases, and LFS assets into Gitea so hobby projects survive account removals or repo deletions."
|
||||
canonical: "https://gitea-mirror.com/use-cases/preserve-github-history/"
|
||||
---
|
||||
|
||||
## Keep the entire story, not just the code
|
||||
|
||||
GitHub accounts get banned, repos go private, and owners rage-delete history. If you care about the full timeline—issues, releases, wiki—Gitea Mirror snapshots everything on a schedule so the story survives in your homelab.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Running Gitea Mirror (follow the [backup playbook](../backup-github-repositories/))
|
||||
- GitHub PAT with metadata scopes (`repo`, `read:org`)
|
||||
- Destination Gitea with enough disk for cloned repos + attachments
|
||||
- Optional: object storage or snapshots for long-term archiving of the mirror volume
|
||||
|
||||
## Step-by-step
|
||||
|
||||
### 1. Set archival-friendly defaults
|
||||
|
||||
In the admin UI under **Settings → Mirror Options**:
|
||||
|
||||
- Enable **Mirror metadata**.
|
||||
- Enable **Mirror releases** and **Mirror wiki**.
|
||||
- Turn on **Include attachments** so release assets and issue uploads copy across.
|
||||
|
||||
### 2. Create an "Archive" organization in Gitea
|
||||
|
||||
1. In Gitea, create an org like `github-archive` with read-only members.
|
||||
2. Back in Gitea Mirror, edit each owner and set the destination to the archive org.
|
||||
3. Enable **Lock mirrors** so accidental edits on the archive side are blocked.
|
||||
|
||||
### 3. Choose retention & cadence
|
||||
|
||||
- Set the global interval to `1h` for active projects or `12h` for dormant ones.
|
||||
- Configure **Snapshot retention** (for example `keep last 30`) so old mirror runs remain inspectable.
|
||||
- Schedule a weekly full sync window during off-hours to re-check metadata drift.
|
||||
|
||||
### 4. Record provenance
|
||||
|
||||
- Tag each archived repo in Gitea with the upstream URL and the first mirrored date.
|
||||
- Enable **Mirror webhooks** to push sync summaries into Matrix/Discord for auditing.
|
||||
- Export a CSV of repos quarterly as part of your homelab documentation.
|
||||
|
||||
### 5. Back up the backup
|
||||
|
||||
- Snapshots: Use ZFS/BTRFS or Proxmox backups on the mirror’s data volume.
|
||||
- Offsite: `restic`/`rclone` the `data/` directory to a NAS or object store.
|
||||
- Test: Restore to a test Gitea instance and spot-check history every few months.
|
||||
|
||||
## Verify the archive
|
||||
|
||||
1. Delete a draft issue on GitHub.
|
||||
2. Wait for the next sync; open the issue in Gitea—you should still see the original content.
|
||||
3. Compare `git tag -l` in both remotes to ensure releases match.
|
||||
4. Use `git lfs ls-files` to confirm large assets made it across.
|
||||
|
||||
## Maintenance checklist
|
||||
|
||||
- Rotate tokens annually and document the rotation date in the repo README.
|
||||
- Monitor disk growth; configure `persistence.size` if you run the Helm chart.
|
||||
- Log anomalies—failed runs, conflicts—in your homelab journal to track trends.
|
||||
|
||||
## Related playbooks
|
||||
|
||||
- [Automate GitHub Backups](../github-backup-automation/)
|
||||
- [Build a Starred Repo Collection](../starred-repos-collection/)
|
||||
61
www/src/pages/use-cases/starred-repos-collection.mdx
Normal file
61
www/src/pages/use-cases/starred-repos-collection.mdx
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
layout: ../../layouts/UseCaseLayout.astro
|
||||
title: "Build a Starred Repo Collection"
|
||||
description: "Mirror your starred GitHub projects into a dedicated Gitea library so favorites remain available offline."
|
||||
canonical: "https://gitea-mirror.com/use-cases/starred-repos-collection/"
|
||||
---
|
||||
|
||||
## Curate without losing projects
|
||||
|
||||
Stars are a personal library—but they vanish when creators delete repos or your account is rate limited. Gitea Mirror can automatically capture every starred repository into a dedicated Gitea organization, complete with issues and releases, so your inspiration lives on.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Gitea Mirror up and running (Docker, LXC, or Helm)
|
||||
- GitHub PAT for the account whose stars you want mirrored
|
||||
- Destination Gitea with a personal organization ready (e.g. `stars`)
|
||||
- Optional: DNS entry for the mirror so friends can browse the collection
|
||||
|
||||
## Step-by-step
|
||||
|
||||
### 1. Enable starred owner tracking
|
||||
|
||||
1. In the onboarding wizard (or later under **Settings → Owners**), add your GitHub username.
|
||||
2. Enable the **Include starred repositories** toggle.
|
||||
3. Set the destination in Gitea to a dedicated org, e.g. `stars-jamie`.
|
||||
|
||||
### 2. Categorize the collection
|
||||
|
||||
- Create sub-organizations in Gitea (e.g. `stars-iot`, `stars-ai`).
|
||||
- Use Destination Overrides inside the dashboard to route specific stars into themed orgs.
|
||||
- Tag repos in Gitea with labels like `language:rust`, `topic:homelab` for quick filtering.
|
||||
|
||||
### 3. Schedule incremental updates
|
||||
|
||||
- Set the star discovery interval to something light like `1h` so new stars import quickly.
|
||||
- Use the **Starred sync window** (e.g. `00:00-00:30`) to avoid interfering with org backups.
|
||||
- Turn on **Starred repo cleanup** if you want unstarred projects removed from the library.
|
||||
|
||||
### 4. Showcase the library
|
||||
|
||||
- Point a read-only Gitea user at the org so friends can browse without write access.
|
||||
- Host the Gitea instance behind a reverse proxy with HTTPS, then link it on your blog.
|
||||
- Export the repo list weekly and share it as a curated newsletter.
|
||||
|
||||
## Verify the collection works
|
||||
|
||||
1. Star a new repo on GitHub.
|
||||
2. Wait for the star interval or click **Sync now** in the dashboard.
|
||||
3. Confirm the repo appears in your `stars` org with issues/releases intact.
|
||||
4. Unstar it on GitHub; if cleanup is enabled, confirm it disappears on the next sync.
|
||||
|
||||
## Nice-to-haves
|
||||
|
||||
- Add a `README.md` in the Gitea org homepage explaining your tagging rules.
|
||||
- Pair with [Preserve GitHub History](../preserve-github-history/) so you keep metadata, not just code.
|
||||
- Use the [Helm deployment](../deploy-with-helm-chart/) if you want the collection available inside your cluster.
|
||||
|
||||
## Related playbooks
|
||||
|
||||
- [Backup GitHub Repositories](../backup-github-repositories/)
|
||||
- [Automate GitHub Backups](../github-backup-automation/)
|
||||
71
www/src/pages/use-cases/sync-github-to-self-hosted-gitea.mdx
Normal file
71
www/src/pages/use-cases/sync-github-to-self-hosted-gitea.mdx
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
layout: ../../layouts/UseCaseLayout.astro
|
||||
title: "Sync GitHub to Your Self-Hosted Gitea"
|
||||
description: "Keep a homelab Gitea instance continuously updated with GitHub by using Gitea Mirror's discovery, scheduling, and metadata sync."
|
||||
canonical: "https://gitea-mirror.com/use-cases/sync-github-to-self-hosted-gitea/"
|
||||
---
|
||||
|
||||
## Keep SaaS and self-hosted in lockstep
|
||||
|
||||
You may still collaborate on GitHub every day, yet want a LAN Gitea copy you control. Gitea Mirror bridges the two: it tracks owners, auto-discovers repos, mirrors metadata, and keeps a local instance only minutes behind upstream without hand-written cron jobs.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Gitea Mirror deployed (Docker, Proxmox LXC, or Helm)
|
||||
- GitHub PAT with `repo`, `read:org`, and `admin:org` scopes
|
||||
- Gitea API token for the target account/org
|
||||
- Stable connectivity between the mirror host and both GitHub + Gitea
|
||||
|
||||
## Step-by-step
|
||||
|
||||
### 1. Connect accounts in the admin wizard
|
||||
|
||||
1. Sign in at `http://<mirror-host>:4321`.
|
||||
2. Open **Settings → Connections**.
|
||||
3. Paste the GitHub PAT and choose the owners (user + orgs) you want mirrored.
|
||||
4. Add your self-hosted Gitea URL and token; pick the destination org structure (typically **Preserve structure**).
|
||||
|
||||
### 2. Enable continuous discovery
|
||||
|
||||
- Go to **Settings → Mirror Options** and toggle **Auto-discovery**.
|
||||
- Set the discovery interval (for example `15 minutes`) so new repositories, forks, and transfers sync automatically.
|
||||
- Optionally add a "Starred" owner to pull in personal favorites alongside org repos.
|
||||
|
||||
### 3. Configure sync cadence
|
||||
|
||||
Decide how far behind GitHub the mirror can lag:
|
||||
|
||||
- Global interval: start with `15 minutes` for active projects.
|
||||
- Use **Custom intervals** on specific orgs/repositories if you need faster mirrors (as low as 5 minutes).
|
||||
- Set a quiet window (e.g. `01:00-05:00`) for heavy metadata pulls to avoid daytime throttling.
|
||||
|
||||
### 4. Mirror metadata and LFS
|
||||
|
||||
Under **Repository defaults**:
|
||||
|
||||
- Enable **Mirror metadata** so issues, labels, and milestones stay in sync.
|
||||
- Enable **Mirror LFS** if your repos store binaries; confirm your Gitea instance has LFS enabled.
|
||||
- Turn on **Delete missing** only if you want Gitea to remove repos when they disappear upstream.
|
||||
|
||||
### 5. Validate the local mirror
|
||||
|
||||
- Select a repo in the dashboard and click **Sync now**.
|
||||
- In Gitea, verify commit history, tags, issues, and releases match GitHub.
|
||||
- Run a quick diff: `git remote add gitea http://<gitea>/<owner>/<repo>.git && git fetch gitea` then `git log origin/main..gitea/main` — it should be empty.
|
||||
|
||||
## Monitoring & alerts
|
||||
|
||||
- Check the **Activity** page for failed runs; set up Healthchecks.io/webhooks on the `/api/health` endpoint.
|
||||
- Enable email notifications so administrators learn about repeated failures or token expiry.
|
||||
- Export `/api/repos/:id/logs` periodically to archive sync history alongside the repos themselves.
|
||||
|
||||
## Tips for smooth syncing
|
||||
|
||||
- Avoid running more than one mirror against the same Gitea target; let Gitea Mirror manage the schedule centrally.
|
||||
- When restructuring orgs, pause auto-discovery, move repos in Gitea, then resume to prevent thrash.
|
||||
- Rate limits cropping up? Move the mirror onto a different IP or configure GitHub fine-grained PATs per org.
|
||||
|
||||
## Related playbooks
|
||||
|
||||
- [Backup GitHub Repositories](../backup-github-repositories/) for the base Docker deployment
|
||||
- [Run Gitea Mirror inside a Proxmox LXC](../proxmox-lxc-homelab/) if you want the mirror on a dedicated appliance
|
||||
61
www/src/pages/use-cases/vendor-lock-in-prevention.mdx
Normal file
61
www/src/pages/use-cases/vendor-lock-in-prevention.mdx
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
layout: ../../layouts/UseCaseLayout.astro
|
||||
title: "Stay Ready to Leave GitHub"
|
||||
description: "Use Gitea Mirror to keep an always-current fallback so policy or pricing changes at GitHub never stall your projects."
|
||||
canonical: "https://gitea-mirror.com/use-cases/vendor-lock-in-prevention/"
|
||||
---
|
||||
|
||||
## Keep your exit hatch open
|
||||
|
||||
GitHub can change pricing, authentication rules, or terms without notice. With Gitea Mirror running, you always have a live copy of code and metadata inside infrastructure you control—so switching to self-hosted Gitea, Forgejo, or something else becomes a DNS change, not a fire drill.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Production-ready Gitea instance (backed by your usual storage and TLS)
|
||||
- Gitea Mirror configured with owner discovery and metadata sync
|
||||
- Documentation of your current GitHub org structure (for validation)
|
||||
- Optional: reverse proxy + SSO for a smooth cutover experience
|
||||
|
||||
## Step-by-step
|
||||
|
||||
### 1. Mirror everything continuously
|
||||
|
||||
- Add every GitHub organization you care about as an owner in Gitea Mirror.
|
||||
- Enable **Preserve structure** so Gitea’s org layout matches GitHub.
|
||||
- Turn on metadata + LFS mirroring to ensure issues, releases, and binaries are ready on day one.
|
||||
|
||||
### 2. Simulate a cutover
|
||||
|
||||
1. Pick a pilot team.
|
||||
2. Ask them to work exclusively out of the Gitea mirror for a sprint.
|
||||
3. Capture feedback about permissions, webhooks, CI integrations, and adjust.
|
||||
|
||||
### 3. Keep integrations dual-homed
|
||||
|
||||
- Point your CI (e.g. Woodpecker, Jenkins) at both GitHub and Gitea using mirrored tokens.
|
||||
- Maintain matching webhook payloads so automation keeps running post-swap.
|
||||
- Mirror secrets (deploy keys, bot accounts) into the Gitea org to remove blockers.
|
||||
|
||||
### 4. Document the flip procedure
|
||||
|
||||
- Write a runbook: DNS updates, webhook changes, `git remote set-url` commands.
|
||||
- Version-control the document inside the mirror so updates stay in sync.
|
||||
- Rehearse twice a year; include steps to roll back to GitHub if needed.
|
||||
|
||||
### 5. Watch for drift
|
||||
|
||||
- Review the Gitea mirror weekly for newly created repos, teams, or permissions.
|
||||
- Parse the `/api/owners` endpoint to ensure auto-discovery still works.
|
||||
- Set alerts on the mirror’s activity log so you catch sync failures quickly.
|
||||
|
||||
## Success criteria
|
||||
|
||||
- A developer can change their `origin` remote to Gitea and push without errors.
|
||||
- CI pipelines succeed when pointed exclusively at the mirror.
|
||||
- All active repos have synced within your SLA (for example, last run < 2 hours ago).
|
||||
- The runbook includes contact info, rollback steps, and verification checklists.
|
||||
|
||||
## Related playbooks
|
||||
|
||||
- [Sync GitHub to Your Self-Hosted Gitea](../sync-github-to-self-hosted-gitea/)
|
||||
- [Deploy Gitea Mirror with the Helm Chart](../deploy-with-helm-chart/)
|
||||
Reference in New Issue
Block a user