Files
plex-playlist/docs/SECURE_DOCKER_CICD.md
Xlorep DarkHelm 9b742a5a6d
Some checks failed
CICD Start / Sanity and Base Decision (push) Successful in 18s
Renovate Dependency Updates / Renovate Dependencies (push) Failing after 7m19s
feature/pp-58-runtime-image-contract (#68)
## Summary

This PR tightens repository quality enforcement around markdown and documentation. It adds `markdownlint` to the `cicd-checks` workflow, expands pre-commit coverage so markdown files are checked repo-wide, and cleans up the PP-58 documentation set to keep it aligned with the new policy.

## What changed

- Added a `Markdownlint Check` entry to `.gitea/workflows/cicd-checks.yaml`
- Added `markdownlint` to pre-commit and widened prettier coverage to include markdown files across the repo
- Updated `README.md` to satisfy markdownlint line-length rules
- Normalized the PP-58 documentation set:
  - `docs/DEPLOYABLE_RUNTIME_CONTRACT.md`
  - `docs/adr/ADR003-deployable_runtime_image_contract.md`
  - `docs/DEVELOPMENT.md`
  - `docs/CICD_MULTI_STAGE_BUILD.md`
  - `docs/CICD_TROUBLESHOOTING_GUIDE.md`
  - `docs/SECURE_DOCKER_CICD.md`

## Validation

- `pre-commit run markdownlint --files README.md docs/DEPLOYABLE_RUNTIME_CONTRACT.md`
- `pre-commit run prettier --files README.md docs/DEPLOYABLE_RUNTIME_CONTRACT.md`
- Workflow YAML validation returned no errors

## Notes

This change does not alter application runtime behavior. It only strengthens CI and documentation quality enforcement.

Co-authored-by: copilotcoder <copilotcoder@darkhelm.org>
Reviewed-on: #68
2026-06-19 17:00:57 -04:00

3.1 KiB

Secure Docker CI/CD with BuildKit Secrets

This document explains how our CI/CD pipeline securely handles SSH keys using Docker BuildKit secrets.

🔒 Security Benefits

Before (Insecure)

ARG SSH_PRIVATE_KEY
RUN echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
  • SSH key stored in Docker image layers
  • Visible in docker history
  • Can be extracted from images
  • Security vulnerability

After (Secure)

RUN --mount=type=secret,id=ssh_private_key \
    cp /run/secrets/ssh_private_key ~/.ssh/id_rsa && \
    # ... use key ... && \
    rm -rf ~/.ssh
  • SSH key never stored in image layers
  • Not visible in docker history
  • Cannot be extracted from final image
  • Secure by design

🏗️ CI/CD Pipeline Implementation

Gitea Actions Workflow

The CI workflow files under .gitea/workflows/ now use:

  1. Docker BuildKit Enabled

    export DOCKER_BUILDKIT=1
    
  2. Secure Secret Mounting

    # Create temporary SSH key file
    echo "${SSH_PRIVATE_KEY}" > /tmp/ssh_key
    chmod 600 /tmp/ssh_key
    
    # Build with secret mount
    docker build -f Dockerfile.cicd \
      --secret id=ssh_private_key,src=/tmp/ssh_key \
      -t cicd:latest .
    
    # Clean up immediately
    rm -f /tmp/ssh_key
    

Local Development

Use the secure build script:

./scripts/build-cicd-secure.sh plex-playlist-cicd:latest

🔧 Required Setup

1. Gitea Secrets Configuration

Ensure these secrets are configured in your Gitea repository:

  • SSH_PRIVATE_KEY: Your private SSH key for git operations
  • GITEA_TOKEN: Token for pushing to container registry

2. Docker BuildKit Support

  • Gitea Actions: Automatically enabled with DOCKER_BUILDKIT=1
  • Local builds: Requires Docker 18.09+ with BuildKit enabled
  • CI runners: Ensure BuildKit support in your runner environment

📋 Best Practices Applied

  1. Temporary Files: SSH keys are written to temporary files and immediately removed
  2. File Permissions: SSH keys get proper 600 permissions
  3. Multi-stage Security: Keys are cleaned up within the same RUN command
  4. No ARG Secrets: Never pass secrets via build arguments
  5. Dockerignore Protection: .dockerignore prevents accidental secret inclusion

🧪 Testing Security

Verify no secrets in image:

# Build the image
./scripts/build-cicd-secure.sh test-image

# Check history (should show no secrets)
docker history test-image

# Try to find SSH keys (should find none)
docker run --rm test-image find / -name "*rsa*" -o -name "*ssh*" 2>/dev/null

🚀 Migration Checklist

  • Updated Dockerfile.cicd to use --mount=type=secret
  • Removed insecure ARG SSH_PRIVATE_KEY
  • Modified CI/CD workflow to use BuildKit secrets
  • Added .dockerignore patterns for SSH keys
  • Created secure build script
  • Documented security improvements

📚 References