ArgoCD Setup

ArgoCD is the GitOps engine that drives the cluster. It is installed from the official Helm chart via kustomize, bootstrapped with a single kubectl apply, and then manages itself.


Bootstrap Process

flowchart TD
    A[1. Apply app-argocd.yaml] -->|creates| B[argocd-bootstrap Application]
    B -->|points to| C[kubernetes/bootstrap/]
    C -->|installs| D[ArgoCD Helm chart\n+ namespace + AppProject\n+ repo creds + secrets]
    D --> E[2. Apply ApplicationSets\nkubernetes/argocd/]
    E -->|generates| G[Application per app directory]
    G -->|syncs| H[All cluster workloads running]

    style A fill:#7c3aed,color:#fff
    style B fill:#ef652a,color:#fff
    style D fill:#ef652a,color:#fff
    style E fill:#7c3aed,color:#fff
    style G fill:#18b7be,color:#fff
    style H fill:#326ce5,color:#fff

Step 1: Apply the Bootstrap Application

bash
kubectl apply -f kubernetes/bootstrap/app-argocd.yaml

This creates the argocd-bootstrap Application, which points ArgoCD at kubernetes/bootstrap/ for its own installation manifests.

Step 2: ArgoCD Installs Itself

kubernetes/bootstrap/kustomization.yaml contains:

ResourcePurpose
namespace.yamlargocd namespace (privileged Pod Security labels)
appproject.yamlapps AppProject used by all generated Applications
externalsecret.yaml, externalsecret-custom.yamlArgoCD secrets from Infisical (Dex GitHub OAuth, GitHub App for notifications)
pitower-cluster-secret.yamlCluster Secret labelled home-ops/cluster: pitower, used by the ACK ApplicationSet's cluster generator
repo-creds-github.yaml, repo-creds-ghcr.yamlRepository credentials
argocd-values.yamlHelm values for the ArgoCD chart
kubernetes/bootstrap/kustomization.yaml
helmCharts:
  - name: argo-cd
    version: 10.9.6
    repo: https://argoproj.github.io/argo-helm
    releaseName: argocd
    namespace: argocd
    valuesFile: argocd-values.yaml

Step 3: Apply the ApplicationSets

The ApplicationSets are not managed by ArgoCD. Apply them by hand, and re-apply after editing:

bash
kubectl apply -f kubernetes/argocd/clusters/pitower.yaml
kubectl apply -f kubernetes/argocd/ack-applicationset.yaml

See ApplicationSets for what they generate.


Bootstrap Application

kubernetes/bootstrap/app-argocd.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: argocd-bootstrap
  namespace: argocd
spec:
  project: default
  source:
    repoURL: 'https://github.com/swibrow/home-ops.git'
    targetRevision: main
    path: kubernetes/bootstrap
  destination:
    server: 'https://kubernetes.default.svc'
    namespace: argocd
  ignoreDifferences:
    - group: ""
      kind: Secret
      name: argocd-secret
      namespace: argocd
      jsonPointers:
        - /data
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
      allowEmpty: true
    syncOptions:
      - CreateNamespace=true
      - ServerSideApply=true
      - RespectIgnoreDifferences=true

Notable Configuration

Key settings from argocd-values.yaml:

SettingValueWhy
global.domainargocd.wibrow.devServed via an HTTPRoute on envoy-external
timeout.reconciliation1800s (+300s jitter)Webhooks trigger syncs; polling is only a fallback
kustomize.buildOptions--enable-helm --load-restrictor LoadRestrictionsNoneLets apps inflate Helm charts and reference kubernetes/components
admin.enabledfalseLogin is SSO only, via Dex with the GitHub connector
rbac.policy.defaultrole:readonlyAdmin is granted explicitly in policy.csv
accounts.mcpapiKeyRead-only API account for the ToolHive ArgoCD MCP server
controller.diff.server.sidetrueServer-side diff
applicationsetcontroller.enable.progressive.syncstrueProgressive sync support

Notifications use a GitHub App (service.github); the default trigger is on-sync-status-unknown.


AppProject: apps

All ApplicationSet-generated Applications belong to the apps project:

yaml
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: apps
  namespace: argocd
spec:
  description: Apps
  sourceRepos:
    - https://github.com/swibrow/home-ops
    - public.ecr.aws/aws-controllers-k8s
  destinations:
    - namespace: "*"
      name: "*"
  clusterResourceWhitelist:
    - group: "*"
      kind: "*"
PropertyValueReason
sourceReposhome-ops and the ACK OCI registryWorkloads come from this repo; ACK uses a native Helm source
destinationsAll namespaces, all clustersApps can deploy anywhere
clusterResourceWhitelistAll groups, all kindsApps can create cluster-scoped resources (CRDs, ClusterRoles, etc.)

Project Structure Summary

flowchart TD
    subgraph "ArgoCD Projects"
        Default["default project"]
        AppsProj["apps project"]
    end

    Bootstrap["argocd-bootstrap\n(self-managing)"]
    AppSets["ApplicationSets\npitower, ack\n(applied manually)"]
    GenApps["Generated Applications\n(one per app directory)"]

    Default --> Bootstrap
    Bootstrap -->|installs ArgoCD +\ncreates apps project| AppsProj
    AppSets -->|generate| GenApps
    GenApps --> AppsProj

    style Default fill:#333,color:#fff
    style AppsProj fill:#7c3aed,color:#fff
    style Bootstrap fill:#ef652a,color:#fff
    style AppSets fill:#18b7be,color:#fff
    style GenApps fill:#326ce5,color:#fff
  • argocd-bootstrap lives in the built-in default project.
  • Applications generated by the pitower and ack ApplicationSets live in the apps project.