Skip to main content
RunBook Academy

Git, CI/CD & GitOpsXCVIII · Git Hosting FailureGitHostingFail

Mirror repositories and CDN — the read-only fallback

Advanced⏱ ~26 mingit

What you'll learn

  • Clone a mirror with git clone --mirror and explain why --mirror is the right primitive for the read-only fallback
  • Front the mirror with a CDN (Cloudflare, Fastly, CloudFront) for low-latency clones from any region
  • Configure the push-mirror sync that keeps the mirror current with the canonical remote
  • Distinguish the read-mirror use case (CI fetch, GitOps controller) from the failover clone use case (engineer push)
  • Measure the RPO of a mirror replicated every N minutes and identify the schedule that meets the design constraint

Prerequisites

Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x

Not yet marked complete on this device.

A read-only mirror is the deployment-side counterpart to the multi-remote failover pattern. Where Part XCVIII-02 covered how an engineer pushes during a forge outage, this lesson covers how CI, GitOps controllers, and deployment tooling read during the same outage. The mirror is a bare clone of the canonical remote that the deployment tooling fetches from; the CDN in front of the mirror gives low-latency clones from every region.

git clone --mirror https://github.com/acme/infra.git /srv/git/infra.git

git clone --mirror creates a bare repository with every ref, including remote-tracking branches, refs/remotes, and notes. The --mirror flag is what distinguishes this from git clone --bare, which creates a bare repository with the local branches only. The mirror’s refs are the same refs the canonical remote served at the moment of the clone.

flowchart LR
    A["canonical remote"] --> B["push-mirror sync"]
    B --> C["bare mirror /srv/git/infra.git"]
    C --> D["CDN edge"]
    D --> E["CI runner clone"]
    D --> F["GitOps controller fetch"]
    D --> G["engineer clone during outage"]

Why —mirror and not —bare

The two flags produce superficially similar results - a bare repository with no working tree - but the ref handling differs. git clone --bare sets up a bare repository with the local branches only; it does not configure any remote. A mirror created with --mirror includes every ref the remote advertised (branches, tags, notes, remote-tracking branches) and configures the fetch refspec and the canonical URL as the remote.

The practical difference: a --mirror clone is updated with a plain git fetch; a --bare clone has no remote configured and the fetch has to specify the URL and the refspec each time. --mirror is the production primitive; --bare is the academic primitive.

Fronting the mirror with a CDN

The mirror is read by CI runners, GitOps controllers, and deployment tooling in many regions. A single mirror in one region has a per-region latency penalty: a runner in ap-southeast-2 cloning a mirror in us-east-1 pays the trans-Pacific round-trip on every clone. A CDN fronts the mirror with edge caches that absorb the clone traffic and serve it from the closest edge.

The setup is a CDN (Cloudflare, Fastly, CloudFront) with origin pull pointing at the mirror’s hostname. The production discipline is to configure the CDN to not cache the authentication handshake: the smart-HTTP protocol sends an unauthenticated GET for the refs first and an authenticated POST for the negotiation, and only the GET is cacheable. The CDN URL is what the multi-remote failover from Part XCVIII-02 points at when the canonical is down.

Push-mirror sync

The mirror is kept current by one of two patterns: a push-mirror sync that the canonical remote pushes to, or a scheduled fetch that the mirror pulls from.

GitLab supports push-mirroring natively: the canonical remote is configured to push every commit to a second repository (GitLab calls this “push mirrors”). GitHub supports mirror repositories via the API and external services; Bitbucket supports mirror repositories at the repository level.

# Verify the push-mirror is current
cd /srv/git/infra.git
git fetch
git log --oneline -1

A scheduled fetch is the fallback when the canonical does not support push mirroring:

# Cron entry on the mirror host
*/5 * * * * cd /srv/git/infra.git && git fetch origin && date -u +%FT%TZ > /srv/git/infra.git/last-sync

The schedule period determines the RPO. A mirror synced every five minutes has an RPO of up to five minutes; a mirror synced every hour has an RPO of up to one hour. The RPO is the gap between the last successful sync and the disaster time.

The mirror vs the failover clone

The mirror and the failover clone serve different purposes and have different shapes:

  • Mirror. Read-only, served by a CDN, updated by push-mirror or scheduled fetch. The mirror is what CI and GitOps controllers fetch from. The mirror does not accept engineer pushes.
  • Failover clone. Writable, owned by the engineer, served by the multi-remote pattern from Part XCVIII-02. The failover clone is what the engineer pushes to when the canonical is down. The failover clone is not a CDN; it is a single clone on the engineer’s laptop or on a CI runner.

A team that conflates the two ends up with a mirror that engineers push to (which corrupts the read path) or a failover clone that CI fetches from (which fails every clone because the clone is single-tenant). The two patterns are complementary, not interchangeable.

# Mirror on the mirror host (read-only)
git clone --mirror https://github.com/acme/infra.git /srv/git/infra.git

# Failover clone on the engineer's laptop (writable)
git clone https://github.com/acme/infra.git ~/infra
git remote add backup https://backup.internal/acme/infra.git

Production discipline

  1. Use git clone --mirror, not git clone --bare, for the read-only fallback. The --mirror flag configures the fetch refspec and the remote; the --bare flag does not.
  2. Front the mirror with a CDN. A single mirror in one region has per-region latency; a CDN absorbs the clone traffic and serves from the closest edge.
  3. Match the sync period to the RPO design constraint. A sync period longer than the RPO is a sync that cannot meet the design constraint.
  4. Push-mirror when the canonical supports it, scheduled fetch when it does not. Push-mirror has a smaller RPO; scheduled fetch is the universal fallback.
  5. Verify the mirror is current before the failover flip. A mirror that has not been synced in a week is a mirror that fails the failover.

Cross-course references

  • Git, CI/CD & GitOps — Part XX-05 (Multiple Remotes) covers the multi-remote configuration this lesson’s CDN URL is plugged into.
  • Git, CI/CD & GitOps — Part XCVIII-02 (Multi-Remote Failover) is the engineer-side counterpart this lesson’s mirror is paired with.
  • GitOps with Argo CD — Part III (RepoAuth) covers the Argo CD repository URL configuration, which is exactly the CDN-fronted mirror URL this lesson produces.

Quiz

Knowledge check · 4 questions

  1. Q1. An operator wants to set up a read-only mirror that the deployment tooling can `git fetch` from. Which command is the right primitive?

  2. Q2. A read-only mirror synced every hour has an RPO of up to one hour, regardless of when the disaster strikes relative to the sync schedule.

  3. Q3. Explain why the mirror's RPO is bounded by the sync period, and what the team must change to reduce the RPO from one hour to fifteen minutes.

  4. Q4. Diagnose the RPO gap and recommend the mirror configuration.

    A team's deployment tooling fetches from a CDN-fronted mirror of the canonical remote. The mirror is synced every hour by a cron job. The team's RPO design constraint is fifteen minutes. A regional outage of the canonical remote has lasted forty-five minutes; the failover flip has switched CI and GitOps controllers to the CDN URL. CI jobs are running but some of them are pulling pack files that are missing commits pushed in the last thirty minutes.

Passing score: 75%. Answers are checked in this browser.