Files
homelab/cluster/platform/harbor/REGISTRY_HTPASSWD_SETUP.md
2026-06-04 21:12:00 -05:00

3.8 KiB

Harbor Registry HTPASSWD Setup Instructions

Problem Fixed

The Harbor Helm chart requires TWO credential keys for registry authentication:

  • REGISTRY_PASSWD - plain text password
  • REGISTRY_HTPASSWD - bcrypt-hashed htpasswd format

Previously, only REGISTRY_PASSWD was configured, causing Harbor registry pod failures.

Solution Implemented

Option B: Pre-stored hash in 1Password

This approach was chosen because:

  1. Aligns with mk-labs pattern of storing credentials directly in 1Password
  2. More maintainable and predictable than template-based hashing
  3. Simpler to troubleshoot and validate
  4. No dependency on ExternalSecrets template engine capabilities

1Password Setup Required

Step 1: Generate the htpasswd hash

You need to generate a bcrypt hash of the registry password. The username must be harbor_registry_user.

Using Python (recommended):

python3 -c "import bcrypt; password=input('Enter registry password: '); print(f'harbor_registry_user:{bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=10)).decode()}')"

Using htpasswd tool (if available):

htpasswd -nbB harbor_registry_user <password>

Step 2: Add field to 1Password

  1. Open 1Password and navigate to: mk-labs vaultthe-seas item
  2. Add a new field:
    • Label: registry-htpasswd
    • Type: password/text field
    • Value: The full htpasswd line from Step 1
      • Example format: harbor_registry_user:$2b$10$abcd1234...

Step 3: Verify the configuration

The ExternalSecret has been updated to pull both fields:

- secretKey: REGISTRY_PASSWD
  remoteRef:
    key: the-seas
    property: registry-password

- secretKey: REGISTRY_HTPASSWD
  remoteRef:
    key: the-seas
    property: registry-htpasswd

Step 4: Apply and verify

After adding the field to 1Password:

# The ExternalSecret will automatically sync within 1h, or force sync:
kubectl delete externalsecret harbor-credentials -n harbor
kubectl apply -f /home/hermes/git/homelab/cluster/platform/harbor/externalsecret.yaml

# Verify the secret contains both keys:
kubectl get secret harbor-credentials -n harbor -o jsonpath='{.data}' | jq 'keys'

Expected output should include both:

  • REGISTRY_PASSWD
  • REGISTRY_HTPASSWD

Verification Commands

# Check if secret exists and has correct keys
kubectl get secret harbor-credentials -n harbor -o json | jq '.data | keys'

# Verify REGISTRY_HTPASSWD format (should show username:$2b$...)
kubectl get secret harbor-credentials -n harbor -o jsonpath='{.data.REGISTRY_HTPASSWD}' | base64 -d

# Check Harbor registry pod logs for authentication success
kubectl logs -n harbor -l component=registry --tail=50

Troubleshooting

ExternalSecret not syncing:

  • Check ExternalSecret status: kubectl describe externalsecret harbor-credentials -n harbor
  • Verify 1Password Connect is running: kubectl get pods -n external-secrets
  • Check that field name matches exactly: registry-htpasswd (lowercase, hyphen)

Hash format issues:

  • Ensure bcrypt hash starts with $2b$ or $2a$
  • Verify full line includes username: harbor_registry_user:<hash>
  • No extra whitespace or newlines in the 1Password field

Registry pod still failing:

  • Verify Harbor values.yaml references the correct existingSecret name
  • Check registry pod environment variables contain both keys
  • Review registry pod logs for specific authentication errors

Files Modified

  • /home/hermes/git/homelab/cluster/platform/harbor/externalsecret.yaml
    • Added REGISTRY_HTPASSWD secretKey mapping
    • Updated documentation comment with new field name

Reference

Harbor Helm Chart documentation: https://github.com/goharbor/harbor-helm/blob/main/values.yaml

Search for "REGISTRY_HTPASSWD" to see the requirement in the values.yaml file.