Repository Secrets
Nyl automatically discovers credentials from ArgoCD repository secrets to authenticate with private Git repositories. This enables seamless integration with private Helm charts and GitOps repositories.
Overview
Section titled “Overview”When Nyl encounters a Git URL in a HelmChart or ApplicationGenerator resource, it:
- Queries ArgoCD repository secrets from the
argocdnamespace - Matches the Git URL to an appropriate secret
- Uses the discovered credentials for authentication
- Falls back to SSH agent authentication if no secret matches
This approach provides:
- Zero configuration: Credentials are discovered automatically from existing ArgoCD secrets
- Security: Credentials remain in Kubernetes secrets, never in configuration files
- Consistency: Same credentials used by ArgoCD and Nyl
- Flexibility: Supports both SSH and HTTPS authentication
Secret Types
Section titled “Secret Types”ArgoCD supports two types of repository credential secrets, both of which are supported by Nyl:
Repository Secrets (Fine-Grained)
Section titled “Repository Secrets (Fine-Grained)”Repository secrets (argocd.argoproj.io/secret-type=repository) provide credentials for specific repositories using exact URL matching.
Example:
apiVersion: v1kind: Secretmetadata: name: myorg-charts-repo namespace: argocd labels: argocd.argoproj.io/secret-type: repositorytype: OpaquestringData: type: git # Only "git" type secrets are used (defaults to "git" if omitted) url: git@github.com:myorg/charts.git sshPrivateKey: | -----BEGIN OPENSSH PRIVATE KEY----- ... -----END OPENSSH PRIVATE KEY-----Use when:
- Managing credentials for individual repositories
- Need fine-grained access control
- Different credentials for different repos on same host
Repository Credential Templates (Scalable)
Section titled “Repository Credential Templates (Scalable)”Repository credential templates (argocd.argoproj.io/secret-type=repo-creds) provide credentials for multiple repositories matching a URL pattern.
Example:
apiVersion: v1kind: Secretmetadata: name: github-myorg-all namespace: argocd labels: argocd.argoproj.io/secret-type: repo-credstype: OpaquestringData: type: git # Only "git" type secrets are used (defaults to "git" if omitted) url: https://github.com/myorg/* username: myusername password: ghp_token123Pattern Examples:
https://github.com/myorg/*- All repos in organizationhttps://github.com/*- All GitHub reposgit@gitlab.com:*/*- All GitLab repos with org and repo
Use when:
- Managing many repositories from same provider
- Centralized credential management
- Single credential applies to multiple repos
Important: Both secret types must have type: git (or omit the type field, which defaults to git). Secrets with other types (e.g., helm, oci) are ignored.
Authentication Methods
Section titled “Authentication Methods”SSH Key Authentication
Section titled “SSH Key Authentication”SSH key authentication is the recommended method for private repositories.
Creating an SSH repository secret:
# Create secret with SSH private keykubectl create secret generic my-private-repo \ -n argocd \ --from-literal=url=git@github.com:myorg/charts.git \ --from-file=sshPrivateKey=$HOME/.ssh/id_rsa
# Label the secret for ArgoCDkubectl label secret my-private-repo \ -n argocd \ argocd.argoproj.io/secret-type=repositorySecret structure:
apiVersion: v1kind: Secretmetadata: name: my-private-repo namespace: argocd labels: argocd.argoproj.io/secret-type: repositorytype: Opaquedata: url: Z2l0QGdpdGh1Yi5jb206bXlvcmcvY2hhcnRzLmdpdA== # base64: git@github.com:myorg/charts.git sshPrivateKey: LS0tLS1CRUdJTi... # base64 encoded SSH private keyHTTPS Token Authentication
Section titled “HTTPS Token Authentication”HTTPS authentication uses personal access tokens or passwords.
Creating an HTTPS repository secret:
# Create secret with username and tokenkubectl create secret generic my-private-repo-https \ -n argocd \ --from-literal=url=https://github.com/myorg/charts.git \ --from-literal=username=myusername \ --from-literal=password=ghp_your_token_here
# Label the secret for ArgoCDkubectl label secret my-private-repo-https \ -n argocd \ argocd.argoproj.io/secret-type=repositorySecret structure:
apiVersion: v1kind: Secretmetadata: name: my-private-repo-https namespace: argocd labels: argocd.argoproj.io/secret-type: repositorytype: Opaquedata: url: aHR0cHM6Ly9naXRodWIuY29tL215b3JnL2NoYXJ0cy5naXQ= # base64: https://github.com/myorg/charts.git username: bXl1c2VybmFtZQ== # base64: myusername password: Z2hwX3lvdXJfdG9rZW5faGVyZQ== # base64: ghp_your_token_hereSSH Agent Fallback
Section titled “SSH Agent Fallback”If no ArgoCD secret matches a Git URL, Nyl automatically falls back to SSH agent authentication for SSH URLs:
# Start SSH agenteval "$(ssh-agent -s)"
# Add your SSH keyssh-add ~/.ssh/id_rsa
# Nyl will now use the SSH agent for authenticationnyl render my-chart.yamlURL Matching
Section titled “URL Matching”Nyl matches Git URLs to repository secrets using multiple strategies with specific precedence rules.
Credential Selection Precedence
Section titled “Credential Selection Precedence”When multiple secrets could apply to a repository, Nyl uses this precedence:
- Exact match (repository secret with exact URL match)
- Pattern match (repo-creds secret with matching pattern)
- Hostname fallback (repository secret with same hostname)
Example:
Given these secrets:
# 1. Exact match (highest precedence)apiVersion: v1kind: Secretmetadata: name: charts-exact namespace: argocd labels: argocd.argoproj.io/secret-type: repositorystringData: url: https://github.com/myorg/charts.git sshPrivateKey: | -----BEGIN OPENSSH PRIVATE KEY----- ...specific key for charts repo...
# 2. Pattern match (medium precedence)apiVersion: v1kind: Secretmetadata: name: myorg-pattern namespace: argocd labels: argocd.argoproj.io/secret-type: repo-credsstringData: url: https://github.com/myorg/* username: myuser password: ghp_token_for_myorg
# 3. Hostname fallback (lowest precedence)apiVersion: v1kind: Secretmetadata: name: github-fallback namespace: argocd labels: argocd.argoproj.io/secret-type: repositorystringData: url: https://github.com/other/repo.git username: myuser password: ghp_generic_tokenFor URL https://github.com/myorg/charts.git:
- Uses exact match (#1) ✅
For URL https://github.com/myorg/other-repo.git:
- No exact match
- Uses pattern match (#2) ✅
For URL https://github.com/different-org/repo.git:
- No exact match
- No pattern match
- Uses hostname fallback (#3) ✅
Exact Match
Section titled “Exact Match”The secret’s url field exactly matches the requested URL (after normalization):
# Secret URL (repository type)url: https://github.com/myorg/charts.git
# Matches- https://github.com/myorg/charts.git- https://github.com/myorg/charts # .git suffix optionalPattern Match
Section titled “Pattern Match”The secret’s url field contains wildcards (*) that match the requested URL:
# Secret URL (repo-creds type)url: https://github.com/myorg/*
# Matches- https://github.com/myorg/charts.git- https://github.com/myorg/other-repo.git- https://github.com/myorg/any-repo
# Does NOT match- https://github.com/otherorg/repo.git # Different organization- https://gitlab.com/myorg/repo.git # Different hostPattern Examples:
# Organization-level accessurl: https://github.com/myorg/*# Matches: https://github.com/myorg/repo1, https://github.com/myorg/repo2
# Host-level access (all repos on GitHub)url: https://github.com/*# Matches: https://github.com/anyorg/anyrepo
# SSH with patternurl: git@github.com:myorg/*# Matches: git@github.com:myorg/charts, git@github.com:myorg/other
# Multi-level wildcardurl: https://gitlab.com/*/*# Matches: https://gitlab.com/group/project, https://gitlab.com/org/repoHostname Fallback
Section titled “Hostname Fallback”If no exact or pattern match is found, Nyl matches by hostname. This allows a single repository secret to authenticate all repositories on the same host:
# Secret URL (repository type)url: https://github.com/myorg/charts.git
# Also matches (same hostname, no exact/pattern match)- https://github.com/myorg/other-repo.git- https://github.com/another-org/repo.gitURL Normalization
Section titled “URL Normalization”URLs are normalized before matching:
- Case-insensitive comparison
.gitsuffix is optional- SSH shorthand converted to full URL:
git@github.com:org/repo→ssh://git@github.com/org/repo
- Trailing slashes removed
This means these URLs are considered equivalent:
https://GitHub.com/MyOrg/Repo.githttps://github.com/myorg/repogit@github.com:myorg/repo(when matching SSH patterns)
Examples
Section titled “Examples”Private Helm Chart
Section titled “Private Helm Chart”apiVersion: nyl.niklasrosenstein.github.com/v1kind: HelmChartmetadata: name: my-app namespace: defaultspec: chart: repository: git+git@github.com:myorg/private-charts.git version: main name: charts/my-appNyl will:
- Look for ArgoCD secret with URL
git@github.com:myorg/private-charts.git - If not found, look for secret with hostname
github.com - If not found, try SSH agent
- Clone repository and extract chart from
charts/my-app
Private ApplicationGenerator
Section titled “Private ApplicationGenerator”apiVersion: argocd.nyl.niklasrosenstein.github.com/v1kind: ApplicationGeneratormetadata: name: microservicesspec: destination: server: https://kubernetes.default.svc namespace: argocd source: repoURL: https://github.com/myorg/gitops-repo.git targetRevision: main path: appsNyl will:
- Look for ArgoCD secret with URL
https://github.com/myorg/gitops-repo.git - If found, use credentials to clone repository
- Scan
apps/directory for application definitions - Generate ArgoCD
Applicationresources
Troubleshooting
Section titled “Troubleshooting”Authentication Failures
Section titled “Authentication Failures”Error: Authentication failed for git@github.com:myorg/repo.git: Failed to use SSH agent
Solutions:
- Create an ArgoCD repository secret with SSH key
- Start SSH agent and add your key:
ssh-add ~/.ssh/id_rsa - Verify SSH key has access to the repository
Error: No credentials found for repository: https://github.com/myorg/repo.git
Solutions:
- Create an ArgoCD repository secret for this URL
- Verify secret has label
argocd.argoproj.io/secret-type=repository - Check secret is in
argocdnamespace
Permission Issues
Section titled “Permission Issues”Error: Failed to query ArgoCD secrets: Forbidden
Solutions:
- Verify Nyl has RBAC permissions to read secrets in
argocdnamespace - Add ClusterRole/Role with
get,listpermissions on secrets - Bind role to Nyl service account
URL Matching Issues
Section titled “URL Matching Issues”If credentials aren’t being discovered:
- Check URL format matches between secret and chart
- Verify secret URL is normalized (lowercase, no trailing slash)
- Test with exact URL match before relying on hostname fallback
- Check secret has the correct label
Debugging
Section titled “Debugging”Enable debug logging to see credential discovery:
RUST_LOG=debug nyl render my-chart.yamlLook for log messages:
Discovering credentials from ArgoCD secretsFound credential for URL: ...No credential found, falling back to SSH agent
Best Practices
Section titled “Best Practices”- Use SSH keys: Preferred over HTTPS tokens for better security
- Choose the right secret type:
- Use
repo-credsfor organization-wide access (scalable) - Use
repositoryfor specific repos needing different credentials - Combine both types for flexibility with proper precedence
- Use
- Pattern-based credentials: Use
repo-credswith patterns likehttps://github.com/myorg/*to centrally manage credentials for multiple repositories - Leverage precedence: Use exact match
repositorysecrets to override broaderrepo-credspatterns for specific repos - Rotate credentials: Update secrets regularly and test after rotation
- Least privilege: Ensure SSH keys/tokens have minimal required permissions
- Monitor access: Review ArgoCD secret access logs periodically
- Document secrets: Maintain inventory of repository secrets, their patterns, and their purpose
Example Setup:
# 1. Organization-wide access (repo-creds)apiVersion: v1kind: Secretmetadata: name: github-myorg-default labels: argocd.argoproj.io/secret-type: repo-credsstringData: type: git url: https://github.com/myorg/* username: ci-bot password: ghp_org_token
---# 2. Specific repo with different credentials (repository)apiVersion: v1kind: Secretmetadata: name: sensitive-repo-override labels: argocd.argoproj.io/secret-type: repositorystringData: type: git url: https://github.com/myorg/sensitive-repo.git sshPrivateKey: | -----BEGIN OPENSSH PRIVATE KEY----- ...dedicated SSH key for sensitive repo...This setup provides:
- Default credentials for all
myorgrepositories via pattern match - Override with dedicated SSH key for
sensitive-repovia exact match - Separation of concerns and least privilege access
Kubernetes RBAC
Section titled “Kubernetes RBAC”Nyl requires these permissions to discover repository secrets:
apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: nyl-secret-readerrules:- apiGroups: [""] resources: ["secrets"] verbs: ["get", "list"] # Optionally scope to argocd namespace---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: name: nyl-secret-readersubjects:- kind: ServiceAccount name: nyl namespace: argocdroleRef: kind: ClusterRole name: nyl-secret-reader apiGroup: rbac.authorization.k8s.ioSecurity Considerations
Section titled “Security Considerations”- Credential storage: Secrets are stored in Kubernetes, encrypted at rest
- Access control: RBAC limits who can read repository secrets
- Credential scope: Each secret applies only to specific repositories
- No plaintext: Credentials never appear in logs or configuration files
- SSH keys: Use dedicated deploy keys with read-only access
- Token rotation: Update tokens/keys regularly and monitor for leaks