# GHCR Authentication 🔑 This guide explains how GitHub Container Registry (GHCR) authentication works for mirroring images via GitHub Actions. ## How Authentication Works 🔑 All workflows use `secrets.GITHUB_TOKEN` to log in to GHCR: ```yaml - name: Login to GHCR uses: docker/login-action@... with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} ``` No personal access token (PAT) or additional secrets are required. ## Why GITHUB_TOKEN Is the Correct Choice ✅ When a workflow runs in a public repository and pushes to GHCR using `GITHUB_TOKEN`, GitHub automatically: 1. Links the package to the repository. 2. Sets the package visibility to match the repository visibility (public → public). This means mirrored images are published as public packages without any additional configuration. ## Docker Hub Rate Limits 🐳 To avoid Docker Hub pull rate limits when mirroring images, configure the following optional secrets: | Name | Type | Description | |---|---|---| | `DOCKERHUB_USERNAME` | Secret | Docker Hub username | | `DOCKERHUB_TOKEN` | Secret | Docker Hub access token | These are used only for pulling source images from Docker Hub and are not required for GHCR authentication. ## Fork Pull Requests 🍴 Secrets are NOT available in `pull_request` workflows triggered by forks. This is a GitHub security restriction. The mirror workflow handles this transparently: - Fork PRs trigger a `pull_request_target` run with the base repository's trusted `GITHUB_TOKEN`. - That trusted run mirrors any new images needed by the fork. - The fork PR's CI then waits for those images to appear on GHCR before proceeding. ## Troubleshooting 🔧 If a push to GHCR fails with `denied: denied`: 1. Verify the workflow has `packages: write` in its `permissions` block. 2. Confirm the repository is public (private repositories require additional package visibility configuration). 3. Re-run the workflow after any permission or visibility changes.