Skip to content

backups: redisBackupClientImage is committed as a bare tag, against the tag+digest rule #4264

Open

Description

@IvanHunters

Describe the bug

packages/system/backupstrategy-controller/values.yaml:57 commits a first-party image reference with a tag and no digest:

redisBackupClientImage: "ghcr.io/cozystack/cozystack/redis-backup:v1.6.0"

docs/agents/image-refs.md:45 rules that out in as many words: "Every first-party reference is tag+digest. A bare tag with no digest is not reproducible and must not be committed."

Environment

  • Cozystack: main

To Reproduce

$ git show origin/main:packages/system/backupstrategy-controller/values.yaml | grep -n redisBackupClientImage
57:  redisBackupClientImage: "ghcr.io/cozystack/cozystack/redis-backup:v1.6.0"

Expected behaviour

The committed value carries the digest the build stamps, as its two siblings in the same file do (chBackupClientImage, rabbitmqBackupClientImage).

Actual behaviour

Tag only. The pin is not reproducible: whatever v1.6.0 resolves to at pull time is what runs.

Additional context

This is not a missing producer. packages/system/backupstrategy-controller/Makefile:32-33 stamps the key with a digest on every build:

	IMAGE="$(REGISTRY)/redis-backup:$(IMAGE_TAG)@$$(yq e '."containerimage.digest"' images/redis-backup.json -o json -r)" \
		yq -i '.backupStrategyController.redisBackupClientImage = strenv(IMAGE)' values.yaml

So the build writes tag@sha256:… and the committed copy carries only the tag. It arrived that way in b0eb10427 (2026-08-28, the Redis driver) and has stayed.

Worth fixing beyond the rule itself: this exact line is what made the whole file drift in the image overlay, because the classifier recognised its siblings only through their @sha256: and had no branch for a suffixed key. #4261 fixes the classifier, so the overlay no longer depends on the digest being there — but the reference is still not reproducible, and the next reader has no way to tell which build v1.6.0 meant.

Checklist

  • I have checked the documentation
  • I have searched for similar issues
  • I have included all required information
  • I have provided clear steps to reproduce
  • I have included relevant logs

Activity

  1. added
    kind/bugCategorizes issue or PR as related to a bug
    triage/needs-triageIndicates an issue needs triage by a maintainer
    area/storageIssues or PRs related to storage (linstor, seaweedfs, bucket, velero, harbor)
    on Sep 15, 2026
  2. IvanHunters commented on Sep 15, 2026

    @IvanHunters
    CollaboratorAuthor

    Two things this issue understates.

    The tag does not exist. redis-backup publishes nightly tags and nothing else, so the committed reference does not merely lack a digest, it resolves to nothing:

    $ curl -s .../v2/cozystack/cozystack/redis-backup/tags/list
    {"name":"cozystack/cozystack/redis-backup","tags":[
      "0.0.0-nightly.20260911.34554132544.1","nightly",
      "0.0.0-nightly.20260912.34667295001.1",
      "0.0.0-nightly.20260913.34732721769.1",
      "0.0.0-nightly.20260914.34798944219.1"]}
    
    $ curl -sI .../redis-backup/manifests/v1.6.0   # not found
    $ curl -sI .../cozystack-api/manifests/v1.6.0  # control: answers with a digest
    docker-content-digest: sha256:c4d374a9bc5e6f6e66d24b29396f1eae9d7f06fd268ff767d05c45ca35e84e2e
    

    The control matters: the method finds a released first-party tag when there is one, so the empty answer for redis-backup is a fact about the registry rather than about the query.

    This changes what the fix is. Writing a digest beside the tag is not possible while nothing is published under it; the image needs a release tag first, and only then can the reference be pinned. Until that happens, any lane falling back to the committed reference cannot pull it at all.

    A second reference has the same shape, one step worse. packages/system/migration-controller/values.yaml:2:

    migrationController:
      image: "ghcr.io/cozystack/cozystack/migration-controller:latest"

    A floating tag is not merely unreproducible: it is a reference whose bytes change under a cluster that never asked for a new version. Anonymous pull of that repository is refused (HTTP 403 on the token endpoint) while cozystack-api is public, so it is either private or absent, and the committed fallback is unusable for the same reason as the one above.

    Both keys DO have a producer, which is worth stating because the sibling comment in packages/core/platform/Makefile describes a key that had none and froze at v1.4.0-rc.2. redisBackupClientImage is stamped by packages/system/backupstrategy-controller/Makefile and migrationController.image by packages/system/migration-controller/Makefile. So the stamp is fine and the committed value is the fallback used by every lane that does not rebuild the package, which is exactly where an unpublished or floating tag does its damage.

    Related: the bare-tag spelling of redisBackupClientImage is also what cost backupstrategy-controller its image overlay in e2e (#4257), because a key ending in Image with no digest read as a config change. That half is fixed in #4261; the pin itself is this issue.

  3. added
    triage/acceptedIndicates an issue is ready to be actively worked on
    priority/important-longtermImportant over the long term, but may not be staffed and/or may need multiple releases to complete
    and removed
    triage/needs-triageIndicates an issue needs triage by a maintainer
    on Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/storageIssues or PRs related to storage (linstor, seaweedfs, bucket, velero, harbor)kind/bugCategorizes issue or PR as related to a bugpriority/important-longtermImportant over the long term, but may not be staffed and/or may need multiple releases to completetriage/acceptedIndicates an issue is ready to be actively worked on

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions