What's Actually Happening
Flux CD GitRepository resource is not syncing with the Git repository. Source controller fails to fetch or clone the repository.
The Error You'll See
```bash $ flux get sources git
Name Ready Status my-repo False failed to clone: authentication required
$ kubectl get gitrepository my-repo -n flux-system NAME URL READY STATUS my-repo https://github.com/org/repo.git False authentication failed ```
SSH key error:
failed to clone ssh://git@github.com/org/repo.git: ssh: handshake failedTLS error:
failed to clone https://github.com/org/repo.git: x509: certificate signed by unknown authorityTimeout error:
failed to clone: context deadline exceededWhy This Happens
- 1.Missing credentials - Secret with Git credentials not created
- 2.Wrong secret reference - GitRepository references wrong secret
- 3.SSH key invalid - SSH private key not valid or not added to Git
- 4.HTTPS auth failed - Username/password or token incorrect
- 5.Network issues - Cannot reach Git server
- 6.TLS certificate issue - Self-signed or expired certificate
Step 1: Check GitRepository Status
```bash # List GitRepositories: flux get sources git -A
# Get GitRepository details: kubectl get gitrepository -A
# Check specific repository: kubectl get gitrepository my-repo -n flux-system -o yaml
# Describe repository: kubectl describe gitrepository my-repo -n flux-system
# Check artifact status: kubectl get gitrepository my-repo -n flux-system -o jsonpath='{.status.artifact}'
# Check last sync time: kubectl get gitrepository my-repo -n flux-system -o jsonpath='{.status.lastAutomationRunTime}'
# View conditions: kubectl get gitrepository my-repo -n flux-system -o jsonpath='{.status.conditions}'
# Check for error message: kubectl get gitrepository my-repo -n flux-system -o jsonpath='{.status.conditions[?(@.type=="Ready")].message}' ```
Step 2: Check Source Controller
```bash # Check Flux source controller: kubectl get deploy -n flux-system
# Check pods: kubectl get pods -n flux-system | grep source
# Check pod logs: kubectl logs -n flux-system deploy/source-controller
# Check for Git errors: kubectl logs -n flux-system deploy/source-controller | grep -i "git|clone|fetch"
# Check recent errors: kubectl logs -n flux-system deploy/source-controller --tail=50
# Check events: kubectl get events -n flux-system --sort-by='.lastTimestamp'
# Check source controller resources: kubectl top pods -n flux-system | grep source ```
Step 3: Verify Secret Reference
```bash # Check secret reference in GitRepository: kubectl get gitrepository my-repo -n flux-system -o yaml | grep -A5 secretRef
# Look for: # spec: # secretRef: # name: git-credentials
# Check if secret exists: kubectl get secret git-credentials -n flux-system
# If secret missing, check what Flux expects: flux get sources git my-repo -n flux-system
# Describe secret: kubectl describe secret git-credentials -n flux-system
# Check secret namespace matches: # GitRepository and secret must be in same namespace # Or use .spec.secretRef.namespace
# If secretRef is wrong, patch: kubectl patch gitrepository my-repo -n flux-system --type='merge' \ -p '{"spec":{"secretRef":{"name":"correct-secret-name"}}}' ```
Step 4: Check SSH Credentials
```bash # Check SSH secret: kubectl get secret git-ssh-key -n flux-system -o yaml
# Should have: # data: # identity: <base64-encoded-private-key> # identity.pub: <base64-encoded-public-key> # known_hosts: <base64-encoded-known_hosts>
# Verify SSH key format: kubectl get secret git-ssh-key -n flux-system \ -o jsonpath='{.data.identity}' | base64 -d | head -1 # Should be: -----BEGIN OPENSSH PRIVATE KEY----- # Or: -----BEGIN RSA PRIVATE KEY-----
# Check known_hosts: kubectl get secret git-ssh-key -n flux-system \ -o jsonpath='{.data.known_hosts}' | base64 -d
# Must include GitHub/GitLab SSH host key: # github.com ssh-rsa AAAAB3...
# Get GitHub known_hosts: ssh-keyscan github.com | base64 -w 0
# Create SSH secret: flux create secret git git-ssh-key \ --namespace flux-system \ --url ssh://git@github.com/org/repo.git \ --private-key-file=./id_rsa
# Or manually: kubectl create secret generic git-ssh-key -n flux-system \ --from-file=identity=./id_rsa \ --from-file=identity.pub=./id_rsa.pub \ --from-file=known_hosts=./known_hosts.txt ```
Step 5: Check HTTPS Credentials
```bash # Check HTTPS secret: kubectl get secret git-https-auth -n flux-system -o yaml
# Should have: # data: # username: <base64-encoded-username> # password: <base64-encoded-password-or-token>
# Decode and verify: kubectl get secret git-https-auth -n flux-system \ -o jsonpath='{.data.username}' | base64 -d kubectl get secret git-https-auth -n flux-system \ -o jsonpath='{.data.password}' | base64 -d
# Create HTTPS secret with token: flux create secret git git-https-auth \ --namespace flux-system \ --url https://github.com/org/repo.git \ --username git \ --password <personal-access-token>
# Or manually: kubectl create secret generic git-https-auth -n flux-system \ --from-literal=username=git \ --from-literal.password=<token>
# Test credentials manually: git clone https://<token>@github.com/org/repo.git /tmp/test-clone ```
Step 6: Test Git Connectivity
```bash # From source controller pod, test connectivity:
# Get source controller pod: kubectl get pods -n flux-system -l app=source-controller
# Exec into pod: kubectl exec -n flux-system deploy/source-controller -it -- sh
# Test HTTPS: curl -I https://github.com/org/repo.git
# Test SSH (if SSH configured): ssh -T git@github.com # Or for GitLab: ssh -T git@gitlab.com
# Check DNS: nslookup github.com
# Check network policies: kubectl get networkpolicy -n flux-system
# If network policy blocks, add rule to allow GitHub: apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-git namespace: flux-system spec: podSelector: matchLabels: app: source-controller policyTypes: - Egress egress: - to: - ipBlock: cidr: 0.0.0.0/0 ports: - port: 443 - port: 22 ```
Step 7: Check TLS Certificates
```bash # If using self-hosted Git with self-signed cert:
# Check if secret has ca.crt: kubectl get secret git-credentials -n flux-system -o yaml | grep ca.crt
# Add CA certificate to secret: kubectl create secret generic git-ca-cert -n flux-system \ --from-file=ca.crt=./git-server-ca.crt
# Reference in GitRepository: apiVersion: source.toolkit.fluxcd.io/v1 kind: GitRepository metadata: name: my-repo spec: url: https://git.internal.company.com/org/repo.git secretRef: name: git-ca-cert # CA cert used for TLS verification
# Or disable TLS verification (not recommended): kubectl patch gitrepository my-repo -n flux-system --type='merge' \ -p '{"spec":{"verify":{"secretRef":{"name":"git-ca-cert"}}}}'
# For insecure skip (development only): # Add ca.crt with empty value to skip verification ```
Step 8: Check Repository URL
```bash # Verify repository URL: kubectl get gitrepository my-repo -n flux-system -o jsonpath='{.spec.url}'
# Correct URLs: # HTTPS: https://github.com/org/repo.git # SSH: ssh://git@github.com/org/repo.git # GitLab: https://gitlab.com/org/repo.git
# Common URL errors:
# Wrong protocol (ssh:// missing): git@github.com:org/repo.git # Wrong ssh://git@github.com/org/repo.git # Correct
# Missing .git extension: https://github.com/org/repo # May fail https://github.com/org/repo.git # Correct
# Wrong branch: kubectl get gitrepository my-repo -n flux-system -o jsonpath='{.spec.ref}'
# Fix URL: kubectl patch gitrepository my-repo -n flux-system --type='merge' \ -p '{"spec":{"url":"ssh://git@github.com/org/repo.git"}}'
# Check ref (branch, tag, commit): kubectl patch gitrepository my-repo -n flux-system --type='merge' \ -p '{"spec":{"ref":{"branch":"main"}}}' ```
Step 9: Force Reconciliation
```bash # Trigger manual reconciliation: flux reconcile source git my-repo -n flux-system
# With force: flux reconcile source git my-repo -n flux-system --force
# Via kubectl annotation: kubectl annotate gitrepository my-repo -n flux-system \ fluxcd.io/reconcileAt="$(date +%s)" --overwrite
# Check reconciliation result: flux get sources git my-repo -n flux-system
# Check artifact created: kubectl get gitrepository my-repo -n flux-system -o jsonpath='{.status.artifact.path}'
# Verify artifact in source controller: kubectl exec -n flux-system deploy/source-controller -- \ ls -la /data/gitrepository/flux-system/my-repo/ ```
Step 10: Flux GitRepository Verification Script
```bash # Create verification script: cat << 'EOF' > /usr/local/bin/check-flux-git.sh #!/bin/bash
REPO=${1:-"my-repo"} NS=${2:-"flux-system"}
echo "=== GitRepository Status ===" flux get sources git $REPO -n $NS
echo "" echo "=== Repository Details ===" kubectl get gitrepository $REPO -n $NS -o yaml | grep -A10 "spec:" kubectl get gitrepository $REPO -n $NS -o yaml | grep -A10 "status:"
echo "" echo "=== Secret Reference ===" kubectl get gitrepository $REPO -n $NS -o yaml | grep -A3 "secretRef"
echo "" echo "=== Secrets ===" kubectl get secrets -n $NS | grep git
echo "" echo "=== Source Controller Logs ===" kubectl logs -n $NS deploy/source-controller --tail=20 | grep -i "git|clone|fetch|error"
echo "" echo "=== Source Controller Pods ===" kubectl get pods -n $NS -l app=source-controller
echo "" echo "=== Events ===" kubectl get events -n $NS --sort-by='.lastTimestamp' | grep -i git | tail -10
echo "" echo "=== Test Reconciliation ===" flux reconcile source git $REPO -n $NS 2>&1 | head -10
echo "" echo "=== Recommendations ===" echo "1. Ensure secret exists with correct credentials" echo "2. Verify secretRef points to correct secret" echo "3. Check SSH key or token is valid" echo "4. Verify repository URL is correct" echo "5. Test connectivity from source controller pod" echo "6. Check TLS certificates for self-hosted Git" echo "7. Force reconciliation to retry sync" EOF
chmod +x /usr/local/bin/check-flux-git.sh
# Usage: /usr/local/bin/check-flux-git.sh my-repo flux-system ```
Flux GitRepository Checklist
| Check | Expected |
|---|---|
| Source controller pod | Running |
| Secret exists | git-credentials in namespace |
| Secret reference | matches secret name |
| SSH key valid | Known_hosts configured |
| HTTPS token valid | Works with git clone |
| URL correct | ssh:// or https:// format |
| Connectivity | Can reach Git server |
Verify the Fix
```bash # After fixing Flux GitRepository sync
# 1. Check repository ready flux get sources git my-repo -n flux-system // Ready: True
# 2. Check artifact kubectl get gitrepository my-repo -n flux-system // Artifact: .tar.gz created
# 3. Check last sync kubectl get gitrepository my-repo -n flux-system -o yaml // Last sync time updated
# 4. Force reconciliation flux reconcile source git my-repo -n flux-system // Succeeds without error
# 5. Check source controller logs kubectl logs -n flux-system deploy/source-controller --tail=10 // No errors
# 6. Verify Kustomization works flux get kustomizations -A // Uses synced repository ```
Related Issues
- [Fix Flux Reconciliation Failed](/articles/fix-flux-reconciliation-failed)
- [Fix Flux Kustomization Drift](/articles/fix-flux-kustomization-drift)
- [Fix ArgoCD Application Not Syncing](/articles/fix-argocd-application-not-syncing)