Argo CD runs in the cluster and reconciles the GitOps repositories (homelabs and homelabs-private). Install the in-cluster manifests, then register applications through app-of-apps. Every private Git source needs repository credentials.
Install#
kubectl apply -k argocd
kubectl -n argocd get podsInitial admin password:
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -dReach the UI#
Service argocd-server is ClusterIP. There is no Cloudflare Public Hostname for Argo CD, and the UI does not use Dex. argocd-cm has no url or oidc.config; do not add an argocd Dex static client. Anyone who can kubectl already has cluster credentials.
Forward the HTTPS Service and accept the self-signed certificate in the browser:
kubectl -n argocd port-forward svc/argocd-server 8080:443Then open https://localhost:8080. Log in as admin with the initial admin secret above. The local admin account stays enabled.
The argocd CLI can use the same forward (argocd login localhost:8080 --insecure) or talk through your kubeconfig without a public URL (argocd login --core on a context that can reach namespace argocd).
Dex still publishes dex.<your-domain> for kubectl OIDC. That path does not log you into the Argo CD UI. Do not put Cloudflare Access in front of Dex; OIDC discovery and JWKS must stay reachable.
Repository authentication#
Argo CD needs credentials for every private Git repo used as a source. Without them, apps show ComparisonError: authentication required: Repository not found.
- Create a GitHub Personal Access Token (classic) with
reposcope. - For each private repo, create a repository secret. Replace placeholders:
kubectl create secret generic SECRET_NAME \
-n argocd \
--from-literal=type=git \
--from-literal=url=REPO_URL \
--from-literal=password=YOUR_GITHUB_TOKEN \
--from-literal=username=YOUR_GITHUB_USERNAME
kubectl label secret SECRET_NAME -n argocd argocd.argoproj.io/secret-type=repositoryRepos used by this setup:
| Secret name | Repo URL |
|---|---|
homelabs-private-repo | https://github.com/<owner>/homelabs-private.git |
website-repo | https://github.com/<owner>/website.git |
When adding an application that uses another private repo, extend the AppProject (argocd/projects/homelab.yaml) and create a matching repository secret.
Rotate an expired GitHub token#
When the PAT expires, applications fail with authentication errors. Recreate the secret (example for homelabs-private):
NEW_GITHUB_PAT=ghp_xxx
kubectl create secret generic homelabs-private-repo \
-n argocd \
--from-literal=type=git \
--from-literal=url=https://github.com/<owner>/homelabs-private.git \
--from-literal=password="${NEW_GITHUB_PAT}" \
--from-literal=username=YOUR_GITHUB_USERNAME \
-o yaml --dry-run=client | kubectl apply -f -The argocd.argoproj.io/secret-type=repository label is only needed on first create.
Single token for all repos under an owner#
Use a repository credentials secret for every repo under https://github.com/<owner>:
export NEW_GITHUB_PAT=ghp_xxx
export GITHUB_USERNAME=your-github-username
kubectl create secret generic github-repo-creds \
-n argocd \
--from-literal=url=https://github.com/<owner> \
--from-literal=username="${GITHUB_USERNAME}" \
--from-literal=password="${NEW_GITHUB_PAT}" \
-o yaml --dry-run=client | kubectl apply -f -
kubectl label secret github-repo-creds -n argocd argocd.argoproj.io/secret-type=repo-creds --overwriteWebsite image pull secret (GHCR)#
If the website image is private, the pull secret lives in homelabs-private/clusters/<cluster>/overlays/website/secret.yaml. Generate a base64 Docker config with a PAT that has read:packages:
echo -n '{"auths":{"ghcr.io":{"username":"USERNAME","password":"YOUR_GITHUB_PAT","auth":"'$(echo -n "USERNAME:YOUR_GITHUB_PAT" | base64 -w0)'"}}}' | base64 -w0On macOS, omit -w0 from base64. Paste the output into secret.yaml under data.dockerconfigjson.
Disable Git submodules (if needed)#
If a repo uses submodules (e.g. Hugo theme), disable submodule fetch in Argo CD:
kubectl patch configmap argocd-cmd-params-cm -n argocd --type merge -p '{"data":{"reposerver.enable.git.submodule":"false"}}'
kubectl rollout restart deployment argocd-repo-server -n argocdDeploy applications#
After repository authentication is configured, apply AppProject resources, then deploy app-of-apps (it discovers Application resources under clusters/<cluster>/argocd/applications/):
kubectl apply -k argocdkubectl apply -f clusters/<cluster>/argocd/app-of-apps.yamlDelete an application#
Remove the app definition from Git: clusters/<cluster>/argocd/applications/<app-name>.yaml, the app repo and destination entries from argocd/projects/homelab.yaml, and the optional overlay at clusters/<cluster>/overlays/<app-name>/. Then follow Argo CD app deletion.
Application tracking model#
This setup uses app-of-apps with <cluster>-apps creating child applications. Sync <cluster>-apps when changing files under clusters/<cluster>/argocd/applications/.