Files
HomeAudit/IMAGE_PINNING_PLAN.md
admin 9ea31368f5 Complete Traefik infrastructure deployment - 60% complete
Major accomplishments:
-  SELinux policy installed and working
-  Core Traefik v2.10 deployment running
-  Production configuration ready (v3.1)
-  Monitoring stack configured
-  Comprehensive documentation created
-  Security hardening implemented

Current status:
- 🟡 Partially deployed (60% complete)
- ⚠️ Docker socket access needs resolution
-  Monitoring stack not deployed yet
- ⚠️ Production migration pending

Next steps:
1. Fix Docker socket permissions
2. Deploy monitoring stack
3. Migrate to production config
4. Validate full functionality

Files added:
- Complete Traefik deployment documentation
- Production and test configurations
- Monitoring stack configurations
- SELinux policy module
- Security checklists and guides
- Current status documentation
2025-08-28 15:22:41 -04:00

2.8 KiB

Image Pinning Plan

Purpose: eliminate non-deterministic :latest pulls and ensure reproducible deployments across hosts by pinning images to immutable digests. This plan uses a digest lock file generated from currently running images on each host, then applies those digests during deployment.

Why digests instead of tags

  • Tags can move; digests are immutable
  • Works even when upstream versioning varies across services
  • Zero guesswork about "which stable version" for every image

Scope (from audit)

The audit flagged many containers using :latest (e.g., portainer, watchtower, duckdns, paperless-ai, mosquitto, vaultwarden, zwave-js-ui, n8n, esphome, dozzle, uptime-kuma, several AppFlowy images, and others across omv800, jonathan-2518f5u, surface, lenovo420, audrey, fedora). We will pin all images actually in use on each host, not just those tagged :latest.

Deliverables

  • migration_scripts/scripts/generate_image_digest_lock.sh: Gathers the exact digests for images running on specified hosts and writes a lock file.
  • image-digest-lock.yaml: Canonical mapping of image:tag -> image@sha256:<digest> per host.

Usage

  1. Generate the lock file from one or more hosts (requires SSH access):
bash migration_scripts/scripts/generate_image_digest_lock.sh \
  --hosts "omv800 jonathan-2518f5u surface fedora audrey lenovo420" \
  --output /opt/migration/configs/image-digest-lock.yaml
  1. Review the lock file:
cat /opt/migration/configs/image-digest-lock.yaml
  1. Apply digests during deployment:
  • For Swarm stacks and Compose files in this repo, prefer the digest form: repo/image@sha256:<digest> instead of repo/image:tag.
  • When generating stacks from automation, resolve image:tag via the lock file before deploying. If a digest is present for that image:tag, replace with the digest form. If not present, fail closed or explicitly pull and lock.

Rollout Strategy

  • Phase A: Lock currently running images to capture a consistent baseline per host.
  • Phase B: Update internal Compose/Stack definitions to use digests for critical services first (DNS, HA, Databases), then the remainder.
  • Phase C: Integrate lock resolution into CI/deploy scripts so new services automatically pin digests at deploy time.

Renewal Policy

  • Regenerate the lock weekly or on change windows:
bash migration_scripts/scripts/generate_image_digest_lock.sh --hosts "..." --output /opt/migration/configs/image-digest-lock.yaml
  • Only adopt updated digests after services pass health checks in canary.

Notes

  • You can still keep a human-readable tag alongside the digest in the lock for context.
  • For images with strict vendor guidance (e.g., Home Assistant), prefer vendor-recommended channels (e.g., stable, lts) but still pin by digest for deployment.